大家好,我是带我去滑雪!
在前一篇文章中,笔者爬取了东方财富网上证指数股吧的495775条评论数据,并对文本进行了情感分析,基于自制的股票情感词典,使用了深度学习模型对爬取的文本数据进行分类标注,将正向文本标注为1,将负向文本标注为-1,将同一天的不同时段的文本标注进行加总,得到该天的情绪指数,而上证指数的收盘价格利用python获取,数据展示如下:
由于情绪指数与上证指数的数值差距较大,后续将情绪指数总体加上2500,使其达到同一水平。下面利用数据构建VAR模型,开始代码实战。
目录
(1)导入模块
import statsmodels.api as sm
import statsmodels.stats.diagnostic
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from statsmodels.tsa.stattools import adfuller as ADF
from statsmodels.tsa.stattools import grangercausalitytests
plt.rcParams ['font.sans-serif'] ='SimHei' #显示中文
plt.rcParams ['axes.unicode_minus']=False
(2)导入数据
# 读取数据
train_data = pd.read_csv(r'E:\工作\硕士\博客\博客粉丝问题\情绪指数与上证指数VAR模型\data.csv',encoding="ANSI")
# 确保数据是数值型
train_data['情绪指数'] = pd.to_numeric(train_data['情绪指数'], errors='coerce')
train_data['上证指数'] = pd.to_numeric(train_data['上证指数'], errors='coerce')
# 填补或移除缺失值
train_data.dropna(inplace=True)
(3)平稳性检验
def check_station(train_data, column, alpha=0.05):
"""
参数说明:
train_data:原始数据
column:要检验的列
alpha:置信区间,默认为0.05
返回结果:
返回原始数据折线图、平稳性检验结果
"""
data_series = train_data[column]
plt.figure(figsize=(14, 5),dpi=300) # 设置图表大小
plt.plot(data_series)
plt.title(f'{column} 序列图')
print("*如数据围绕某一常数上下波动,没有上升或下降的趋势,即可认为是平稳序列。")
data_adf = ADF(data_series) # 单位根检验,及特征根检验,序列平稳,就不存在单位根,检验结果的P值越小越好
if data_adf[1] < alpha:
result = f"{column} 序列是弱平稳序列,P值为:{round(float(data_adf[1]), 4)}"
else:
result = f"{column} 序列不是弱平稳序列,P值为:{round(float(data_adf[1]), 4)}"
return result
# 对每个列进行平稳性检查
for column in train_data.columns:
result = check_station(train_data, column)
print(result)
输出结果:
*如数据围绕某一常数上下波动,没有上升或下降的趋势,即可认为是平稳序列。
情绪指数 序列是弱平稳序列,P值为:0.0
*如数据围绕某一常数上下波动,没有上升或下降的趋势,即可认为是平稳序列。
上证指数 序列不是弱平稳序列,P值为:0.3602
(4)差分与协整检验
def coint_pvalue_matrix(train_data):
"""
参数说明:
train_data:原始数据,为dataframe格式,每一列代表一个变量:
返回结果:
返回协整检验的p_value,p_value越低,越显著。
"""
train_data=train_data
n=len(train_data.columns)
#创建一个空的矩阵
coint_pvalue=np.ones((n,n))
#将矩阵转换为dataframe格式
coint_pvalue=pd.DataFrame(coint_pvalue)
coint_pvalue.index=train_data.columns
coint_pvalue.columns=train_data.columns
for column_1 in train_data.columns:
for column_2 in train_data.columns:
#协整检验会返回三个值,第二值为p值,p值越小,说明存在长期协整关系
if column_1!=column_2:
result = sm.tsa.stattools.coint(train_data[column_1],train_data[column_2])
coint_pvalue.loc[column_1,column_2]=round(result[1],4)#pd.loc[index,column]
return coint_pvalue
coint_pvalue=coint_pvalue_matrix(train_data)
print(coint_pvalue)#由于序列上证指数序列不平稳,需要差分,且不存在长期协整关系
(5)格兰杰因果检验
#差分后序列平稳,进行格兰杰因果检验
def granger_pvalue_matrix(train_data,test="ssr_chi2test",lags=10):
"""
参数说明:
train_data:原始数据,为dataframe格式,每一列代表一个变量:第一列为Y,第二列为X,检验X是否为Y的格兰杰原因:
lags:为最大滞后阶数
test:格兰杰检验方法,一共会有4个p值,默认选用ssr_chi2test的p值(其他可选项lrtest,params_ftest,ssr_ftest)
返回结果:
返回格兰杰检验的p_value,p_value越低,越显著。说明X是Y的格兰杰原因。
"""
train_data=train_data
n=len(train_data.columns)
#初始化一个dataframe格式
granger_pvalue=pd.DataFrame(np.zeros((n,n)))
granger_pvalue.index=train_data.columns
granger_pvalue.columns=train_data.columns
for column_1 in granger_pvalue.index:
for column_2 in granger_pvalue.columns:
result = grangercausalitytests(train_data[[column_1,column_2]],maxlag=lags,verbose=False)#verbose=False不打印结果
p_values = [round(result[i+1][0][test][1],4) for i in range(lags)]
min_p_value = np.min(p_values)#一共滞后10阶,没滞后1阶都会有一个p值,获取最小的那个p值
granger_pvalue.loc[column_1,column_2]=min_p_value
granger_pvalue.columns = [column_2 + '_x' for column_2 in granger_pvalue.columns]
granger_pvalue.index = [column_1 + '_y' for column_1 in granger_pvalue.index]
return granger_pvalue
granger_pvalue=granger_pvalue_matrix(train_data)
print(granger_pvalue)
(6)VAR模型构建
#VAR模型滞后阶数不方便单独通过图表判断,一般都是设置一个最大滞后项,然后运用AIC信息准则的方式来判断,AIC值越小,模型拟合越优。
model = sm.tsa.VAR(train_data)
result=model.fit(maxlags=10, method='ols', ic="aic", trend='c', verbose=False)#ic="aic"系统会根据aic准则在(1-10)中自动选取最优模型
print(result.summary())
输出结果:
(7)单位根检验
def root_ar(roots,maxlim=1.5):
"""
参数说明:
roots:VAR模型返回的模型根。
maxlim:坐标轴的最大值
返回结果:
AR根图,如果根都在单位圆内,则为平稳模型。
"""
#绘制单位圆
x=np.linspace(-1,1,400)
y=np.linspace(-1,1,400)
[X,Y]=np.meshgrid(x,y)
Z=X*X+Y*Y
plt.figure(figsize=(5,5))
plt.contour(X,Y,Z,1)
plt.title("Inverse Roots of AR")
#提取模型根的实部和虚部
roots_real=roots.real
roots_imag=roots.imag
plt.xlim(-maxlim,maxlim)
plt.ylim(-maxlim,maxlim)
#画中间十字线
h_x=np.linspace(0,0,400)
h_y=np.linspace(-maxlim,maxlim,400)
plt.plot(h_y,h_x,"b--")
plt.plot(h_x,h_y,"b--")
"""
VAR模型库,对roots的解释如下:
The roots of the VAR process are the solution to (I - coefs[0]*z - coefs[1]*z**2 … - coefs[p-1]*z**k_ar) = 0.
Note that the inverse roots are returned,
and stability requires that the roots lie outside the unit circle.
根在模型外说明模型是平稳的,这和传统的AR根图画法有很大不同;
因此我们将其根转换成其倒数,这样根就会落在单位圆内。
"""
#将根转化成根的倒数(根为复数)
Inverse_real=roots_real/(np.abs(roots)*np.abs(roots))#abs即可以算绝对值,也可以算复数的模
Inverse_imag=-roots_imag/(np.abs(roots)*np.abs(roots))
plt.plot(Inverse_real,Inverse_imag,"ro")
plt.savefig(r'E:\工作\硕士\博客\博客粉丝问题\接单34-1200元\情绪指数与上证指数VAR模型\AR单位根检验.png',
bbox_inches ="tight",
pad_inches = 1,
transparent = True,
facecolor ="w",
edgecolor ='w',
dpi=300,
orientation ='landscape')
return None
roots=result.roots
root_ar(roots,maxlim=1.5)
#从AR根图来看,所有根都落在单位圆内,因此我们认为模型是平稳的。
输出结果:
说明模型是有效的。
(8)脉冲响应分析
#绘制脉冲响应图
irf = result.irf(15)
irf.plot(orth=False)
plt.savefig(r'E:\工作\硕士\博客\博客粉丝问题\情绪指数与上证指数VAR模型\脉冲响应图.png',
bbox_inches ="tight",
pad_inches = 1,
transparent = True,
facecolor ="w",
edgecolor ='w',
dpi=300,
orientation ='landscape')
输出结果:
需要数据集的家人们可以去百度网盘(永久有效)获取:
链接:
提取码:2138
更多优质内容持续发布中,请移步主页查看。
点赞+关注,下次不迷路!