用时序模型预测明天的股票价格

864b70755112d45c2b158193cd1d9f0d.gif

前言

上次介绍了一个简单的量化交易策略,收到一堆私信询问如何使用深度学习的时序模型,那再抛砖引玉分享一下LSTM模型预测明天价格的方法。

LSTM模型

长短期记忆(Long short-term memory, LSTM)是一种特殊的循序神经网络,一个普通的 LSTM 单元由一个「单元」、一个「输入门」、一个「输出门」和一个「遗忘门组成」

19751ed4f093394a335b145df84eda75.png
LSTM单元

时序模型简单而言,就是用历史上时间连续的一段数据来预测未来的数据,我们将输入的数据流按照下图用 LSTM 模块循环连接起来。

b7f246dd2e2e4a6d4e40ac71c132f5ce.png

环境准备

我们先在聚宽上开一个新的 Notebook,记得用 python3 的版本,已经预装了 Tensorflow。

如果没有,就手动安装一下

!pip install tensorflow

import math
import numpy as np
import pandas as pd
import tensorflow as tf
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import Dense, LSTM
import matplotlib.pyplot as plt
plt.style.use('fivethirtyeight')

先检查一下 tensorflow 的版本,1.12 的,keras 2.2.4,简单模型基本够用了。

import keras
print('tensorflow:',tf.__version__)  # 1.12.2
print('keras:',keras.__version__)  # 2.2.4

数据准备

以"沪深300指数基金"为例,前60天的数据为时序区间,我们获取2015年以来的所有「收盘数据」作为数据集。

security = '510300.XSHG'
his_period = 60  # 历史时间
df = get_price(security, start_date="2015-01-05", end_date="2021-12-31", frequency='daily')
df[:3]
6975f2f7be834ff9829bab75613cb9b1.png

一共有1705条数据,先可视化一下。

plt.figure(figsize=(16,8))
plt.title('Close Price History')
plt.plot(df['close'])
plt.xlabel('Date', fontsize=18)
plt.ylabel('Close Price', fontsize=18)
plt.show()
dcb7b3a38ad128b23a4a272ef8435394.png

划分训练集

筛选到收盘数据,先将其 80% 划分为训练集,1364条记录。

data = df.filter(['close'])
dataset = data.values
training_data_len = math.ceil( len(dataset) * .8 )

归一化数据,将其缩放到 (0,1)方便训练

scaler = MinMaxScaler(feature_range=(0, 1))
scaled_data = scaler.fit_transform(dataset)
b1b1e2fee668e81fc04fb850387470d9.png

每60个历史数据作为训练集,配一个标签数据,生成训练集。

train_data = scaled_data[0:training_data_len, :]
x_train = []
y_train = []

for i in range(his_period, len(train_data)):
    x_train.append(train_data[i-his_period:i, 0])
    y_train.append(train_data[i, 0])

x_train, y_train = np.array(x_train), np.array(y_train)
x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))
x_train.shape

将其转化为 numpy 阵列后,维度为 (1304, 60, 1)。

建立模型

我们用 keras 顺序模型来搭建神经网络,先用 2层50单元的 LSTM 来提取特征,然后用全连接层来输出结果。优化器采用 Adam,损失函数用 MSE。

model = Sequential()
model.add(LSTM(50, return_sequences=True, input_shape=(x_train.shape[1], 1)))
model.add(LSTM(50, return_sequences=False))
model.add(Dense(25))
model.add(Dense(1))

model.compile(optimizer='adam', loss='mean_squared_error')

训练模型

batch size 设为 1,先训练 5 个 epoch。

model.fit(x_train, y_train, batch_size=1, epochs=5)
d455bfd13ef38cb4a6780af0701f4dfa.png

好了,万事俱备,接下来就是泡杯咖啡cda2027fed4bbafa001139b0449d930c.png,耐心等待了。。。

验证模型

我们将剩余的 20% 数据划分为测试集,同样转为 numpy 数据,维度为 (341, 60, 1)。

test_data = scaled_data[training_data_len - his_period:, :]
x_test = []
y_test = dataset[training_data_len:, :]
for i in range(his_period, len(test_data)):
    x_test.append(test_data[i-his_period:i, 0])
    
x_test = np.array(x_test)
x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1], 1))
x_test.shape

预测一波,先计算一下 rmse。

predictions = model.predict(x_test)
predictions = scaler.inverse_transform(predictions)
rmse=np.sqrt(((predictions - y_test) ** 2).mean())
rmse
6debec02a393975861063c6ec2fd91ee.png

可视化看看效果

train = data[:training_data_len]
valid = data[training_data_len:]
valid['Predictions'] = predictions

plt.figure(figsize=(16, 8))
plt.title('Model')
plt.xlabel('Data', fontsize=18)
plt.ylabel('Close Price', fontsize=18)
plt.plot(train['close'])
plt.plot(valid[['close', 'Predictions']])
plt.legend(['Train', 'Val', 'Predictions'], loc='lower right')
plt.show()
9ec4ce938c329ec13495c8afc2b2de86.png

整体来看,基本预测出了趋势,预测价格偏保守。可能有模型epoch不足的因素,也可能是指数处于近两年的相对高位,模型没见过世面。

有兴趣的朋友可以改些参数,或者引入更多特征,finetune 一下。

实战

重新获取一下数据集,从2015年到昨天的所有数据。

new_df = get_price(security, start_date="2015-01-05", end_date="2022-1-4", frequency='daily')
new_df.tail()
cec54f5eb176eb410858a8b009c18f47.png

来预测一下明天的收盘价

last_days = new_df.filter(['close'])[-his_period:].values
last_days_scaled = scaler.transform(last_days)
X_test = []
X_test.append(last_days_scaled)
X_test = np.array(X_test)
X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], 1))
pred_price = model.predict(X_test)
pred_price = scaler.inverse_transform(pred_price)
print(pred_price)
[[4.901391]]

记得明天收盘以后,再来看看实际价格是多少来着?

get_price(security, start_date="2022-1-5", end_date="2022-1-5", frequency='daily').filter(['close'])

好了,财富密码告诉你们了,就看明天的收盘价准不准吧。430eecc26a47ea4077e08cae2a556057.png

94f3152075318638ec629e97f478350f.png

最后再提一句,入市有风险,投资需谨慎。

源码下载

b25564a43ca8a17b4d13d84d348defd6.png

本期相关文件资料,可在公众号“深度觉醒”,后台回复:“trade01”,获取下载链接。

32f80945924d673d1f066c57bf4ca527.gif

猜你喜欢

转载自blog.csdn.net/weixin_47479625/article/details/122335490