本文将从原理到实战,详细讲解长短期记忆网络(LSTM)在股票时间序列预测中的应用,拆解核心机制、数据预处理流程与模型训练要点,并提供基于 Python 的完整可运行代码,帮助你快速上手 LSTM 时间序列建模。

前言

在量化交易与金融数据分析领域,股票价格预测一直是极具挑战性的课题。传统机器学习方法如 XGBoost 虽在结构化数据上表现优异,但难以有效捕捉时间序列数据中的长期依赖关系,容易忽略历史趋势对未来的影响。

而 LSTM(Long Short-Term Memory,长短期记忆网络)作为循环神经网络(RNN)的改进版本,完美解决了 RNN 的梯度消失问题,能够像经验丰富的分析师一样,精准记住历史数据中的关键规律,自动过滤无关杂音,成为时间序列预测的首选算法。

一、什么是 LSTM?

简单来说,LSTM 就像一个具备 "选择性记忆" 能力的股票分析师。它的核心优势在于能够分辨:

  • 哪些信息需要长期记住(如持续数月的牛市 / 熊市趋势)
  • 哪些信息可以直接忽略(如某天因偶然事件导致的股价波动)

这种特性让 LSTM 在处理股票、气象、商品销量、工业设备故障等时间序列数据时,表现远超传统统计方法和基础机器学习算法。

二、LSTM 的三大 "智能开关"(核心门控机制)

LSTM 之所以能实现精准的记忆与过滤,依靠的是其内部三个独立的门控单元,它们就像三个智能开关,协同控制信息的流动:

1. 遗忘门:负责 "断舍离"

核心功能:判断哪些历史信息已经过时,将其从细胞的长期记忆中丢弃。股票场景举例:如果央行突然宣布加息,市场整体环境发生根本性变化,遗忘门会自动降低模型对过去低利率时期股价运行规律的依赖,避免用旧经验判断新市场。

2. 输入门:负责 "抓重点"

核心功能:识别当前输入中的重要信号,并将其更新到细胞的长期记忆中。股票场景举例:当某只股票同时出现 "成交量暴增 + 突破关键压力位 + 北向资金大幅流入" 的组合特征时,输入门会判定这是强上涨信号,将其重点记录到长期记忆中。

3. 输出门:负责 "做决策"

核心功能:结合长期记忆和当前输入信息,输出最终的预测结果。股票场景举例:如果模型记住了过去 3 个月股票处于震荡上行的长期趋势,同时当前输入显示公司发布了重大利好公告,输出门会综合判断,给出次日股价上涨概率更高的预测。

三、股票预测的数据准备三大步骤

数据是模型的基石,高质量的数据预处理直接决定了 LSTM 模型的预测效果。针对股票数据,我们需要完成以下三个核心步骤:

1. 数据清洗

原始股票数据往往存在错误和缺失,需要先进行清洗:

  • 删除异常数据:如股价突然归零、成交量为负数、涨跌幅超出 ±10%(ST 股 ±5%)等系统故障或错误记录
  • 补全缺失值:如节假日、停牌日的缺失数据,可采用前后两天的平均值、线性插值或同行业指数涨跌幅填充

2. 特征加工

单一的收盘价数据无法全面反映股票的运行状态,建议加工多维度特征:

  • 基础特征:每日开盘价、收盘价、最高价、最低价、成交量、成交额
  • 技术指标:5 日 / 10 日 / 20 日 / 60 日均线、MACD、RSI、布林带、KDJ 等,用于判断趋势和买卖力道
  • 外部特征:对应行业指数走势、沪深 300 大盘指数、宏观经济数据(如利率、CPI)、新闻情绪分(用 AI 判断财经新闻的利好 / 利空程度)

3. 时间切片

LSTM 模型需要以 "时间窗口" 的形式输入数据,即将连续的时间序列切分为多个独立样本:

  • 输入:过去 N 天(本文采用 60 天)的所有特征数据
  • 输出:第 N+1 天的收盘价或涨跌概率

例如,我们用 2020 年 1 月 1 日 - 2020 年 3 月 1 日(60 天)的价格、成交量数据,来预测 2020 年 3 月 2 日的收盘价。

四、LSTM 模型训练的三个关键要点

1. 试错学习:反向传播优化

模型训练的本质是 "试错 - 修正" 的迭代过程。模型先根据初始参数对历史数据进行预测,如果预测结果与实际值存在偏差(如实际下跌却预测上涨),就会通过反向传播算法自动调整各层神经元的权重参数,类似于学生通过错题本修正自己的知识盲点。

2. 防止过拟合:避免 "死记硬背"

过拟合是指模型在训练集上表现极好,但在测试集上泛化能力极差,本质是模型 "死记硬背" 了训练数据的所有细节,而没有学到通用规律。常用的解决方法有:

  • 早停法:监控验证集的损失值,如果连续多个 epoch(如 10 次)损失值没有下降,立即停止训练
  • 随机屏蔽(Dropout):训练时随机关闭部分神经元,强迫模型学习多种特征组合,避免依赖单一特征

五、完整可运行代码实现

以下代码基于 Python 实现,使用 akshare 免费获取 A 股历史数据,TensorFlow/Keras 构建 LSTM 模型,最终实现股票收盘价预测与可视化。

环境依赖安装

首先安装所需的 Python 库:

pip install akshare pandas numpy scikit-learn tensorflow plotly

完整代码

import akshare as ak
import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout
import plotly.graph_objects as go
from datetime import datetime

# 获取A股股票历史数据(前复权)
def get_stock_data(stock_code, start_date, end_date):
    """
    参数:
        stock_code: 股票代码,如"600519"(贵州茅台)
        start_date: 开始日期,datetime对象
        end_date: 结束日期,datetime对象
    返回:
        包含每日行情的DataFrame
    """
    start_date_str = start_date.strftime("%Y%m%d")
    end_date_str = end_date.strftime("%Y%m%d")
    stock_zh_a_hist_df = ak.stock_zh_a_hist(
        symbol=stock_code,
        period="daily",
        start_date=start_date_str,
        end_date=end_date_str,
        adjust="qfq"  # 前复权,消除除权除息影响
    )
    return stock_zh_a_hist_df

# 数据预处理:Min-Max归一化
def preprocess_data(data):
    """
    将收盘价数据缩放到[0,1]区间,提升模型训练效率和收敛速度
    """
    scaler = MinMaxScaler(feature_range=(0, 1))
    scaled_data = scaler.fit_transform(data[["收盘"]].values)
    return scaled_data, scaler

# 创建LSTM所需的训练数据集
def create_dataset(dataset, time_step=60):
    """
    将一维时间序列转换为LSTM要求的三维输入格式 [样本数, 时间步, 特征数]
    参数:
        dataset: 归一化后的数据集
        time_step: 时间窗口大小,即使用过去多少天的数据预测未来
    返回:
        X: 输入特征
        Y: 预测标签(第time_step+1天的收盘价)
    """
    dataX, dataY = [], []
    for i in range(len(dataset) - time_step - 1):
        a = dataset[i:(i + time_step), 0]
        dataX.append(a)
        dataY.append(dataset[i + time_step, 0])
    return np.array(dataX), np.array(dataY)

# 构建双层LSTM模型(加入Dropout防止过拟合)
def build_lstm_model(input_shape):
    """
    模型结构:LSTM(50) -> Dropout(0.2) -> LSTM(50) -> Dropout(0.2) -> Dense(25) -> Dense(1)
    """
    model = Sequential()
    # 第一层LSTM,返回序列用于下一层LSTM
    model.add(LSTM(50, return_sequences=True, input_shape=input_shape))
    model.add(Dropout(0.2))
    # 第二层LSTM
    model.add(LSTM(50, return_sequences=False))
    model.add(Dropout(0.2))
    # 全连接层
    model.add(Dense(25))
    # 输出层:预测收盘价
    model.add(Dense(1))
    # 编译模型:Adam优化器 + 均方误差损失函数(回归任务常用)
    model.compile(optimizer='adam', loss='mean_squared_error')
    return model

# 主执行流程
if __name__ == "__main__":
    # 1. 获取数据(以贵州茅台600519为例)
    start_date = datetime(2020, 1, 1)
    end_date = datetime(2026, 5, 8)
    stock_data = get_stock_data("600519", start_date, end_date)
    print(f"数据获取完成,共{len(stock_data)}条历史记录")

    # 2. 数据归一化
    scaled_data, scaler = preprocess_data(stock_data)

    # 3. 划分训练集和测试集(80%训练,20%测试)
    training_size = int(len(scaled_data) * 0.8)
    test_size = len(scaled_data) - training_size
    train_data = scaled_data[0:training_size, :]
    test_data = scaled_data[training_size:len(scaled_data), :]

    # 4. 构建训练和测试数据集
    time_step = 60  # 使用过去60天的数据预测第61天
    X_train, y_train = create_dataset(train_data, time_step)
    X_test, y_test = create_dataset(test_data, time_step)

    # 5. 调整输入形状为LSTM要求的三维格式
    X_train = X_train.reshape(X_train.shape[0], X_train.shape[1], 1)
    X_test = X_test.reshape(X_test.shape[0], X_test.shape[1], 1)
    print(f"训练集形状:{X_train.shape}")
    print(f"测试集形状:{X_test.shape}")

    # 6. 构建并训练模型
    model = build_lstm_model((X_train.shape[1], 1))
    history = model.fit(
        X_train, y_train,
        batch_size=32,
        epochs=100,
        validation_data=(X_test, y_test)
    )

    # 7. 模型预测
    train_predict = model.predict(X_train)
    test_predict = model.predict(X_test)

    # 8. 反归一化,将预测结果转换为实际价格
    train_predict = scaler.inverse_transform(train_predict)
    test_predict = scaler.inverse_transform(test_predict)
    y_train_actual = scaler.inverse_transform(y_train.reshape(-1, 1))
    y_test_actual = scaler.inverse_transform(y_test.reshape(-1, 1))

    # 9. 可视化预测结果
    # 构造绘图数据
    train_plot = np.empty_like(scaled_data)
    train_plot[:, :] = np.nan
    train_plot[time_step:len(train_predict) + time_step, :] = train_predict

    test_plot = np.empty_like(scaled_data)
    test_plot[:, :] = np.nan
    test_plot[len(train_predict) + (time_step * 2) + 1:len(scaled_data) - 1, :] = test_predict

    # 绘制交互式对比图
    fig = go.Figure()
    fig.add_trace(go.Scatter(
        x=stock_data['日期'],
        y=scaler.inverse_transform(scaled_data)[:, 0],
        name='实际收盘价',
        line=dict(color='blue', width=1.5)
    ))
    fig.add_trace(go.Scatter(
        x=stock_data['日期'],
        y=train_plot[:, 0],
        name='训练集预测',
        line=dict(color='green', width=1.5)
    ))
    fig.add_trace(go.Scatter(
        x=stock_data['日期'],
        y=test_plot[:, 0],
        name='测试集预测',
        line=dict(color='red', width=1.5)
    ))
    fig.update_layout(
        title='LSTM股票收盘价预测(贵州茅台 600519)',
        xaxis_title='日期',
        yaxis_title='收盘价(元)',
        hovermode='x unified',
        template='plotly_white'
    )
    fig.show()

六、注意事项与总结

重要注意事项

  1. 投资风险提示:股票价格受宏观经济、政策、突发事件等多种不可控因素影响,LSTM 模型只能基于历史数据学习规律,无法预测黑天鹅事件。本文内容仅用于技术学习交流,不构成任何投资建议。
  2. 特征工程是关键:单一的收盘价特征预测效果有限,建议加入更多技术指标、行业指数和舆情数据,可显著提升模型精度。
  3. 参数调优:可通过调整时间窗口大小、LSTM 神经元数量、批次大小、训练轮数、Dropout 比例等参数,进一步优化模型性能。

总结

LSTM 作为处理时间序列数据的经典算法,在股票预测领域展现出了强大的能力。本文从原理到实战,详细讲解了 LSTM 的核心门控机制、数据预处理流程和模型训练方法,并提供了完整可运行的 Python 代码。

掌握本文内容后,你不仅能实现股票收盘价预测,还能将 LSTM 模型迁移到销量预测、气象预报、工业设备故障检测等其他时间序列预测场景中。

📜 完整免责申明

  1. 技术性质声明:本文为纯技术分享文章,所有内容仅用于人工智能与时间序列分析的学术研究和学习交流,不涉及任何金融产品的推广、销售或投资指导。
  2. 数据责任声明:本文使用的股票数据来源于第三方开源接口 akshare,作者不对数据的准确性、完整性、及时性和合法性承担任何责任。因数据错误导致的任何后果,均由数据提供方和使用者自行承担。
  3. 投资责任声明:所有投资决策均具有高度风险性,投资者应当结合自身风险承受能力,在咨询持牌金融机构和专业投资顾问后独立做出。任何依据本文内容、代码、预测结果或观点进行的投资操作,所产生的一切直接或间接损失,作者不承担任何民事、刑事或行政法律责任。
  4. 转载与使用声明:本文为原创技术文章,转载请注明作者和出处。禁止将本文内容用于商业用途、非法金融活动或任何违法违规行为。
  5. 观点独立性声明:本文仅代表作者个人技术观点,不构成任何机构、公司或组织的官方立场。文中提及的所有股票代码仅作技术演示使用,不代表对其投资价值的任何评价。
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐