时间序列分析系列(1)LSTM对股价进行预测

时间序列原理

  生活中,有一类数据有明显的先后顺序,比较常见的就是今天的主题:时间序列。所谓时间序列,讲的是,如果从时间的角度进行观察一组数据,它们是按照时间的流逝依次发生的,即数据的位置不能颠倒,其中股票数据就是最常见的时间序列。
  时间序列在生活中如此常见,以至于我们产生了些幻想。
  我们能否基于已经观察到的历史数据去预测未来还没有发生的情况呢?那画面岂不很美?如果要能对未来进行预测,那么需要满足一个前提假设:历史数据包含了未来数据的信息,即未来数据和历史数据存在一定的相关性。举个栗子,例如上个月你多吃了几个汉堡,那么可能导致的结果就是今天的你长胖了几斤,换句话说,也就是今天的你和过去的你是存在一定关联的,如果能通过过去的你的行为模式找到这种关联,那么不就能基于昨天的你或者一年前的你对今天的你做出一定的预测了吗?
  但是,也存在一种特殊情况,未来的数据和历史数据无关,例如,白噪声,随机游走等,该类序列每一时刻的取值都符合高斯分布,即下一个时刻的取值和上一时刻没有任何关系,相关性为0,面对这样的数据,还是洗洗睡了,没有预测的必要。
  现在我们有了假设:历史数据能对未来数据产生影响,接下来我们的任务就是建立模型去找到这种影响,从而对未来进行预测。
  这一类的问题把它统称为序列预测,用一个简单的图示表示:
在这里插入图片描述
  上图所示,观察到一组时间序列:[1,2,3,4,5],通过模型预测得到下一个时刻的观测值为6,这里模型可以简单理解成为一种映射关系,给它一个输入,它就能给出一个输出。
  接下来,就需要原材料,即时间序列,这里我用了立讯精密19年到20年的收盘价作为数据。
  再接下来,就是模型的选择,用什么模型去完成这个任务呢?机器学习和深度学习有大量的模型可以供选择,今天,先选择LSTM作为模型,它属于RNN网络的一种改进版,优点就是可以学习序列里的长期依赖信息,比较适合用来处理时间序列的问题。
  废话少说,进入主题,撸代码。

代码部分

  1. 加载各种需要的包以及获取数据
# 载入所需的各种工具包工具包
import numpy as np
import pandas as pd

import seaborn as sns
import matplotlib.pyplot as plt

import tushare as ts

from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import LSTM
from keras.callbacks import ModelCheckpoint
from keras.utils import np_utils
from keras.preprocessing.sequence import TimeseriesGenerator
from sklearn.preprocessing import MinMaxScaler
import warnings
warnings.filterwarnings('ignore')
plt.style.use('ggplot')
#这里我们选择tushare去获取股票数据
#获取前复权数据
ts.set_token('你的token')

#获取立讯精密19年-20年前复权历史数据
data = ts.pro_bar(ts_code='002475.SZ', adj='qfq', start_date='20190101', end_date='20200914')

#设置时间索引并对序列进行排序
data.index = pd.to_datetime(data['trade_date'])
data = data.sort_index()
data.head()
#这里我们只需要每日收盘价数据
uni_data = data['close']
index = uni_data.index
(数据打印出来如下:)
trade_date
2019-01-02     8.3304
2019-01-03     7.9239
2019-01-04     7.7825
2019-01-07     8.0771
2019-01-08     8.1949
               ...   
2020-09-08    52.7600
2020-09-09    51.6500
2020-09-10    53.1000
2020-09-11    55.9500
2020-09-14    56.2100

2.为了评估模型的效果,我们需要将数据分成两部分,训练集和测试集,训练集用来让模型学习,测试集用来对模型学习的效果进行评估(这里,训练集可以看成是学生平时学习的材料,测试集看成是高考的题目,所以,测试集是不能让模型’看见’的)

#拆分训练数据和测试数据(这里用80%的数据作为训练模型的数据)
split = 0.8
train_set = uni_data[:int(len(uni_data)*split)]
test_set = uni_data[int(len(uni_data)*split):]
train_set.shape,test_set.shape

上述表示,我们用2019年1月到2020年5月18日区间内的数据作为训练数据,用2020年5月19日到2020年9月14日的数据作为测试数据

  1. 接下来我们绘制出这段时间内立讯精密的收盘价走势
train_set.plot(figsize=(16,5),legend=True)
test_set.plot(figsize=(16,5),legend=True)
plt.title('002475 Stock Price')
plt.legend(['Train Set','Test Set'])
plt.xlabel('Date')
plt.ylabel('Price')
plt.show()

在这里插入得瑟得瑟描述
(图中,红色的部分是模型学习的材料,蓝色的数据是模型考试的材料)

#定义一个绘制函数  用来绘制图像,方便之后调用
def plot(test_result,predict_result,time_window):
    '''
    test_result:真实值
    predict_result:预测值
    time_window:时间序列的窗口大小
    
   '''
    plt.figure(figsize=(16,6))
    plt.plot(test_result,c='red',label='True Stock Price')
    plt.plot(predict_result,c='blue',label='Predicted Stock Price')
    plt.title('Stock Price,time step is {}'.format(time_window))
    plt.xlabel('Time')
    plt.ylabel('Price')
    
    plt.legend(loc='best')
    plt.show()```

  1. 在训练模型之前,需要对数据做缩放处理,因为深度学习的模型对数据的大小比较敏感,容易对噪声做出错误反应,缩放后,能最大程度降低噪声的干扰,以及加快模型的训练。
scaler = MinMaxScaler(feature_range=(0,1))

#使用MinMaxScaler对训练集进行拟合 并缩放训练集
train_set_scaled = scaler.fit_transform(np.array(train_set).reshape(-1,1))

#对测试集进行缩放
test_set = np.array(test_set).reshape(-1,1)
test_set_scaled = scaler.transform(test_set)```
  1. 制作样本和标签
    这里我们随机选择时间步长为5,即5个观察值作为X,下一个时刻的值作为y,得到样本数据(X,y)
#创建时间序列
time_step = 5
x_train = []
y_train = []

#创建训练集
for i in range(time_step,len(train_set)):
    x_train.append(train_set_scaled[i-time_step:i])
    y_train.append(train_set_scaled[i])
x_train, y_train = np.array(x_train),np.array(y_train)```

#创建测试集

x_test = []
y_test = []
for i in range(time_step,len(test_set)):
    x_test.append(test_set_scaled[i-time_step:i])
    y_test.append(test_set_scaled[i])
x_test, y_test = np.array(x_test),np.array(y_test)

#打印数据维度
x_train.shape,y_train.shape
((327, 5, 1), (327, 1))

x_test.shape,y_test.shape
((78, 5, 1), (78, 1))



构建LSTM模型

model = Sequential()
#第一层LSTM
model.add(LSTM(128,return_sequences=True,input_shape=(x_train.shape[1],x_train.shape[2])))
model.add(Dropout(0.2))

#第二层 LSTM
model.add(LSTM(128,return_sequences=True))
model.add(Dropout(0.2))

#第三层LSTM
model.add(LSTM(128))
model.add(Dropout(0.2))

#输出层
model.add(Dense(1))
#模型编译
model.compile(optimizer='adam',loss='mse')
#拟合模型
model.fit(x_train, y_train,epochs=200,batch_size=32)

#对测试集进行预测
y_pred = model.predict(x_test)

#因为得到的数据是缩放之后的,所以需要将数据进行还原
#对数据进行还原
y_pred = scaler.inverse_transform(y_pred)
y_test = scaler.inverse_transform(y_test)

#绘制预测值和真实值的图像
plot(y_test,y_pred,5)

在这里插入图片描述

#用R2对结果进行评估
from sklearn.metrics import r2_score
r2_score(y_test,y_pred)
return:0.762
#看结果,还是很好拟合出了趋势,而且相对原数据,比较平滑。

总结

1.使用LSTM对股价进行预测,在数据样本较少,且只使用收盘价这一个特征的情况下,从结果来看,效果还是蛮理想的,虽然和真实数据存在一定的差异,但是已经很好的拟合了数据的趋势,毕竟,影响股价的因素太多。
2.使用机器学习的办法对股票的时间序列数据进行拟合、预测,可以简单理解为模型对历史数据进行归纳,找到规律。这里插播一个火鸡的故事:讲的是在一个农场,一只火鸡被养了三年,它因此总结出1000天的经验:主人对我真好,每次只要伸过手来都是喂我好吃的。但是在第1001天,主人一直伸过来喂它的手,却抓住了它的脖子,把它杀死了。

  • 2
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值