基于LSTM的沪深股票价格预测

摘要

(Tushare ID:412919)
股票市场是国民经济发展变化的“晴雨表”和“报警器”,其行情的变化与国家的宏观经济发展、法律法规的制定、政治事件的发生、公司的财务状况和政策、投资者心理、舆论引导等等都有所关联。因此,在学习深度学习后,使用LSTM对从Tushare平台获取的沪深股票日线行情数据进行训练,将前60天的开盘价作为模型的输入,第61天的开盘价作为标签,对模型进行训练,并使用平均绝对误差(MAE)、相关系数、误差均方(MSE)进行评估,结果表明,在训练50次后,LSTM的预测效果最佳。

一、长短期记忆人工神经网络(LSTM)

长短期记忆神经网络(LSTM)是由Hochreiter和Schmidhuber提出的一种特殊的循环神经网络,主要是为了解决长序列数据在训练过程中的梯度消失和梯度爆炸问题,相比于RNN,LSTM神经网络可以在更长的序列中取得较好的效果,能够对有价值的信息进行长期的记忆。LSTM神经网络的神经单元结构如下图所示,其中包含了输入门i(t)、遗忘门f(t)、输出门o(t_和记忆单元C_t。输入门控制当前计算的新状态以多大程度更新到记忆单元中;遗忘门控制前一步记忆单元中的信息有多大程度被遗忘掉;输出门控制当前的输出在多大程度上取决于当前的记忆单元。

LSTM神经网络的核心思想是在网络中每个神经元中维护一个细胞(cell)存储状态信息,同时设置三个逻辑门———输入门(i(t))、遗忘门(f(t))、输出门(o(t))———来控制cell增加或者去除保存的信息。这些门使LSTM具备长期依赖的功能,同时避免梯度爆炸或者梯度消失的问题。计算公式中各符号含义分别为:
(1) X_t : t时刻神经元的输入;
(2) h_t : t时刻神经元的输出;
(3) tanh、ẟ:神经元激活函数(activation function);
(4) w_i、w_f、w_c、w_o : 权重矩阵;
(5) b_i、b_f、b_c、b_o : 阈值向量;
(6) C_t:t时刻神经元细胞状态。
LSTM在t时刻的输出h_t为
h_t=o(t)+tanh⁡(c_t ) (1)
其中,
O(t)=ẟ(W_0∙x_t+U_0∙h_(t-1)+b_0) (2)
c_t=f(t)∙c_(t-1)+i_t∙〖c^’〗t (3)
f(t)=σ(W_f∙x_t+U_f∙h
(t-1)+b_f) (4)
i(t)=σ(W_i∙x_t+U_i∙h_(t-1)+b_i) (5)
〖c^’〗t=tanh⁡(W_c∙x_t+U_c∙h(t-1) ) (6)
LSTM神经网络的神经单元结构中的门控结构使用的是Sigmoid激活函数和tanh激活函数。其中sigmoid函数为
f(x)=1/(1+e^(-x) ) (7)
tanh函数为
f(x)=(ex-e(-x))/(ex+e(-x) ) (8)
两者的区别在于Sigmoid函数的值域为(0,1),而tanh函数的值域为(-1,1)。两个激活函数都是随着变量x的增大而增大,以实现门控结构的作用。

二、数据集介绍

本文使用的数据集是利用Tushare提供的股票数据接口获取到的沪深股票日线行情数据,该数据集一共包含11列数据,包括:股票代码(ts_code)、交易日期(trade_date)、收盘价格 (close)、开盘价格(open)、当日最高价(high)、当日最低价(low)、昨日收盘价格(pre_close)、涨跌额(change)、涨跌幅(pct_chg)、成交量(vol)、成交额(amount)。该数据集包含了2000年1月11日至2020年4月1日之间共计9999条的股票数据,其数据形式如下表所示。
在这里插入图片描述
数据获取代码:

from sqlalchemy import create_engine
import tushare as ts
ts.set_token('tushare提供的token')
pro = ts.pro_api()
df = pro.daily(ts_code='000001.SZ,600000.SH', start_date='20100102', end_date='20210430')

engine = create_engine("mysql+pymysql://root:123456@localhost:3306/fund")
df.to_sql(name='info', con=engine, if_exists='append')

三、实验流程

在这里插入图片描述

四、基于双层LSTM的Python代码实现

import tensorflow as tf
import time
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from keras.layers import LSTM, SimpleRNN, Dropout,Dense,GRU
from keras import layers
from keras import models
from keras import Sequential
from sklearn import preprocessing

import pymysql
plt.rc('font', family='simhei', size=15)
plt.rc('axes', unicode_minus=False)
class MySQLDB():
    def __init__(self, host="127.0.0.1", port=3306, user="root", password="123456",
                 database="fund"):
        try:
            self.conn = pymysql.connect(host=host, port=port, user=user, password=password, database=database)
            self.cursor = self.conn.cursor()
        except Exception as e:
            print("数据库连接异常")
    def selectall(self):
        sql = 'select * from info where ts_code="000001.SZ" and trade_date>="20110401" and trade_date<="20200401"'
        self.cursor.execute(sql)
        col_name_list = [tuple[0] for tuple in self.cursor.description]
        results = self.cursor.fetchall()
        df = pd.DataFrame(results, columns=col_name_list)
        df.sort_values(by=["trade_date"], inplace=True, ascending=True) #对表格数据进行排序操作
        self.time = df['trade_date'].values
        self.data = df.drop(["index", "ts_code", "trade_date"], axis=1)
        col_name_list.remove("index")
        col_name_list.remove("ts_code")
        col_name_list.remove("trade_date")
        # print(col_name_list)
        self.columns = col_name_list
        for index in range(0, len(self.time)):
            temp = list(self.time[index])
            temp.insert(4, '-')
            temp.insert(7, '-')
            temp = ''.join(temp)
            self.time[index] = temp
    def countmae(self,arr1, arr2):
        sums = 0
        for index in range(len(arr1)):
            sums += abs(arr1[index]-arr2[index])
        print("平均绝对误差为:"+str(sums/len(arr1)))
    def countmse(self,arr1, arr2):
        sums = 0
        for index in range(len(arr1)):
            sums += abs(arr1[index] - arr2[index])**2
        print("均方误差为:" + str(sums / len(arr1)))
    def precessing(self):
        scaler = preprocessing.MinMaxScaler()
        # self.precess = pd.DataFrame(scaler.fit_transform(self.data), columns=self.columns)
        train_set = self.data.iloc[0:1200, 0:1].values
        test_set = self.data.iloc[1200:, 0:1].values
        train_set = scaler.fit_transform(train_set)
        test_set = scaler.fit_transform(test_set)
        x_train = []
        y_train = []
        x_test = []
        y_test = []
        for index in range(60, len(train_set)):
            x_train.append(train_set[index-60:index, 0])
            y_train.append(train_set[index, 0])
        np.random.seed(7)
        np.random.shuffle(x_train)
        np.random.seed(7)
        np.random.shuffle(y_train)
        x_train, y_train = np.array(x_train), np.array(y_train)
        x_train = np.reshape(x_train, (x_train.shape[0], 60, 1))
        for index in range(60, len(test_set)):
            x_test.append(test_set[index-60:index, 0])
            y_test.append(test_set[index, 0])
        x_test, y_test = np.array(x_test), np.array(y_test)
        x_test = np.reshape(x_test, (x_test.shape[0], 60, 1))
        model = Sequential([
            LSTM(60, return_sequences=True),
            Dropout(0.2),
            LSTM(60),
            Dropout(0.2),
            Dense(1)
        ])
        model.compile(optimizer='adam', loss='mean_squared_error')
        model.fit(x_train, y_train, batch_size=10, epochs=50)
        y_tests = model.predict(x_test)
        y_tests = scaler.inverse_transform(y_tests)
        y_tests = np.reshape(y_tests, (y_tests.shape[0]))
        y_test = scaler.inverse_transform(np.reshape(y_test, (y_test.shape[0], 1)))
        y_test = np.reshape(y_test, (y_test.shape[0]))
        my_rho = np.corrcoef(y_tests, y_test)
        print("预测值与真实值之间的相关性:"+str(my_rho[0][1]))
        x = pd.date_range(self.time[1260], periods=len(y_test))
        self.countmae(y_test, y_tests)
        self.countmse(y_tests, y_test)
        plt.plot(x, y_test, c='g', label="真实值")
        plt.plot(x, y_tests, c='r', label="预测值")
        plt.xlabel("日期")
        plt.ylabel("开盘价")
        plt.title("基于LSTM神经网络的股票价格预测")
        plt.legend()
        plt.gcf().autofmt_xdate()
        plt.show()
mysqldb = MySQLDB()
mysqldb.selectall()
mysqldb.precessing()

五、实验结果

基于LSTM神经网络的沪深股票下一日开盘价预测结果:
在这里插入图片描述
基于GRU神经网络的沪深股票下一日开盘价预测结果:
在这里插入图片描述
基于RNN神经网络的沪深股票下一日开盘价预测结果:
在这里插入图片描述

六、结束语

从模型评价结果,LSTM神经网络模型的平均绝对误差(MAE)为0.159754,误差均方(MSE)为0.056972,相关系数(ẟ)为0.994964;RNN神经网络模型的平均绝对误差(MAE)为0.188044,误差均方(MSE)为0.064974,相关系数(ẟ)为0.994947;GRU神经网络模型的平均绝对误差(MAE)为0.235536,误差均方(MSE)为0.099653,相关系数(ẟ)为0.995105;总的来看,LSTM神经网络的预测效果最好,其预测值与真实值之间的相关系数与其他两个模型相近,但平均绝对误差(MAE)、误差均方(MSE)最小。

  • 30
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

dream1909

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

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

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

打赏作者

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

抵扣说明:

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

余额充值