Keras-LSTM:股价预测(lstm预测股票涨跌)

sddy008 理财百科 2023-01-11 155 5

简介

任务:利用Keras建立LSTM模型,基于股票历史价格实现对未来对预测。

模型整体结构:双层LSTM+全连接层

说明:以下只是部分代码,如需完整代码,可留邮箱,欢迎交流。

获取数据

利用tushare接口获取股票历史信息;将数据索引改为datatime格式,并按其排序。

def get_home_data(num, start, end): tushare接口获取dataframe数据,数据索引为datetime格式,并按照datetime升序排列。 :param num:str,stock code :param start:str,like 2019-08-01 :param end:str,like 2019-08-01 :return:dataframe,index is datetime and ascending by datetime try: data_df = ts.get_hist_data(num, start=start, end=end) data_df.index = data_df.index.astype(datetime64[ns]) data_df = data_df.sort_index() print(股票数据获取完成!) return data_df except Exception: print(股票获取失败!) data = get_home_data(600570, 2018-09-01, 2019-11-05)

特征选取

选择收盘价为历史特征,并转为array数据结构。后续可选择其他的特征做尝试。

array = data[close].values if array.ndim == 1: array = array.reshape(-1, 1)

数据预处理

将数据标准化。后续可对数据噪声处理做尝试。

def preprocess(array): :param data: numpy :return: from sklearn.preprocessing import MinMaxScaler scl = MinMaxScaler() array = scl.fit_transform(array) return array, scl normalize_data, scl = preprocess(array)

切分训练数据和测试数据

将预处理后的数据切分,具体代码如下。forward_days代表所要预测forward_days天的股票价格,将最新的num_periods*forward_days天的数据作为模型的测试数据。代码第二行,测试数据需包括前look_back天,以便对测试数据做预测。

division = len(normalize_data) - config.num_periods * config.forward_days array_test = normalize_data[division - config.look_back:] array_train = normalize_data[:division]

因训练数据和测试数据构造训练集和测试集的步长不一致,因此需在构造样本前先切分。步长不一致的原因是为了模型在测试数据效果的可视化。

构造LSTM样本

具体代码如下所示。LSTM模型的时间步长为look_back变量,对未来forward_days天的价格做预测。以时间步长为1建立训练集,以时间步长forward_days建立测试集合。对测试集合进行forward_days处理的目的是为了后续可视化。

def sample_to_data(data, look_back=40, forward_days=10, jump=1): X, Y = [], [] for i in range(0, len(data) - look_back - forward_days + 1, jump): X.append(data[i:(i + look_back)]) Y.append(data[(i + look_back):(i + look_back + forward_days)]) return np.array(X), np.array(Y) X, y = sample_to_data(array_train, config.look_back, config.forward_days) X_test, y_test = sample_to_data(array_test, config.look_back, config.forward_days, config.forward_days)

训练集切分为训练集和验证集

验证集用于调参

from sklearn.model_selection import train_test_split X_train, X_validate, y_train, y_validate = train_test_split(X, y, test_size=0.20, random_state=42)

训练模型

定义模型结构

model = Sequential() model.add(LSTM(NUM_NEURONS_FirstLayer, input_shape=(config.look_back, 1), return_sequences=True)) model.add(LSTM(NUM_NEURONS_SecondLayer)) model.add(Dense(config.forward_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)

训练过程画图,可根据此图判断模型拟合程度,进而调参。

plot_figure(history.history,[loss,val_loss])

模型在测试集效果

测试集送入模型

Xt = model.predict(X_test)

画出测试集的预测效果和真实值做对比。首先将模型预测的价格反向标准化,分段画出并标记为红色;其次,将真实值反向标准化画出。

plt.figure(figsize=(15, 10)) for i in range(0, len(Xt)): plt.plot([x + i * config.forward_days for x in range(len(Xt[i]))], scl.inverse_transform(Xt[i].reshape(-1, 1)), color=r) plt.plot(0, scl.inverse_transform(Xt[0].reshape(-1, 1))[0], color=r, label=Prediction) # 巧妙对分段函数进行标注 plt.plot(scl.inverse_transform(y_test.reshape(-1, 1)), label=Target) plt.legend(loc=best) plt.show()

模型在训练集和测试集的效果

准备对训练集进行预测,为了保证计算计算训练集从哪个位置开始

division = len(normalize_data) - config.num_periods*config.forward_days leftover = division%config.forward_days while(leftover<config.look_back): leftover+=config.look_back array_train = normalize_data[leftover-config.look_back:division] array_test = normalize_data[division-config.look_back:] Xtrain,ytrain = sample_to_data(array_train,config.look_back,config.forward_days,config.forward_days) Xtest,ytest = sample_to_data(array_test,config.look_back,config.forward_days,config.forward_days) Xtrain = model.predict(Xtrain) Xtrain = Xtrain.ravel() Xtest = model.predict(Xtest) Xtest = Xtest.ravel() y = np.concatenate((ytrain, ytest), axis=0) plt.figure(figsize = (15,10)) # Data in Train/Validation plt.plot([x for x in range(leftover, len(Xtrain)+leftover)], scl.inverse_transform(Xtrain.reshape(-1,1)), color=r, label=Train) # Data in Test plt.plot([x for x in range(leftover+ len(Xtrain), len(Xtrain)+len(Xtest)+leftover)], scl.inverse_transform(Xtest.reshape(-1,1)), color=y, label=Test) #Data used plt.plot([x for x in range(leftover, leftover+len(Xtrain)+len(Xtest))], scl.inverse_transform(y.reshape(-1,1)), color=b, label=Target) plt.legend(loc=best) plt.show()

需改进之处:

特征只选了股票收盘价,可在ma值等方面做尝试。数据预处理太单薄,可增加平滑处理等做尝试。各时间段样本权重不应相同,可对近时间样本加权做尝试。样本数量还是过少,结合多只股票数据训练会不会更好。模型直接输出了股票未来段时间的价格,忽略了段时间价格彼此是联系的,后续需对模型结果做改进,在预测一天股价对基础上,再对下一天做预测。这也是所预测段时间价格趋势相同的原因,是极为不合理的。直接预测股价有局限性,转为分类任务会不会更好,类别为大涨、小涨、小跌、大跌。学习回测系统,实际查看模型表现。强化学习和LSTM的结合。

评论

精彩评论
2024-08-03 21:12:48

精华帖的节奏啊!http://33q.sy00066.com

2024-08-09 16:03:59

论坛人气好旺!http://87vq60.dbbdoor.com

2024-08-26 13:41:22

有钱、有房、有车,人人都想!http://ret.zjqf05.com

2024-09-02 16:32:30

这么版块的帖子越来越有深度了!http://www.a5km.com/yxgl/dnf/23489.html