前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >验证 | 单纯用LSTM预测股价,结果有多糟(附代码)

验证 | 单纯用LSTM预测股价,结果有多糟(附代码)

作者头像
量化投资与机器学习微信公众号
发布2019-02-26 16:32:46
13.3K1
发布2019-02-26 16:32:46
举报
文章被收录于专栏:量化投资与机器学习

本期作者:Alexandre Xavier

本期翻译:Remedios | 公众号翻译部

前言

在这篇文章中,我们会使用神经网络,特别是LSTM模型,来预测时间序列。

尽管预测股价确实是一个老问题,至今仍然没有被解决。事实十分简单:股票的价格由多种因素决定,而股票的历史价格仅仅是众多原因中的一小部分。因此,预测股价走势是一个非常困难的问题

获取全部代码见文末:

摘要

首先,我将使用一些数据可视化工具介绍数据集。然后,我们将大致讨论使用移动平均算法预测股票市场走势有多难并且展示其局限性。接下来,我们将对RNN和LSTM的做一个简短的介绍,并举一个预测单个公司股价的LSTM实例。最后,我们会展示使用LSTM同时预测四个公司的股价,并且比较结果以探究是否预测效果会随着我们预测股价的公司个数的增加而提升。

数据可视化

本文使用的数据集是以CSV格式从雅虎财经下载下来的,其中包括四个公司从2010年1月8日到2019年1月7日的股价。我们将这四个公司分别称为A,B,C和D.

基础步骤是用Pandas打开这个CSV文件。我们先看一下这些数据:

代码语言:javascript
复制
df_A = pd.read_csv(‘data/company_A.csv’)
df_A[‘Date’] = pd.to_datetime(df_A[‘Date’])
df_A.head()
代码语言:javascript
复制
plt.figure(figsize = (15,10))
plt.plot(df_A['Date'], df_A['Close'], label='Company A')
plt.plot(df_B['Date'], df_B['Close'], label='Company B')
plt.plot(df_C['Date'], df_C['Close'], label='Company C')
plt.plot(df_D['Date'], df_D['Close'], label='Company D')
plt.legend(loc='best')
plt.show()

四个公司的收盘价

移动平均

用于股价预测的一个经典算法是移动平均值(MA)。这个方法主要在于计算过去“m”个观察日的平均值,并且使用此结果作为下一日的预测值。作为举例,使用过去10天和20天的收盘价计算移动平均值。

代码语言:javascript
复制
df['MA_window_10'] = df['Close'].rolling(10).mean().shift() 
df['MA_window_20'] = df['Close'].rolling(20).mean().shift()

当我们尝试使用移动平均值对未来10天股票的收盘价进行预测时,结果如下:

获取全部代码,见文末

代码语言:javascript
复制
window_size = 10
forward_days = 10 # > 1, ou seja, 2,3,4,5,...
for index in range(window_size, len(df), forward_days):
    for i in range(0,forward_days):
        if index+i >= len(df):
            break
        window_close = make_window(window_size-i, index+i-window_size)
        #print(window_close)
        window_MA = make_window(i, index)
        #print(window_MA)
        mean = pd.concat([ df['Close'].iloc[window_close], df['MA_window_10_forward_10'].iloc[window_MA] ]).mean(axis=0)
        df.iat[index+i, df.columns.get_loc('MA_window_10_forward_10')] = mean

plt.figure(figsize = (15,10))

size = len(df)-limit - (len(df)-limit)%forward_days

for index in range(size, len(df), forward_days):
    plt.plot(df['MA_window_10_forward_10'][index:index+forward_days], color='r')
    
plt.plot(df['Close'][-limit:], color='b', label='Close')
#plt.legend(loc='best')
plt.show()

使用移动平均对公司A股票的十日收盘价预测

注意每条红线代表一个基于过去十天数据的10日股价预测。因此,红线是不连续的。

使用一个稍微更好一点的算法,指数移动平均(EMA),我们可以对预测实现一点点改善:

使用指数移动平均对公司A股票收盘价进行提前一天预测结果

对比MA和EMA:

提前一天使用移动平均和指数移动平均对股票收盘价进行预测结果对比

这个方法过于简单。我们真正想要的是提前“n”天预测未来的走势,这个任务MA和EMA都无法做到。

RNN

要理解LSTM网络,我们首先需要理解RNN。这种网络被用于过去结果对目前结果有影响时的模式识别。时间序列函数是RNN的一个运用实例。在这个函数中,数据顺序极其重要。

在这个网络架构中,神经元不仅使用普通的输入(即前一层的输出),也使用它之前的状态作为输入。

RNN结构

需要注意的是,“H”代表神经元的状态。因此,在状态H1,神经元使用参数X1和H0(它之前的状态)作为输入。这个模型的主要问题是记忆的损失。之前的网络状态将会被更快地遗忘。在我们需要记忆前序信息之前的信息的序列中,RNN无法记忆。

LSTM

LSTM源于RNN,但是它能够通过改变神经元架构解决记忆的损失。

LSTM结构

新的神经元有三个门,每一个有不同的功能。这些门分别是:

  • 输入门
  • 输出门
  • 遗忘门

每个LSTM神经元依然将它之前的状态作为输入:

LSTM神经元让它之前状态的参数通过

使用LSTM预测单个公司股价

最后,让我们使用一个LSTM来预测公司A单个公司股价的走势。

首先来看以下这些参数。我们想要利用m日过去的数据(look_back)对未来n天(forward_days)的股价进行预测。所以,如果我们有m天过去数据的输入值,这个网络的输出值会是之后n天股价的预测值。我们将数据集划分为训练集和测试集。训练集将由k个周期组成(num_periods),每个周期中有一系列的n日预测。

代码语言:javascript
复制
look_back = 40
forward_days = 10
num_periods = 20

现在,让我们用Pandas打开这个CSV文件并且只保留我们会用到的日期和收盘价两列。公司A初始的收盘价作图如下:

代码语言:javascript
复制
plt.figure(figsize = (15,10))
plt.plot(df)
plt.show()

我们依次衡量输入值的比例,将数据划分成训练集/验证集和测试集,并进行格式化来反馈给模型。详细过程可以在文末代码上找到

现在,我们建立并训练这个模型。

获取全部代码,见文末

代码语言:javascript
复制
NUM_NEURONS_FirstLayer = 128
NUM_NEURONS_SecondLayer = 64
EPOCHS = 220
#Build the model
model = Sequential()
model.add(LSTM(NUM_NEURONS_FirstLayer,input_shape=(look_back,1), return_sequences=True))
model.add(LSTM(NUM_NEURONS_SecondLayer,input_shape=(NUM_NEURONS_FirstLayer,1)))
model.add(Dense(foward_days))
model.compile(loss='mean_squared_error', optimizer='adam')
history = model.fit(X_train,y_train,epochs=EPOCHS,validation_data=(X_validate,y_validate),shuffle=True,batch_size=2, verbose=2)

结果得到:

看看测试集:

注意每条红线代表基于过去40天的十日预测。我们选择在20个周期上测试,因而有20根红线。这就是为什么红色的预测线不连续。

通过对所有公司重复以上相同的流程,测试集的最好结果出现在对公司C的预测。

尽管这是这之间最好的模型,结果还远远不够优秀。可能导致这个结果的理由有很多,其中的一些可能是:

  • 仅仅用收盘价历史数据不足以预测股价走势
  • 这个模型还能被进一步改善

使用LSTM预测四个公司的股价

最后,我们将用LSTM模型来一起预测所有四个公司的股价走势,并将结果与LSTM预测单个公司的结果进行对比。目标是分析是否使用来自几个不同公司的数据能够提高对个个公司股价的预测。

需要指出的是,所有四个CSV文件有相同的日期。这样以来,网络不会从一家公司接收未来讯息来预测另一家公司的价值。

在数据正则化并格式化,反馈给模型之后,这个模型被训练:

代码语言:javascript
复制
NUM_NEURONS_FirstLayer = 100
NUM_NEURONS_SecondLayer = 50
EPOCHS = 200
#Build the model
model = Sequential()
model.add(LSTM(NUM_NEURONS_FirstLayer,input_shape=(look_back,num_companies), return_sequences=True))
model.add(LSTM(NUM_NEURONS_SecondLayer,input_shape=(NUM_NEURONS_FirstLayer,1)))
model.add(Dense(foward_days * num_companies))
model.compile(loss='mean_squared_error', optimizer='adam')
history = model.fit(X_train,y_train,epochs=EPOCHS,validation_data=(X_validate,y_validate),shuffle=True,batch_size=1, verbose=2)

结果:

仔细看测试集:

到了比较结果的时候了。单个公司LSTM模型的结果放在左边,四个公司LSTM模型的结果放右边遍。第一条线展示的是测试集中的预测,第二条线是所有数据集的预测。

公司A

公司B

公司C

公司D

总结

仅仅使用股票的历史价格预测证券市场的走势是不可能的。LSTM预测仍然令人不合意。甚至当利用多个公司的历史股价预测时,预测结果更加糟糕。

The original:https://medium.com/infosimples/predicting-stock-prices-with-lstm-349f5a0974d4

参考资料

[1] https://www.datacamp.com/community/tutorials/lstm-python-stock- market

[2] http://colah.github.io/posts/2015-08-Understanding-LSTMs/

[3] https://towardsdatascience.com/train-validation-and-test-sets- 72cb40cba9e7

[4] https://machinelearningmastery.com/diagnose-over12tting-under12tting- lstm-models/

[5] https://machinelearningmastery.com/reshape-input-data-long-short- term-memory-networks-keras/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-02-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 量化投资与机器学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档