前言
在本文开始前,作者并没有提倡LSTM是一种高度可靠的模型,它可以很好地利用股票数据中的内在模式,或者可以在没有任何人参与的情况下使用。写这篇文章,纯粹是出于对机器学习的热爱。在我看来,该模型已经观察到了数据中的某些模式,因此它可以在大多数时候正确预测股票的走势。但是,这个模型是否可以用于实际,有待用更多回测和实践去验证。
为什么需要时间序列模型?
你想要正确地模拟股票价格,因此作为股票买家,你可以合理地决定什么时候买股票,什么时候卖股票。这就是时间序列建模的切入点。你需要良好的机器学习模型,可以查看数据序列的历史记录,并正确地预测序列的未来元素是什么。
提示:股市价格高度不可预测且不稳定。这意味着在数据中没有一致的模式可以让你近乎完美地模拟股票价格。就像普林斯顿大学经济学家Burton Malkiel在他1973年的书中写到的:“随机漫步华尔街”,如果市场确实是有效的,那么当股票价格反应的所有因素一旦被公开时,那我们闭着眼睛都可以做的和专业投资者一样好。
但是,我们不要一直相信这只是一个随机过程,觉得机器学习是没有希望的。你不需要预测未来的股票确切的价格,而是股票价格的变动。做到这点就很不错了!
数据准备
使用以下数据源:
地址:https://www.kaggle.com/borismarjanovic/price-volume-data-for-all-us-stocks-etfs
当然你也可基于Wind数据库去研究。因为Wind数据相对于其他平台和数据商而言,总体上在国内算是比较全面和准确的。
从Kaggle获得数据
在Kaggle上找到的数据是csv文件,所以,你不需要再进行任何的预处理,因此你可以直接将数据加载到DataFrame中。同时你还应该确保数据是按日期排序的,因为数据的顺序在时间序列建模中至关重要。
df = df.sort_values('Date')
df.head()
数据可视化
plt.figure(figsize = (18,9))
plt.plot(range(df.shape[0]),(df['Low']+df['High'])/2.0)
plt.xticks(range(0,df.shape[0],500),df['Date'].loc[::500],rotation=45)
plt.xlabel('Date',fontsize=18)
plt.ylabel('Mid Price',fontsize=18)
plt.show()
上图已经说明了很多东西。我选择这家公司而不是其他公司的具体原因是,随着时间的推移,这张图中展现了不同的股价行为。这将使学习更加稳健,并且可以更改以便测试各种情况下预测的好坏程度。
数据拆分训练集和测试集
计算一天中最高和最低价的平均值来计算的中间价格。
high_prices = df.loc[:,'High'].as_matrix()
low_prices = df.loc[:,'Low'].as_matrix()
mid_prices = (high_prices+low_prices)/2.0
现在你可以分离训练数据和测试数据。训练数据是时间序列的前11000个数据,其余的是测试数据。
train_data = mid_prices[:11000]
test_data = mid_prices[11000:]
现在需要定义一个标准对数据进行归一化。MinMaxScalar方法将所有数据归到0和1之间。你还可以将训练和测试数据重新组为[data_size, num_features]。
scaler = MinMaxScaler()
train_data = train_data.reshape(-1,1)
test_data = test_data.reshape(-1,1)
根据之前得数据,可以看出不同时间段有不同的取值范围,你可以将整个序列拆分为窗口来进行归一化。如果不这样做,早期的数据接近于0,并且不会给学习过程增加太多价值。这里你选择的窗口大小是2500。
当选择窗口大小时,确保它不是太小,因为当执行窗口规范化时,它会在每个窗口的末尾引入一个中断,因为每个窗口都是**规范化的。
在本例中,4个数据点将受此影响。但假设你有11000个数据点,4个点不会引起任何问题。
smoothing_window_size = 2500
for di in range(0,10000,smoothing_window_size):
scaler.fit(train_data[di:di+smoothing_window_size,:])
train_data[di:di+smoothing_window_size,:] = scaler.transform(train_data[di:di+smoothing_window_size,:])
# You normalize the last bit of remaining data
scaler.fit(train_data[di+smoothing_window_size:,:])
train_data[di+smoothing_window_size:,:] = scaler.transfo