LSTM对股票的收益进行预测(Keras实现)

目录

一、概述:

二、股票数据准备

三、股票数据预处理

1、数据特征归一化(标准化)

2、将数据集转化为有监督学习问题

四、股票数据划分为训练集和测试集

五、模型构建及其预测

1、搭建LSTM模型并绘制损失图

2、预测并反转数据(反归一化)

3、绘制模型预测结果图

六、模型评估


一、概述:

传统的线性模型难以解决多变量或多输入问题,而神经网络如LSTM则擅长于处理多个变量的问题,该特性使其有助于解决时间序列预测问题。

本文将初步探究 LSTM 在股票市场的应用。通过使用LSTM对股票收益的预测,可以了解到:(1)如何将原始数据集转换为可用于时间序列预测的数据。(2)如何准备数据并使LSTM适合多变量时间序列预测问题。(3)如何进行预测并将结果重新调整回原始数据。

本文以600000.SH股票数据为基准进行分析,以2016年3月1日至2017年12月31日为回测期,进行收益率的预测模拟。

本实验所需要导入的库如下:

import pandas as pd
# 核心代码,设置显示的最大列、宽等参数,消掉打印不完全中间的省略号
pd.set_option('display.max_columns', 1000)
pd.set_option('display.width', 1000)
pd.set_option('display.max_colwidth', 1000)

import matplotlib.pyplot as plt
from pandas import read_excel
import numpy as np
from pandas import DataFrame
from pandas import concat
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import LSTM,Dense,Dropout
from numpy import concatenate
from sklearn.metrics import mean_squared_error,mean_absolute_error,r2_score
from math import sqrt

二、股票数据准备

前两篇博客对股票数据进行了详细分析,根据股票指标间的相关关系,删除成交量市值pb这三个指标,实现了股票数据的降维。具体股票数据如下:

#定义字符串转换为浮点型(此处是转换换手率)
def str_to_float(s):
    s=s[:-1]
    s_float=float(s)
    return s_float

## 读取excel文件,并将‘日期’列解析为日期时间格式,并设为索引
stock_data=read_excel('stock_data/600000.SH.xlsx',parse_dates=['日期'],index_col='日期')
stock_data.drop(['交易日期','成交量','市值','pb'],axis=1, inplace=True) #删除多列数据
stock_data['换手率']=stock_data['换手率'].apply(str_to_float)
#对股票数据的列名重新命名
stock_data.columns=['open','high','low','close','turnover','pe']
stock_data.index.name='date' #日期为索引列
#将数据按日期这一列排序(保证后续计算收益率的正确性)
stock_data=stock_data.sort_values(by='date')
# 增加一列'earn_rate', 存储每日的收益率
stock_data['earn_rate'] = stock_data['close'].pct_change()
#缺失值填充
stock_data['earn_rate'].fillna(method='bfill',inplace=True)
# 打印数据的前5行
print(stock_data.head())

 部分数据如下:

三、股票数据预处理

采用LSTM模型时,需要对数据进行适配处理,其中包括归一化变量(包括输入和输出值)和将数据集转化为有监督学习问题,使其能够实现通过前一个时刻(t-1)的股票数据和收益率预测当前时刻(t)的股票收益率。

1、数据特征归一化(标准化)

LSTM对输入数据的规模很敏感,特别是当使用sigmoid(默认)或tanh激活函数时。需要将数据重新调整到0到1的范围(也称为标准化)。本实验使用scikit-learn库中的MinMaxScaler预处理类实现数据集的规范化。

#获取DataFrame中的数据,形式为数组array形式
values=stock_data.values
#确保所有数据为float类型
values=values.astype('float32')

# 特征的归一化处理
scaler = MinMaxScaler(feature_range=(0, 1))
scaled = scaler.fit_transform(values)
print(scaled)

归一化结果如下:

2、将数据集转化为有监督学习问题

在本文中,定义一个名为series_to_supervised()函数该函数采用单变量或多变量时间序列并将其构建为监督学习数据集。

#定义series_to_supervised()函数
#将时间序列转换为监督学习问题
def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
	"""
	Frame a time series as a supervised learning dataset.
	Arguments:
		data: Sequence of observations as a list or NumPy array.
		n_in: Number of lag observations as input (X).
		n_out: Number of observations as output (y).
		dropnan: Boolean whether or not to drop rows with NaN values.
	Returns:
		Pandas DataFrame of series framed for supervised learning.
	"""
	n_vars = 1 if type(data) is list else data.shape[1]
	df = DataFrame(data)
	cols, names = list(), list()
	# input sequence (t-n, ... t-1)
	for i in range(n_in, 0, -1):
		cols.append(df.shift(i))
		names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
	# forecast sequence (t, t+1, ... t+n)
	for i in range(0, n_out):
		cols.append(df.shift(-i))
		if i == 0:
			names += [('var%d(t)' % (j+1)) for j in range(n_vars)]
		else:
			names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]
	# put it all together
	agg = concat(cols, axis=1)
	agg.columns = names
	# drop rows with NaN values
	if dropnan:
		agg.dropna(inplace=True)
	return agg

该函数有四个参数:

  • data:输入数据需要是列表或二维的NumPy数组的观察序列。
  • n_in:输入的滞后观察数(X)。值可以在[1..len(data)]之间,可选的。默认为1。
  • n_out:输出的观察数(y)。值可以在[0..len(data)-1]之间,可选的。默认为1。
  • dropnan:Bool值,是否删除具有NaN值的行,可选的。默认为True。

该函数返回一个值:

  • 返回:用于监督学习的Pandas DataFrame。

新数据集构造为DataFrame,每列适当地由变量编号和时间步骤命名。使其可以根据给定的单变量或多变量时间序列设计各种不同的时间步长序列类型预测问题。

本文股票数据转换为监督学习问题如下:

#将时间序列转换为监督学习问题
reframed = series_to_supervised(scaled, 1, 1)
# 删除不想预测的特征列,这里只预测收益率
reframed.drop(reframed.columns[[7,8,9,10,11,12]], axis=1, inplace=True)
# 打印数据的前5行
print(reframed.head())

结果如下:

四、股票数据划分为训练集和测试集

将处理后的数据集划分为训练集和测试集。我们将2016年3月1日至2017年12月31日的股票数据作为测试集,其余作为训练集。将训练集和测试集的最终输入(X)转换为为LSTM的输入格式,即[samples,timesteps,features]

Keras LSTM层的工作方式是通过接收3维(N,W,F)的数字阵列,其中N是训练序列的数目,W是序列长度,F是每个序列的特征数目。

# 划分训练集和测试集
values = reframed.values
train = np.concatenate([values[:774, :],values[1219:,:]])
test = values[774:1219, :]
# 划分训练集和测试集的输入和输出
train_X, train_y = train[:, :-1], train[:, -1]
test_X, test_y = test[:, :-1], test[:, -1]
#转化为三维数据
# reshape input to be 3D [samples, timesteps, features]
train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))
print(train_X.shape, train_y.shape)
print(test_X.shape, test_y.shape)

训练集和测试集的输入格式如下:

五、模型构建及其预测

1、搭建LSTM模型并绘制损失图

本实验使用keras深度学习框架对模型进行快速搭建。建立Sequential模型,向其中添加LSTM层,设定Dropout为0.5,加入Dense层将其维度聚合为1,激活函数使用relu(也用了sigmoid作为激活函数,但实验效果不如relu),损失函数定为均方差Mean Absolute Error(MAE)。优化算法采用Adam,模型采用50个epochs并且每个batch的大小为100。 

其中:隐藏层有64个神经元,输出层1个神经元(回归问题),输入变量是一个时间步(t-1)的特征。在fit()函数中设置validation_data参数,记录训练集和测试集的损失。

# 搭建LSTM模型
model = Sequential()
model.add(LSTM(64, input_shape=(train_X.shape[1], train_X.shape[2])))
model.add(Dropout(0.5))
model.add(Dense(1,activation='relu'))
model.compile(loss='mae', optimizer='adam')
# fit network
history = model.fit(train_X, train_y, epochs=50, batch_size=100, validation_data=(test_X, test_y), verbose=2,shuffle=False)

# 绘制损失图
plt.plot(history.history['loss'], label='train')
plt.plot(history.history['val_loss'], label='test')
plt.title('LSTM_600000.SH', fontsize='12')
plt.ylabel('loss', fontsize='10')
plt.xlabel('epoch', fontsize='10')
plt.legend()
plt.show()

 完成训练和测试后绘制损失图如下:

2、预测并反转数据(反归一化)

需要将预测结果和测试集数据组合然后进行比例反转(invert the scaling),同时需要将测试集上的预期值也进行比例转换。 

这里为什么进行比例反转(反归一化)呢?(因为我们将原始数据进行了预处理(连同输出值y),此时的误差损失计算是在处理之后的数据上进行的,为了计算在原始比例上的误差需要将数据进行转化。反转时的矩阵大小一定要和原来的大小(shape)完全相同,否则就会报错。)

#模型预测收益率
y_predict = model.predict(test_X)
test_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))

# invert scaling for forecast
#将预测结果按比例反归一化
inv_y_test = concatenate((test_X[:, :6],y_predict), axis=1)
inv_y_test = scaler.inverse_transform(inv_y_test)
inv_y_predict=inv_y_test[:,-1]

# invert scaling for actual
#将真实结果按比例反归一化
test_y = test_y.reshape((len(test_y), 1))
inv_y_train = concatenate((test_X[:, :6],test_y), axis=1)
inv_y_train = scaler.inverse_transform(inv_y_train)
inv_y = inv_y_train[:, -1]
print('反归一化后的预测结果:',inv_y_predict)
print('反归一化后的真实结果:',inv_y)

反归一化后的部分结果如下:

3、绘制模型预测结果图

plt.plot(inv_y,color='red',label='Original')
plt.plot(inv_y_predict,color='green',label='Predict')
plt.xlabel('the number of test data')
plt.ylabel('earn_rate')
plt.title('2016.3—2017.12')
plt.legend()
plt.show()

六、模型评估

回归模型常用评价指标有:均方误差(Mean Squared Error,MAE)、均方根误差(Root Mean Squard Error,RMSE)、平均绝对误差(MAE)、R squared

本实验的LSTM模型主要采用RMSE作为评价标准。主要比较训练集误差损失train_loss和验证集误差损失val_loss和预测集误差损失pre_loss。很显然loss的值越低说明模型拟合的效果越好。

为了测试模型,使用了所有的评估指标,如下:


#回归评价指标
# calculate MSE 均方误差
mse=mean_squared_error(inv_y,inv_y_predict)
# calculate RMSE 均方根误差
rmse = sqrt(mean_squared_error(inv_y, inv_y_predict))
#calculate MAE 平均绝对误差
mae=mean_absolute_error(inv_y,inv_y_predict)
#calculate R square
r_square=r2_score(inv_y,inv_y_predict)
print('均方误差: %.6f' % mse)
print('均方根误差: %.6f' % rmse)
print('平均绝对误差: %.6f' % mae)
print('R_square: %.6f' % r_square)

结果为:

LSTM实现对股票数据进行预测(Keras实现)源代码及数据集资源下载:

LSTM实现对股票数据进行预测(Keras实现)源代码及数据集-深度学习文档类资源-CSDN下载

本实验旨在将LSTM应用于股票数据预测,通过使用LSTM对股票收益的预测,学习时间序列数据的处理和转化。使用LSTM来对股票数据的预测具有一定的可行性,但本实验效果不佳。同时可以使用此方法预测股票的价格,每日最高价等,思路相似。如果要形成一个在股票市场比较实用的 LSTM 模型,还需要在 features 选择、模型构建、模型参数选择以及调优等方面进行学习研究。

参考:

1、如何将时间序列转换为Python的监督学习问题

2、Keras中LSTM的多变量时间序列预测

3、空气污染预测

4、用于时间序列预测的LSTM神经网络

本人博文量化交易项目实战基础学习

1、Python3对股票数据进行分析项目实战源代码和股票数据资源下载

2、Python3对股票的收益和风险进行分析项目实战源代码和股票数据资源下载

3、LSTM对股票的收益进行预测(Keras实现)项目实战源代码和股票数据资源下载

4、Python3对多股票的投资组合进行分析项目实战源代码和股票数据资源下载

交流学习资料共享欢迎入群:955817470(群一),801295159(群二)

  • 82
    点赞
  • 906
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 47
    评论
以下是使用Keras构建LSTM模型进行股票预测的示例代码: ```python import numpy as np import pandas as pd from keras.models import Sequential from keras.layers import Dense, LSTM, Dropout from sklearn.preprocessing import MinMaxScaler # 载入数据 df = pd.read_csv('stock_price.csv') # 选择收盘价作为预测目标 data = df['Close'].values.reshape(-1, 1) # 归一化 scaler = MinMaxScaler(feature_range=(0, 1)) data = scaler.fit_transform(data) # 构造训练数据集 look_back = 60 # 使用前60天的数据作为输入特征 train_X, train_Y = [], [] for i in range(look_back, len(data)): train_X.append(data[i-look_back:i, 0]) train_Y.append(data[i, 0]) train_X, train_Y = np.array(train_X), np.array(train_Y) # 调整输入数据的形状 train_X = np.reshape(train_X, (train_X.shape[0], train_X.shape[1], 1)) # 构建LSTM模型 model = Sequential() model.add(LSTM(units=50, return_sequences=True, input_shape=(train_X.shape[1], 1))) model.add(Dropout(0.2)) model.add(LSTM(units=50, return_sequences=True)) model.add(Dropout(0.2)) model.add(LSTM(units=50)) model.add(Dropout(0.2)) model.add(Dense(units=1)) # 编译模型 model.compile(optimizer='adam', loss='mean_squared_error') # 训练模型 model.fit(train_X, train_Y, epochs=100, batch_size=32) # 预测未来30天的收盘价 test_X = data[-look_back:, 0] test_X = np.reshape(test_X, (1, look_back, 1)) predictions = [] for i in range(30): prediction = model.predict(test_X) predictions.append(prediction) test_X = np.append(test_X[:, 1:, :], [[prediction]], axis=1) # 反归一化 predictions = scaler.inverse_transform(predictions) # 输出预测结果 print(predictions) ``` 其中,`stock_price.csv`是包含股票历史价格数据的CSV文件,第一列为日期,第五列为收盘价。该模型使用前60天的收盘价数据作为输入特征,训练LSTM模型,并使用该模型预测未来30天的收盘价。
评论 47
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Asia-Lee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值