ARIMA单变量预测股价DEMO
时间序列介绍:
时间序列(TIME-SERISE)充斥着我们生活的空间,在金融、医疗、交通等领域都可体现,甚至我认为人类个体生存生活的时间线都是时间序列,个体在什么时间干了什么事,具体量化细分皆是时间序列。在严格学术意义上大致将时间序列区别为,平稳时间序列和非平稳时间序列。平稳时间序列是标准的严平稳时间序列,表示有着明显的周期性的序列数据,在整个序列中不存在“噪声”等,而现实的世界中大都是非平稳的时间序列,本文中介绍的ARIMA模型主要是针对平稳时间序列有效。
统计学模型-ARIMA介绍
网络上存在很多的ARIMA模型的原理介绍,本文在此不再陈述,具体的参考为下。
https://zhuanlan.zhihu.com/p/67092940
ARIMA 参数选择说明
关于ARIMA模型参数的确定是根据具体自己的数据来选择的。一共有三个参数(P、Q、D)
D: 是数据的差分阶数,根据自己数据的特点选择,但是一般情况下我们选择一阶差分或者二阶差分。
Q: Q指的是自相关系数(ACF)。自相关(英语:Autocorrelation),也叫序列相关,是一个信号于其自身在不同时间点的互相关。非正式地来说,它就是两次观察之间的相似度对它们之间的时间差的函数。它是找出重复模式(如被噪声掩盖的周期信号),或识别隐含在信号谐波频率中消失的基频的数学工具。它常用于信号处理中,用来分析函数或一系列值,如时域信号。也就是研究序列T时刻与T+K时刻的关系,量化两者间是否存在一定的相似性。
P: P是指偏相关系数(PACF)。在多要素所构成的序列中,当研究某一个要素对另一个要素的影响或相关程度时,把其他要素的影响视作常数(保持不变),即暂时不考虑其他要素影响,单独研究两个要素之间的相互关系的密切程度,所得数值结果为偏相关系数 。也就是只研究序列T时刻与T+K时刻的关系,忽略中间K-1个数值的影响。
至于PQ的参数选择可以参考下图:
源代码解析
本文的数据集是沪深股票数据。具体获取处理可以自行解决。本博客部分代码参考下博客:
https://blog.csdn.net/qq_36523839/article/details/80191243
源代码部分:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from statsmodels.tsa.arima_model import ARIMA
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
sns.set_style("whitegrid", {"font.sans-serif": ['KaiTi', 'Arial']})
import csv
def run_main():
with open('scaled_open.csv', 'r') as csvfile:
reader = csv.reader(csvfile)
for i, rows in enumerate(reader):
if i == 3: ###读取某行
row_2 = rows
if i==0:
row_0 = rows
row_0.reverse()
row_2.reverse()
data = pd.DataFrame(row_2[:1000],columns=['open'],index=row_0[:1000],dtype=np.float64)
print(data)
# plt.plot(data['open']) # 原始数据
# plt.title('股市每日开盘价')
# plt.show()
data = data.set_index(pd.DatetimeIndex(pd.to_datetime(data.index))) ##日期索引转换
data1_w = data['open'].resample('W-MON').mean() #一周来采样,更好预测,并取每一周的均值
data1_train = data1_w['2017':'2019'] # 我们只取2018到2020的数据来训练
plt.plot(data1_train)
plt.title('周重采样数据')
plt.show()
# data2_train = data2_train.tolist()
# data2_train = data['open']['2019':'2020']
data1_train[np.isnan(data1_train)] = 0
data1_train[np.isinf(data1_train)] = 0
print(data1_train)
data1_diff = data1_train.diff(1) # 差分使用pandas的diff()函数可以进行一阶差分
diff = data1_diff.dropna()
plt.plot(diff)
plt.title('一阶差分')
plt.show()
#分析ACF
plot_acf(diff, lags=20) # 通过plot_acf来查看训练数据,以便我们判断q的取值
plt.title("股票指数的 ACF")
plt.show()
#
# 分析PACF
plot_pacf(diff, lags=20) # 通过plot_pacf来查看训练数据,以便我们判断p的取值
plt.title("股票指数的 PACF")
plt.show()
# 根据ACF和PACF以及差分 定阶并建模
model = ARIMA(data1_train, order=(2, 1, 3), freq='W-MON') # pdq 频率按周
# model = ARIMA(data2_train, order=(2, 1, 3)) # pdq
# 拟合模型
arima_result = model.fit()
print(arima_result.summary())### 打印模型参数
# 预测
pred_vals = arima_result.predict('2020-01-01','2021-1-28',dynamic=True, typ='levels') # 输入预测参数,这里我们预测2021-01-01以后的数据
print(pred_vals)###输出预测值
#可视化预测
stock_forcast = pd.concat([data1_w, pred_vals], axis=1, keys=['original', 'predicted']) # 将原始数据和预测数据相结合,使用keys来分层
# 构图
plt.figure()
plt.plot(stock_forcast)
plt.title('真实值vs预测值')
plt.show()
if __name__ == "__main__":
run_main()
参考资料
https://zhuanlan.zhihu.com/p/67092940
https://www.cnblogs.com/tianqizhi/p/9277376.html
https://blog.csdn.net/qq_36523839/article/details/80191243
https://www.bilibili.com/video/BV1F441187xt?p=2&spm_id_from=pageDriver
https://zhuanlan.zhihu.com/p/35069699