恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Python深度学习股票量化系统实战:从数据到模型与可视化
首页
资讯中心
/
Python深度学习股票量化系统实战:从数据到模型与可视化
Python深度学习股票量化系统实战:从数据到模型与可视化
发布时间:2026/9/28 18:17:55
简介这是一套基于Python与深度学习实现的股票量化系统源码面向计算机、人工智能、通信工程等专业的在校学生与教师也适合作为毕业设计、课程设计或项目立项演示的参考方案。系统覆盖数据采集与保存、数据分析、可视化展示及深度学习预测等环节并集成日常买卖、做套、MACD、KDJ、网格交易等策略支持机器盯盘与定时更新当股价出现异动时可通过企业微信或邮箱推送提醒均价线借助时序预测判断后续涨跌方向另含基金实时、历史与排行数据展示。压缩包共244个文件约3.53MB以71个py源码、80个pyc编译文件、38张png与11张jpg图表、20个json配置及7个ui界面文件为主辅以css、html等前端资源结构完整便于二次开发。目前已有266人学习代码均经测试运行成功答辩评审平均分达96分下载后建议先阅读README.md仅供学习参考。1. 从一份股票量化系统源码包说起Python 深度学习怎么把行情变成可复现的信号很多人第一次接触股票量化是从拿到一个压缩包开始的里面有 Python 脚本、深度学习模型、可视化页面还有架构图和文档说明。标题写着「基于 Python 和深度学习实现的股票量化系统及可视化源码文档说明架构图」看起来什么都有但真正打开后往往卡在第一步——环境跑不起来数据接不上模型输出一堆看不懂的数字。这篇笔记就围绕这个方向把一套可落地的股票量化系统从数据到模型再到可视化拆开讲清楚。适合两类人一是会点 Python、想用深度学习做量化但不知道从哪下手的新手二是已经写过简单策略、想补上模型和可视化链路的熟手。核心不是复刻某个压缩包而是让你理解这套系统每一层在干什么、参数怎么设、哪里最容易翻车。2. 数据层与特征工程股票量化系统的地基怎么打2.1 行情数据从哪里来、怎么存股票量化系统的第一道坎不是模型是数据。常见做法是用开源数据接口拉日线或分钟线存成 CSV 或直接进 SQLite。我一般会先用一个轻量脚本把数据落盘避免每次训练都重新请求。下面这段代码演示用 akshare 拉一只股票的日线并存入 SQLite字段包括日期、开盘、收盘、最高、最低、成交量。import akshare as ak import sqlite3 import pandas as pd # 拉取贵州茅台日线数据start_date 和 end_date 按需修改 df ak.stock_zh_a_hist(symbol600519, perioddaily, start_date20200101, end_date20241231) df df.rename(columns{ 日期: date, 开盘: open, 收盘: close, 最高: high, 最低: low, 成交量: volume }) df[date] pd.to_datetime(df[date]) # 存入 SQLite表名 stock_daily conn sqlite3.connect(quant.db) df.to_sql(stock_daily, conn, if_existsreplace, indexFalse) conn.close() print(df.tail())逻辑说明akshare 返回的是中文列名先统一成英文方便后续处理日期转成 datetime 类型避免字符串排序出错if_existsreplace在首次建表时最省事但正式环境建议改成append并加唯一索引去重。参数上period可选 daily、weekly、monthly做深度学习一般用 daily 或更细的分钟线start_date和end_date决定样本区间太短模型学不到东西太长又容易混入不同市场阶段。存好数据后下一步是特征工程。股票量化里常见的特征包括收益率、移动平均线、波动率、成交量变化率、RSI、MACD。这些不需要深度学习也能算但它们是模型的输入。我一般会写一个build_features函数把原始 OHLCV 转成特征矩阵。import numpy as np def build_features(df): df df.copy() df[ret] df[close].pct_change() # 日收益率 df[ma5] df[close].rolling(5).mean() # 5日均线 df[ma20] df[close].rolling(20).mean() # 20日均线 df[vol_std] df[ret].rolling(20).std() # 20日波动率 df[vol_chg] df[volume].pct_change() # 成交量变化率 df[rsi] compute_rsi(df[close], 14) # RSI 指标 df df.dropna() return df def compute_rsi(series, period14): delta series.diff() gain delta.where(delta 0, 0).rolling(period).mean() loss -delta.where(delta 0, 0).rolling(period).mean() rs gain / loss return 100 - (100 / (1 rs))逻辑说明pct_change()算收益率rolling().mean()算均线rolling().std()算波动率。RSI 用 14 天是常见默认值可以改成 6 或 24 做对比。dropna()会丢掉前 20 行左右因为均线和波动率需要窗口。参数上窗口越大特征越平滑但滞后越明显做短线可以缩小到 5 和 10做中长线可以放大到 20 和 60。2.2 标签怎么定义回归还是分类深度学习做股票量化标签定义决定了模型是回归还是分类。常见做法有两种一是预测未来 N 天收益率做回归二是预测未来 N 天涨跌方向做分类。我一般先用分类因为方向比幅度更容易学也更容易评估。def make_label(df, horizon5, threshold0.0): df df.copy() df[future_ret] df[close].shift(-horizon) / df[close] - 1 df[label] (df[future_ret] threshold).astype(int) df df.dropna() return df逻辑说明shift(-horizon)把未来第 N 天的收盘价挪到当前行算未来收益率threshold设 0 表示只要涨就算正样本设 0.01 表示涨超 1% 才算。参数上horizon取 1 到 10 都有人用短线取 1 到 3中长线取 5 到 10。注意标签必须用未来数据但特征只能用当前及历史数据否则就是未来函数回测会虚高。提示特征工程阶段最容易犯的错是把未来信息混进特征比如用全样本均线而不是滚动均线。检查方法是看特征计算是否只依赖当前行及之前的数据。3. 深度学习模型选型与训练LSTM、CNN 还是 Transformer3.1 为什么股票量化常用 LSTM 和 CNN股票时序数据有两个特点一是时间依赖今天价格和昨天、上周有关二是局部模式比如连续几天放量上涨可能预示短期见顶。LSTM 擅长捕捉长短期依赖CNN 擅长提取局部形态两者在量化里都有成熟应用。Transformer 近年也有人在用但数据量要求高小样本容易过拟合。我一般先用 LSTM 做基线因为结构简单、调参少。下面是一个用 PyTorch 写的 LSTM 分类模型输入是 30 天窗口的特征序列输出涨跌概率。import torch import torch.nn as nn class LSTMModel(nn.Module): def __init__(self, input_dim, hidden_dim64, num_layers2, dropout0.3): super().__init__() self.lstm nn.LSTM(input_dim, hidden_dim, num_layers, batch_firstTrue, dropoutdropout) self.fc nn.Linear(hidden_dim, 1) def forward(self, x): # x: (batch, seq_len, input_dim) out, _ self.lstm(x) out out[:, -1, :] # 取最后一个时间步 return torch.sigmoid(self.fc(out))逻辑说明input_dim是特征数量比如 6 个特征就填 6hidden_dim是 LSTM 隐藏层维度64 是常见起点num_layers2表示两层 LSTM层数越多越容易过拟合dropout0.3在层间随机丢弃抑制过拟合。out[:, -1, :]取序列最后一个时间步的输出代表模型对当前时刻的判断。最后用 sigmoid 压到 0 到 1输出涨的概率。参数上seq_len一般取 20 到 60太短看不到趋势太长训练慢且容易梯度消失。batch_size取 32 或 64学习率从 1e-3 开始用 Adam 优化器。损失函数用 BCE Loss因为标签是 0 或 1。3.2 训练流程与验证集划分股票数据不能随机划分训练集和验证集因为时间序列有先后顺序。常见做法是按时间切分前 70% 训练中间 15% 验证最后 15% 测试。下面是一个训练循环的骨架。from torch.utils.data import DataLoader, TensorDataset def train_model(model, X_train, y_train, X_val, y_val, epochs50, lr1e-3): train_ds TensorDataset(torch.FloatTensor(X_train), torch.FloatTensor(y_train)) val_ds TensorDataset(torch.FloatTensor(X_val), torch.FloatTensor(y_val)) train_loader DataLoader(train_ds, batch_size64, shuffleFalse) val_loader DataLoader(val_ds, batch_size64, shuffleFalse) optimizer torch.optim.Adam(model.parameters(), lrlr) criterion nn.BCELoss() for epoch in range(epochs): model.train() for xb, yb in train_loader: optimizer.zero_grad() pred model(xb).squeeze() loss criterion(pred, yb) loss.backward() optimizer.step() model.eval() val_loss 0 with torch.no_grad(): for xb, yb in val_loader: pred model(xb).squeeze() val_loss criterion(pred, yb).item() print(fEpoch {epoch}, val_loss {val_loss:.4f}) return model逻辑说明shuffleFalse在时间序列里很重要打乱会破坏时序依赖。训练集和验证集分别用 DataLoader 包装每轮先训练再验证。BCELoss适合二分类如果改成回归就用 MSELoss。参数上epochs取 50 到 100早停可以看验证集损失连续几轮不降就停。学习率太大容易震荡太小收敛慢1e-3 是安全起点。注意验证集损失下降但测试集效果差通常是过拟合。可以加 dropout、减小 hidden_dim、增加数据量或者改用更简单的模型。4. 回测与可视化把模型输出变成能看的图4.1 回测框架怎么搭模型输出概率后需要转成交易信号再回测。常见规则是概率大于 0.6 买入小于 0.4 卖出中间持有。回测要算累计收益、最大回撤、夏普比率。下面是一个简化回测函数。def backtest(df, prob_colprob, threshold0.6): df df.copy() df[signal] 0 df.loc[df[prob_col] threshold, signal] 1 df.loc[df[prob_col] 1 - threshold, signal] -1 df[strategy_ret] df[signal].shift(1) * df[ret] df[cum_ret] (1 df[strategy_ret]).cumprod() df[benchmark] (1 df[ret]).cumprod() return df逻辑说明signal.shift(1)表示今天收盘后出信号明天开盘执行避免未来函数。cumprod()算累计收益。参数上threshold越高信号越少但越保守0.6 是常见起点。回测结果要和基准对比如果策略跑不赢买入持有说明模型没有超额收益。4.2 可视化用 ECharts 或 Matplotlib 画收益曲线可视化是这套系统的门面。常见做法是用 Matplotlib 画收益曲线和回撤或者用 ECharts 做交互式大屏。下面是一个 Matplotlib 画累计收益和回撤的例子。import matplotlib.pyplot as plt def plot_backtest(df): fig, axes plt.subplots(2, 1, figsize(12, 8)) axes[0].plot(df[date], df[cum_ret], labelStrategy) axes[0].plot(df[date], df[benchmark], labelBenchmark) axes[0].legend() axes[0].set_title(Cumulative Return) drawdown df[cum_ret] / df[cum_ret].cummax() - 1 axes[1].fill_between(df[date], drawdown, 0, colorred, alpha0.3) axes[1].set_title(Drawdown) plt.tight_layout() plt.savefig(backtest.png)逻辑说明上面画累计收益下面画回撤。cummax()算历史最高点除以最高点减一就是当前回撤。参数上figsize控制图片大小alpha控制填充透明度。如果要放到网页上可以用 pyecharts 生成 HTML支持缩放和悬停查看数值。提示可视化不只是画图还要能回答「策略在哪些时间段亏钱」「回撤最深多少」「和基准比谁强」。图里至少要有策略曲线、基准曲线和回撤区域。5. 避坑与排查股票量化系统最常见的 5 个翻车点5.1 未来函数回测收益虚高的头号原因现象回测累计收益高得离谱实盘完全跑不出来。原因特征或标签里用了未来数据比如用全样本均值归一化、用当天收盘价算当天信号。解决所有特征只用当前及历史数据信号用shift(1)延迟一天执行归一化参数只用训练集计算。5.2 数据对齐错误日期错位导致信号对不上现象模型预测和实际涨跌完全相反。原因特征和标签的日期没有对齐比如特征用了 T 日数据标签却用了 T1 日收盘价但没 shift。解决统一用date列做 merge检查每一行的特征日期和标签日期是否一致打印几行样本人工核对。5.3 过拟合训练集准确率 90%测试集 50%现象训练损失一直降验证损失先降后升。原因模型太复杂、数据太少、特征太多。解决减小 hidden_dim 和 num_layers加 dropout减少特征数量增加训练数据。早停也是有效手段验证损失连续 5 轮不降就停。5.4 类别不平衡涨跌样本比例悬殊现象模型全预测涨或全预测跌准确率看着不低但没意义。原因A 股长期看涨正样本远多于负样本。解决用pos_weight给少数类加权或者用 F1、AUC 代替准确率评估。重采样也可以但时间序列里要小心破坏时序。5.5 环境与依赖PyTorch 和 akshare 版本冲突现象import torch报错或者 akshare 拉数据返回空。原因Python 版本、PyTorch 版本、akshare 版本不匹配。解决用 conda 建独立环境固定版本比如 Python 3.9 PyTorch 2.0 akshare 最新。拉数据失败先检查网络和接口是否变更akshare 接口经常更新。注意这五个坑里未来函数和数据对齐是最隐蔽的建议每次改完特征都打印几行样本人工看一眼日期和数值。6. 进阶技巧用 walk-forward 验证和模型集成提升稳健性6.1 walk-forward 验证比单次切分更接近实盘单次按时间切分训练测试只能看一个时间段的表现。walk-forward 验证是滚动向前用前 3 年训练预测第 4 年再用前 4 年训练预测第 5 年依次滚动。这样能看出模型在不同市场阶段是否稳定。def walk_forward(df, train_years3, test_years1): results [] start df[date].min().year end df[date].max().year for year in range(start train_years, end - test_years 1): train df[df[date].dt.year year] test df[df[date].dt.year year] # 这里调用训练和回测函数 results.append((year, train.shape[0], test.shape[0])) return results逻辑说明按年份滚动训练集逐年扩大测试集始终是下一年。参数上train_years至少 3 年否则模型学不到完整周期test_years取 1 年方便按年评估。walk-forward 的结果如果每年都跑不赢基准说明模型没有稳定 alpha。6.2 模型集成LSTM CNN 简单规则单个模型容易受随机种子影响集成能降低方差。常见做法是训练 LSTM 和 CNN 两个模型把输出概率平均再叠加一个简单规则比如均线过滤。下面是一个集成预测的示例。def ensemble_predict(lstm_prob, cnn_prob, ma_signal, w10.4, w20.4, w30.2): # ma_signal: 1 表示均线向上0 表示向下 combined w1 * lstm_prob w2 * cnn_prob w3 * ma_signal return (combined 0.5).astype(int)逻辑说明w1、w2、w3是权重加起来等于 1。LSTM 和 CNN 各占 0.4规则占 0.2。参数可以按验证集表现调整如果某个模型明显更强就加大权重。集成后信号更平滑回撤通常更小但收益也可能被拉低需要权衡。6.3 一个具体技巧用概率阈值动态调整仓位固定阈值 0.6 买入太死板可以根据概率大小动态调仓位。比如概率 0.6 到 0.7 半仓0.7 到 0.8 七成仓0.8 以上满仓。这样在模型信心高时加大暴露信心低时减少暴露。def dynamic_position(prob): if prob 0.5: return 0 elif prob 0.6: return 0.3 elif prob 0.7: return 0.5 elif prob 0.8: return 0.7 else: return 1.0逻辑说明概率越低仓位越轻概率越高仓位越重。参数上分档和仓位比例可以按回测调优但不要过度拟合档位太多容易在实盘失效。我一般用 4 到 5 档简单可解释。这套系统从数据到模型到可视化每一层都有坑但每一层也都有成熟做法。我自己踩过最深的坑是未来函数回测收益翻倍实盘一塌糊涂后来每次改特征都强制打印样本核对日期。希望帮到你。本文还有配套的精品资源点击获取