首页/新闻资讯/正文详情

LSTM股票基金预测实战:从akshare数据到PyTorch模型回测

发布时间:2026/9/25 2:05:22 来源:云帆数科 栏目:资讯中心
LSTM股票基金预测实战:从akshare数据到PyTorch模型回测
简介这份资源是面向机器学习初学者与高校学生的LSTM股票/基金预测实战项目适合用作课程设计、期末大作业或入门时序预测的练手案例。压缩包共11个文件约155KB包含3个Python脚本负责模型搭建与数据获取、5个xlsx表格存放训练集、测试集及预测结果、1份README说明文档另有1张运行结果图和1个缓存文件结构紧凑、开箱即用。项目围绕长短期记忆网络对基金与股票净值走势建模涵盖数据读取、特征整理、模型训练与预测输出等完整环节可直接对照代码理解LSTM在金融时序上的应用思路。目前已有224人学习下载适合想快速跑通一个完整预测流程、积累项目经验的读者参考借鉴。1. 从一份高分项目压缩包说起LSTM 做股票/基金预测到底靠不靠谱很多人第一次接触基于机器学习 LSTM 的股票/基金预测模型这个标题是在课程设计、毕设选题或者简历项目里。压缩包解压出来通常是一份 Jupyter Notebook、一份 CSV 数据、一张预测曲线对比图跑一遍发现拟合得还挺像于是心里犯嘀咕这玩意儿真能拿来炒股吗先把结论摆前面——LSTM 做股票/基金预测能做出一个工程上完整、指标上好看的模型但它不是印钞机。它擅长的是从历史量价序列里学出短期趋势和波动模式而不是预测明天涨停。这个方向真正值钱的地方是让你完整走一遍数据获取 → 特征工程 → 序列建模 → 回测评估的量化流水线这套能力放到设备寿命预测、销量预测、流量预测上都能复用。适合读这篇的人有三类一是要交课程设计或毕设、需要一份能跑通、能讲清楚原理的项目二是想入门量化、用 Python 机器学习做点股票组合分析练手的工程师三是已经会调sklearn但没系统做过时间序列、想搞明白 LSTM 时间序列预测 Python 实现细节的人。下面我按自己实际做过的路径把数据怎么拿、模型怎么搭、参数怎么调、哪里最容易翻车一条条讲清楚。2. 数据从哪来、怎么变成 LSTM 能吃的序列2.1 用 akshare 获取股票数据最小可用代码做股票预测第一步永远是数据。国内免费数据源里akshare是这几年用得比较多的一个接口稳定、字段全取 A 股日线一行代码就够。我一般先拉一只票的日线确认字段结构再批量拉。import akshare as ak import pandas as pd # 拉取贵州茅台日线adjustqfq 表示前复权 df ak.stock_zh_a_hist( symbol600519, perioddaily, start_date20180101, end_date20241231, adjustqfq ) # 统一列名方便后续处理 df df.rename(columns{ 日期: date, 开盘: open, 收盘: close, 最高: high, 最低: low, 成交量: volume }) df[date] pd.to_datetime(df[date]) df df.sort_values(date).reset_index(dropTrue) print(df.shape, df.columns.tolist()) print(df.tail(3))逻辑说明stock_zh_a_hist返回的是中文列名先重命名成英文避免后面写特征时中英混用。adjustqfq是关键参数前复权能消除分红送股造成的价格跳空否则模型会把这些跳空当成真实波动去学预测必然失真。period可选daily/weekly/monthly做 LSTM 短期预测一般用日线。参数上start_date建议至少给 3 年以上LSTM 是数据饥渴型模型样本太少学不出东西。提示akshare接口偶尔会因为数据源调整而字段变动跑之前先print(df.columns)确认一遍别直接硬编码列名。2.2 特征工程别只喂收盘价新手最容易犯的错是把close一列丢进 LSTM 就完事。单变量序列能跑但信息量太低模型学不到量价关系。我一般会构造一组基础特征让模型有东西可学特征名计算方式作用ret_1close.pct_change(1)日收益率平稳性比价格好ma5 / ma20close.rolling(n).mean()短期/中期趋势vol_ratiovolume / volume.rolling(5).mean()放量缩量信号high_low(high - low) / close当日振幅close_ma20close / ma20 - 1偏离均线程度df[ret_1] df[close].pct_change() df[ma5] df[close].rolling(5).mean() df[ma20] df[close].rolling(20).mean() df[vol_ratio] df[volume] / df[volume].rolling(5).mean() df[high_low] (df[high] - df[low]) / df[close] df[close_ma20] df[close] / df[ma20] - 1 # 预测目标下一日收益率 df[target] df[close].pct_change().shift(-1) df df.dropna().reset_index(dropTrue)逻辑说明pct_change把绝对价格转成收益率这是时间序列建模的常规操作因为价格是非平稳的直接喂给模型容易过拟合趋势。shift(-1)是把明天的收益率对齐到今天这一行这是构造监督学习标签的标准做法方向千万别搞反shift(1)就变成用未来预测现在了。dropna会砍掉前面均线没算出来的行正常损失 20 行左右。2.3 滑动窗口把表格变成三维张量LSTM 要的输入是(样本数, 时间步, 特征数)的三维张量所以得用滑动窗口把二维表切成序列。窗口长度seq_len是核心参数我一般取 20 或 30对应一个月左右的交易日。import numpy as np def make_sequences(data, target, seq_len20): X, y [], [] for i in range(len(data) - seq_len): X.append(data[i:i seq_len]) # 过去 seq_len 天 y.append(target[i seq_len]) # 第 seq_len1 天的收益 return np.array(X), np.array(y) feat_cols [ret_1, ma5, ma20, vol_ratio, high_low, close_ma20] X, y make_sequences(df[feat_cols].values, df[target].values, seq_len20) print(X.shape, y.shape) # (N, 20, 6)逻辑说明循环里data[i:iseq_len]取窗口target[iseq_len]取窗口后一天保证不泄露未来信息。seq_len太小比如 5模型看不到趋势太大比如 120样本数骤减且容易过拟合20~30 是日线数据的经验区间。特征维度这里是 6后面模型输入层要跟它对齐。注意划分训练集/测试集时绝对不能随机打乱时间序列必须按时间先后切否则就是典型的数据泄露测试集指标会虚高得离谱。3. PyTorch LSTM 模型搭建与训练从网络结构到早停3.1 LSTM 单元在学什么门控机制一句话讲透LSTM长短期记忆网络Long Short-Term Memory1997 年由 Hochreiter 和 Schmidhuber 提出核心是三个门遗忘门决定丢掉多少旧记忆输入门决定写入多少新信息输出门决定当前输出多少。相比普通 RNN它靠这条细胞状态高速公路缓解了梯度消失所以能记住几十步之前的信息。放到股票场景就是让模型自己判断20 天前的放量对明天涨跌还有没有参考价值。你不需要手推公式但要理解一点LSTM 的记忆能力是有代价的序列越长、参数越多越容易在小样本上过拟合这也是为什么股票预测里 LSTM 经常训练集完美、测试集拉胯。3.2 一个能直接跑的 PyTorch LSTM 源码下面是我常用的最小模型结构两层 LSTM 加一层全连接带 Dropout 防过拟合。import torch import torch.nn as nn class LSTMModel(nn.Module): def __init__(self, input_size, hidden_size64, num_layers2, dropout0.3): super().__init__() self.lstm nn.LSTM( input_sizeinput_size, hidden_sizehidden_size, num_layersnum_layers, batch_firstTrue, # 输入格式 (batch, seq, feature) dropoutdropout ) self.fc nn.Linear(hidden_size, 1) def forward(self, x): out, _ self.lstm(x) # out: (batch, seq, hidden) out out[:, -1, :] # 只取最后一个时间步 return self.fc(out).squeeze(-1) model LSTMModel(input_sizelen(feat_cols)) print(model)逻辑说明batch_firstTrue让输入维度是(batch, seq_len, feature)跟前面构造的X对齐忘了设这个参数是最常见的翻车点会报维度不匹配。out[:, -1, :]只取最后一个时间步的隐状态因为我们要预测的是窗口之后那一天前面时间步的输出对最终预测没直接用途。hidden_size64、num_layers2是中小数据集的稳妥起点数据量上万条可以加到 128。dropout0.3只在多层 LSTM 之间生效单层时这个参数无效。3.3 训练循环与早停参数怎么设from torch.utils.data import TensorDataset, DataLoader # 按时间切分前 80% 训练后 20% 测试 split int(len(X) * 0.8) X_train, X_test X[:split], X[split:] y_train, y_test y[:split], y[split:] train_ds TensorDataset(torch.tensor(X_train, dtypetorch.float32), torch.tensor(y_train, dtypetorch.float32)) train_loader DataLoader(train_ds, batch_size64, shuffleFalse) # 不打乱 criterion nn.MSELoss() optimizer torch.optim.Adam(model.parameters(), lr1e-3) best_loss, patience, wait float(inf), 10, 0 for epoch in range(200): model.train() for xb, yb in train_loader: optimizer.zero_grad() loss criterion(model(xb), yb) loss.backward() torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0) # 梯度裁剪 optimizer.step() model.eval() with torch.no_grad(): val_loss criterion(model(torch.tensor(X_test, dtypetorch.float32)), torch.tensor(y_test, dtypetorch.float32)).item() if val_loss best_loss: best_loss, wait val_loss, 0 torch.save(model.state_dict(), best_lstm.pt) else: wait 1 if wait patience: print(fearly stop at epoch {epoch}) break print(fepoch {epoch}, val_loss {val_loss:.6f})逻辑说明shuffleFalse在时间序列里很重要打乱会破坏时序依赖。clip_grad_norm_把梯度范数限制在 1.0LSTM 在收益率这种小数值上训练时梯度容易爆炸这个操作能显著稳住训练。学习率1e-3是 Adam 的常用值如果 loss 震荡就降到5e-4。早停patience10表示验证损失连续 10 轮不降就停这是防过拟合最省事的手段。batch_size64在几千条样本上比较合适样本少就降到 32。提示收益率数值很小0.01 量级MSE 损失会非常小看 loss 时别被0.0001这种数字迷惑重点看它有没有持续下降、测试集有没有反弹。4. 评估与回测模型预测股票涨跌为什么每次结果不一样4.1 别只看 MSE方向准确率才是关键MSE 小不代表能赚钱。收益率预测里模型很容易学成永远预测接近 0MSE 很低但毫无用处。真正要看的是方向准确率预测涨、实际也涨的比例。model.eval() with torch.no_grad(): pred model(torch.tensor(X_test, dtypetorch.float32)).numpy() direction_acc ((pred 0) (y_test 0)).mean() print(f方向准确率: {direction_acc:.4f}) # 简单策略回测预测涨就持有预测跌就空仓 strategy_ret np.where(pred 0, y_test, 0) cum_strategy (1 strategy_ret).cumprod() cum_buyhold (1 y_test).cumprod() print(f策略累计: {cum_strategy[-1]:.4f}, 买入持有: {cum_buyhold[-1]:.4f})逻辑说明方向准确率能到 52%~55% 就已经算有信号了别指望 70%那是过拟合或者数据泄露。回测里np.where(pred 0, y_test, 0)是最朴素的择时策略预测涨就吃当天收益预测跌就空仓。对比买入持有基准很重要很多模型跑不赢躺平不动。4.2 结果每次不一样随机性从哪来模型预测股票涨跌每次结果不一样是高频疑问原因有三一是 PyTorch 权重随机初始化二是 DataLoader 即使shuffleFalse某些操作仍有非确定性三是 Dropout 在训练时随机丢弃神经元。要复现结果固定随机种子import random def set_seed(seed42): random.seed(seed) np.random.seed(seed) torch.manual_seed(seed) torch.cuda.manual_seed_all(seed) torch.backends.cudnn.deterministic True torch.backends.cudnn.benchmark False set_seed(42)逻辑说明cudnn.deterministicTrue会让 GPU 卷积算法确定化代价是速度略降。固定种子后同一份数据、同一份代码结果可复现但换一段测试区间结果还是会变这是市场本身的问题不是 bug。评估模型要跑多个时间窗口取平均单次结果没有说服力。4.3 基金预测和股票预测的差别基金尤其指数基金的净值序列比个股平滑得多噪声小、趋势性强LSTM 在基金净值上的方向准确率通常比个股高几个点。但代价是波动小、可套利空间也小。做基金预测时我一般把seq_len拉长到 30~60因为基金趋势持续时间更长特征里加上跟踪指数的收益率、市场整体涨跌作为外部变量效果比纯净值序列好。个股则相反seq_len短一点、特征里多放量价关系更合适。5. 避坑与排查LSTM 股票预测最常见的 5 个翻车现场5.1 现象测试集准确率高得离谱实盘完全不行原因数据泄露。最常见的是归一化时用了全量数据的均值和方差或者划分数据集时随机打乱让模型看到了未来信息。解决归一化参数只能用训练集算再应用到测试集切分严格按时间顺序。检查方法很简单——把测试集整体后移一天如果指标暴跌说明之前泄露了。5.2 现象loss 一直不降或者变成 nan原因学习率太大、收益率数值太小导致梯度问题或者输入里有 NaN。解决先把学习率降到1e-4试加梯度裁剪训练前assert not np.isnan(X).any()检查数据。收益率量级小的时候也可以把 target 放大 100 倍用百分比表示训练完再缩回去。5.3 现象训练集 loss 很低测试集 loss 高得吓人原因过拟合。LSTM 参数量相对几千条样本还是偏大。解决减小hidden_size64 降到 32、增大dropout0.3 提到 0.5、加 L2 正则优化器里设weight_decay1e-4、缩短seq_len。如果还不行说明特征太多砍到 3~4 个核心特征。5.4 现象预测曲线是一条几乎水平的直线原因模型学成了预测均值因为收益率本身接近零均值MSE 损失下这是局部最优。解决换损失函数用方向性的损失或者对涨跌样本加权或者把任务从回归改成分类涨/跌二分类用交叉熵模型会更愿意给出有倾向的预测。5.5 现象换一只股票就要重调所有参数原因不同股票波动率差异巨大统一参数不通用。解决对每只票做单独的标准化或者用波动率归一化收益率收益率除以滚动标准差。做股票组合分析时我一般按行业或市值分组组内共享一套超参数比全市场一套参数稳得多。6. 把单模型升级成能用的信号几个我压箱底的技巧单只 LSTM 跑出来的预测噪声很大直接拿来交易基本是送钱。我实际做的时候会加两层处理。第一层是多模型集成用不同随机种子训练 5 个 LSTM把预测取平均方向准确率通常能稳 2~3 个点因为单模型的随机波动被平滑掉了。第二层是信号过滤只在模型预测的绝对值超过某个阈值时才动手比如预测收益率绝对值大于 0.5% 才认为有信号否则视为噪声空仓。这个阈值用验证集调别用测试集。# 多模型集成 阈值过滤 preds [] for seed in [42, 7, 123, 2024, 999]: set_seed(seed) m LSTMModel(input_sizelen(feat_cols)) # ... 训练代码同上省略 ... m.load_state_dict(torch.load(fbest_lstm_{seed}.pt)) m.eval() with torch.no_grad(): preds.append(m(torch.tensor(X_test, dtypetorch.float32)).numpy()) ensemble_pred np.mean(preds, axis0) threshold 0.005 signal np.where(np.abs(ensemble_pred) threshold, np.sign(ensemble_pred), 0) strategy_ret signal * y_test print(f集成后方向准确率: {((ensemble_pred 0) (y_test 0)).mean():.4f})逻辑说明np.sign把连续预测转成 -1/0/1 的仓位信号threshold控制交易频率阈值越高交易越少、越保守。这个组合在回测里通常能把最大回撤压下来代价是错过一些小幅上涨。参数上阈值别设太大0.5%~1% 是日线级别的合理区间。还有一个容易被忽略的点滚动重训。市场风格会变一个模型训完就不管几个月后必然失效。我的习惯是每 60 个交易日重新训练一次用最近 3 年数据这样模型能跟上最新的波动特征。这套流程跑下来你会发现 LSTM 股票预测真正的价值不在预测精度而在于它逼你把数据管道、特征、回测、风控整条链路都搭明白——这套东西迁移到任何时间序列任务上都成立。我自己踩过最深的坑就是一开始迷信模型精度花两周调网络结构最后发现把数据泄露修掉、把回测做扎实比换十个模型都管用。希望帮到你。本文还有配套的精品资源点击获取

相关推荐

Word尾注脚注全攻略:插入、彻底删除与横线清除技巧
Word尾注脚注全攻略:插入、彻底删除与横线清除技巧

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 2:05:22

单目标微电网优化实战:用GOOSE Algorithm在MATLAB里跑通TaoToken配置与结果验证
单目标微电网优化实战:用GOOSE Algorithm在MATLAB里跑通TaoToken配置与结果验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 2:05:22

OpenCore Legacy Patcher让2007老Mac运行macOS Sonoma
OpenCore Legacy Patcher让2007老Mac运行macOS Sonoma

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 2:05:16

MySQL后台注入靶场实战:从环境搭建到提权完整链路
MySQL后台注入靶场实战:从环境搭建到提权完整链路

简介:这份资源是一套存在SQL注入漏洞的网站源码,面向正在学习Web安全、需要动手复现注入攻击的初学者与进阶者,可用于本地或空间搭建靶场环境,练习后台注入的探测与利用思路。压缩包共844个文件,约4.95MB,以… · 2026/9/25 2:37:40

源师兄BH1750光照扩展完整入门:从接线到第一个积木,5分钟测出环境光照
源师兄BH1750光照扩展完整入门:从接线到第一个积木,5分钟测出环境光照

源师兄BH1750光照扩展完整入门:从接线到第一个积木,5分钟测出环境光照 【免费下载链接】CupCode_BH1750光线模块 该模块用于测量环境光线强度 项目地址: https://gitcode.com/yuanshixiong/test 想给自己的开发板加一块能"看光"的传感器… · 2026/9/25 2:37:22

Aliens Eye递归扩展完全指南:用--recurse-depth从简介里自动挖出关联账号
Aliens Eye递归扩展完全指南:用--recurse-depth从简介里自动挖出关联账号

Aliens Eye递归扩展完全指南:用--recurse-depth从简介里自动挖出关联账号 【免费下载链接】Aliens_eye Hunt down 840 social media accounts using AI 项目地址: https://gitcode.com/gh_mirrors/al/Aliens_eye Aliens Eye 是一款 AI 驱动的用户名扫描工具&… · 2026/9/25 2:37:15

【Dify】腾讯云智能字幕解析应用
【Dify】腾讯云智能字幕解析应用

音视频内容的自动转写和结构化处理已成为内容管理的重要一环。腾讯云SubtitleInfo智能字幕解析工作流,面向各类音视频数据,提供了自动提取、整理字幕信息的高效方案。 本文介绍腾讯云SubtitleInfo智能字幕解析的整体流程设计、节点拆解与应用案例,重点分析如何利用自动化工… · 2026/9/25 2:37:15

【Dify】数据统计分析可视化应用
【Dify】数据统计分析可视化应用

数据统计分析是理解与利用数据的基础能力,无论是商业、科研还是日常运营,数据洞察已成为必备技能。通过自动化节点协作和可视化技术,数据分析工作流不仅大大简化了操作流程,还提升了分析效率。 本文介绍一种基于自动化节点的统计分析方法,涵盖数据导入、清洗、特征工程、… · 2026/9/25 2:37:15

【Dify】诗句封面生成与语音播报应用
【Dify】诗句封面生成与语音播报应用

以AI为核心的自动化创作工具已经进入内容生产的各个领域。古诗自动生成、配套视觉封面设计、诗句语音合成等多模态创新,正成为数字内容表达的新方式。 本文介绍一种利用大模型与多种AI工具自动生成古诗、诗句封面与语音播报的完整流程,覆盖主要技术节点及实际操作方法,适合… · 2026/9/25 2:37:15

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码