news 2026/10/5 8:55:40

基于深度学习的量化投资策略实战:从CSV数据到模拟回测的完整工程拆解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于深度学习的量化投资策略实战:从CSV数据到模拟回测的完整工程拆解

简介:这是一份面向高校学生与量化投资初学者的深度学习实战项目包,可作为毕业设计、期末大作业或人工智能课程实践参考,帮助读者理解如何将神经网络应用于股票价格预测与交易策略开发。压缩包共46个文件,约216KB,以23个Python源码为核心,辅以xml工程配置、csv策略与行情数据、sqlite与db数据库文件、md说明文档及txt依赖清单,覆盖数据读取、模型构建、策略执行与模拟交易等环节。项目围绕数据预处理、RNN/LSTM等模型搭建、训练调优及历史回测评估展开,代码按分析、深度学习网络、策略、模拟运行等模块分层组织,并配有单元测试与依赖说明,便于读者梳理完整工程结构、理解量化策略从数据到回测的实现链路。目前已有133人学习下载,适合希望打通深度学习与金融量化交叉知识、积累可运行项目经验的读者参考。

1. 从一份 600519 的 CSV 说起:这套深度学习量化策略包到底能跑出什么

很多人第一次接触量化投资,都是从一份贵州茅台的日线 CSV 开始的。你手里这个基于深度学习的量化投资策略.zip,本质上就是一条从原始行情到模拟交易信号的完整链路:data/600519.SH.CSV是原料,process/csv2sqlite.py把 CSV 灌进 SQLite,analysis/stock.py做指标计算,DL/network.py搭深度学习网络,strategy/Strategy.py把预测转成买卖动作,最后simulate_RUN.py跑一遍模拟。它不是一个能直接下单的实盘系统,而是一个结构清晰、可拆可改的毕业设计级工程骨架,适合做期末大作业、课程设计,或者作为你自己策略原型的起点。如果你正卡在“深度学习怎么和量化投资结合”这个点上,这份代码能让你少走一段从零搭架子的路。

2. 拆开压缩包先看什么:目录结构与模块职责

2.1 核心文件清单与调用关系

拿到一个陌生项目,我习惯先看入口文件和依赖,而不是急着跑。这个包里main.py和simulate_RUN.py是两个入口,前者偏策略执行,后者偏模拟回测。requirements.txt决定了你能不能顺利装环境,README.md和Sight.md是作者留下的说明,先扫一遍能省很多猜的时间。

路径职责是否核心
main.py策略主执行入口是
simulate_RUN.py模拟交易运行入口是
ML.py深度学习模型相关逻辑是
DL/network.py网络结构定义是
DL/GPU.pyGPU 相关配置视环境
analysis/stock.py股票数据读取与指标是
analysis/draw.py绘图否
process/csv2sqlite.pyCSV 转 SQLite是
process/SQLFrame.pySQL 数据帧封装是
strategy/Strategy.py策略逻辑是
strategy/chost.py策略辅助模块视情况
data/600519.SH.CSV原始行情数据是
tests/单元测试建议看

从调用关系看,典型链路是:csv2sqlite.py把600519.SH.CSV写入data.sqlite或600519.db,stock.py从库里读数据并算特征,network.py定义网络,ML.py负责训练和预测,Strategy.py根据预测生成信号,simulate_RUN.py串起来跑模拟。你改任何一环,都要顺着这条链往下检查。

2.2 环境准备与依赖安装

requirements.txt是这个项目能不能跑起来的第一道门槛。深度学习项目最怕的就是版本冲突,尤其是 TensorFlow 和 PyTorch 对 Python 版本、CUDA 版本都很敏感。我一般会先建独立虚拟环境,再按文件装依赖。

python -m venv venv # Windows 激活 venv\Scripts\activate # Linux / macOS 激活 source venv/bin/activate pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

第一段建虚拟环境,避免污染全局包;第二段激活环境,Windows 和 Linux 命令不同;第三段用国内镜像装依赖,速度会快很多。如果requirements.txt里没有锁死版本号,装完最好pip freeze > requirements_lock.txt存一份,方便复现。

提示:如果安装过程中报某个包找不到对应版本,先看它的版本号是不是写死了。常见做法是把该行改成不指定版本,让 pip 自己选兼容版本,再观察后续是否报错。

2.3 数据从 CSV 到 SQLite 的落库过程

这个项目没有直接用 pandas 读 CSV 就完事,而是多了一步落库,说明作者想让数据查询和复用更方便。process/csv2sqlite.py大概率就是干这件事的。你可以先手动跑一遍,确认数据能正确进库。

import pandas as pd import sqlite3 # 读取 CSV,注意编码和日期列 df = pd.read_csv("data/600519.SH.CSV", encoding="utf-8") # 日期列转成标准格式,方便后续按时间索引 df["date"] = pd.to_datetime(df["date"]) # 写入 SQLite,表名用 stock_600519 conn = sqlite3.connect("data/600519.db") df.to_sql("stock_600519", conn, if_exists="replace", index=False) conn.close() print("rows:", len(df), "cols:", list(df.columns))

这段代码做了三件事:读 CSV、转日期、写库。if_exists="replace"表示每次覆盖,适合反复调试;如果你不想丢历史数据,改成"append"。index=False避免把 pandas 索引也写进去。跑完打印行列数,能快速判断数据有没有读歪。

2.4 用 stock.py 做特征与指标计算

analysis/stock.py是数据加工层。量化策略里常见的均线、收益率、波动率,通常都在这一层算。你可以先单独调用它,看看输出长什么样,再决定要不要加自己的因子。

import pandas as pd def add_features(df): # 收盘价简单收益率 df["ret"] = df["close"].pct_change() # 5 日和 20 日均线 df["ma5"] = df["close"].rolling(5).mean() df["ma20"] = df["close"].rolling(20).mean() # 20 日滚动波动率 df["vol20"] = df["ret"].rolling(20).std() # 去掉前面因滚动窗口产生的空值 df = df.dropna().reset_index(drop=True) return df if __name__ == "__main__": raw = pd.read_csv("data/600519.SH.CSV") feat = add_features(raw) print(feat[["date", "close", "ret", "ma5", "ma20", "vol20"]].tail())

pct_change()算日收益率,rolling(5).mean()算 5 日均线,rolling(20).std()算 20 日波动率。dropna()会删掉前 19 行,因为均线还没形成。这一步做完,你的特征表就可以喂给网络了。参数上,均线窗口和波动率窗口都可以改,但要注意改完以后样本量会变,训练集划分也要跟着调。

3. 深度学习模型怎么接进策略:网络定义、训练与预测

3.1 DL/network.py 里的网络结构怎么读

DL/network.py是模型定义文件。量化时序数据常见的选择是 LSTM 或一维 CNN,前者擅长捕捉长依赖,后者擅长提取局部形态。你打开文件后,先看它继承的是哪个框架的模块,再看输入输出维度。

import torch import torch.nn as nn class LSTMModel(nn.Module): def __init__(self, input_size=5, hidden_size=64, num_layers=2, output_size=1): super().__init__() # batch_first=True 表示输入形状为 (batch, seq, feature) self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True) self.fc = nn.Linear(hidden_size, output_size) def forward(self, x): # out 形状 (batch, seq, hidden) out, _ = self.lstm(x) # 只取最后一个时间步的输出做预测 return self.fc(out[:, -1, :])

input_size对应你喂进去的特征数量,比如 close、ret、ma5、ma20、vol20 就是 5。hidden_size是隐藏层维度,越大拟合能力越强但越容易过拟合。num_layers=2表示两层 LSTM。out[:, -1, :]取序列最后一步,表示用过去一段窗口预测下一个点。如果你改成预测多步,output_size要相应调整。

3.2 训练循环与损失函数选择

ML.py大概率包含训练逻辑。量化里做回归常用 MSE,做涨跌分类常用交叉熵。你要先确认标签是什么,再决定损失函数。

import torch import torch.nn as nn from torch.utils.data import DataLoader, TensorDataset def train_model(model, X, y, epochs=50, lr=1e-3, batch_size=32): # 转成 tensor,float32 是深度学习默认精度 X_t = torch.tensor(X, dtype=torch.float32) y_t = torch.tensor(y, dtype=torch.float32).view(-1, 1) loader = DataLoader(TensorDataset(X_t, y_t), batch_size=batch_size, shuffle=True) criterion = nn.MSELoss() optimizer = torch.optim.Adam(model.parameters(), lr=lr) for epoch in range(epochs): model.train() total_loss = 0.0 for xb, yb in loader: optimizer.zero_grad() pred = model(xb) loss = criterion(pred, yb) loss.backward() optimizer.step() total_loss += loss.item() if (epoch + 1) % 10 == 0: print(f"epoch {epoch+1}, loss {total_loss/len(loader):.6f}") return model

MSELoss适合预测收益率这类连续值。Adam学习率默认 1e-3,比较稳。shuffle=True打乱样本顺序,避免模型记住顺序。每 10 轮打印一次 loss,方便观察有没有发散。如果 loss 一直不降,先检查输入特征有没有归一化,再检查标签有没有对齐。

3.3 训练集、验证集、测试集怎么切

时序数据不能随机打乱切分,否则会用到未来信息,这是量化里最经典的翻车点之一。正确做法是按时间顺序切。

def time_split(X, y, train_ratio=0.7, val_ratio=0.15): n = len(X) train_end = int(n * train_ratio) val_end = int(n * (train_ratio + val_ratio)) return (X[:train_end], y[:train_end], X[train_end:val_end], y[train_end:val_end], X[val_end:], y[val_end:])

train_ratio=0.7表示前 70% 做训练,中间 15% 做验证,最后 15% 做测试。这样切出来的测试集在时间上最靠后,更接近真实使用场景。如果你用随机切分,模型可能在训练时见过未来数据,回测结果会虚高,实盘就露馅。

3.4 预测结果怎么转成买卖信号

模型输出的是数值,策略需要的是动作。strategy/Strategy.py负责这一步。常见做法是设定阈值:预测收益大于某个值就买,小于某个值就卖。

def signal_from_pred(pred, buy_th=0.005, sell_th=-0.005): signals = [] for p in pred: if p > buy_th: signals.append(1) # 买入 elif p < sell_th: signals.append(-1) # 卖出 else: signals.append(0) # 持有 return signals

buy_th和sell_th是阈值,单位是预测收益率。阈值太小吃太多噪声,太大错过机会。你可以先用 0.005 跑一遍,再根据信号数量和回测结果调整。这一步没有标准答案,更多是经验和反复试。

4. 模拟回测怎么跑:simulate_RUN.py 与策略参数

4.1 模拟运行的入口与参数

simulate_RUN.py是回测入口。它一般会读数据、加载模型、生成信号、模拟买卖、输出收益曲线。你第一次跑,建议先把交易成本设为零,确认逻辑通不通,再加成本。

python simulate_RUN.py --data data/600519.db --model DL/model.pth --cash 100000

--data指定数据库,--model指定模型权重,--cash是初始资金。如果脚本不支持命令行参数,就打开文件改默认值。跑完看输出目录有没有收益曲线图或交易记录 CSV。

4.2 回测指标怎么看

回测不是只看总收益。我一般会同时看年化收益、最大回撤、夏普比率和交易次数。总收益高但回撤大,实盘很难拿住;交易次数过多,成本会吃掉利润。

指标含义关注点
年化收益折算到一年的收益率是否稳定
最大回撤从高点到低点的最大亏损能否承受
夏普比率单位风险的超额收益越高越好
交易次数买卖总次数是否过于频繁
胜率盈利交易占比结合盈亏比看

这些指标如果脚本没直接输出,你可以从交易记录自己算。关键是别只看一个数就下结论。

4.3 策略参数调整的边界

strategy/Strategy.py和strategyDic/default.strategy.csv里通常有策略参数。改参数之前,先想清楚改的是哪一层:是特征窗口、模型超参,还是买卖阈值。每次只改一个,记录结果,否则你分不清是哪个改动起了作用。

# 示例:把均线窗口从 5/20 改成 10/30 df["ma10"] = df["close"].rolling(10).mean() df["ma30"] = df["close"].rolling(30).mean()

窗口变大,信号更平滑但更滞后;窗口变小,反应快但噪声多。没有绝对优劣,要结合你的持仓周期。改完记得重新训练模型,因为输入特征变了。

5. 避坑与排查:这份代码最容易翻车的几个地方

5.1 数据时间对齐问题

现象:回测收益异常高,曲线几乎只涨不跌。原因:特征和标签错位,用了未来数据。解决:检查shift方向,确保预测目标在特征之后。常见做法是标签用close.shift(-1),特征用当前及过去数据。

5.2 归一化不一致

现象:训练 loss 正常,预测结果离谱。原因:训练集和测试集用了不同的归一化参数。解决:归一化参数只在训练集上拟合,然后应用到验证集和测试集。不要对全量数据一起归一化。

5.3 模型过拟合

现象:训练集 loss 很低,验证集 loss 很高。原因:模型太复杂或样本太少。解决:减小hidden_size、加 dropout、早停,或者增加数据量。量化数据本身噪声大,过拟合很常见。

5.4 SQLite 路径与权限

现象:跑csv2sqlite.py报找不到文件或无法写入。原因:相对路径基于当前工作目录,不是脚本所在目录。解决:用os.path.dirname(__file__)拼绝对路径,或者确认你在项目根目录执行命令。

5.5 GPU 与 CPU 切换

现象:DL/GPU.py相关代码报 CUDA 不可用。原因:机器没有 GPU 或驱动不匹配。解决:在代码里加device = torch.device("cuda" if torch.cuda.is_available() else "cpu"),把模型和数据都.to(device)。没有 GPU 就用 CPU,小数据量也能跑。

6. 让这套代码真正为你所用:从改一个因子到验证一轮回测

这份代码最大的价值不是它自带的策略,而是它给了你一条可改的链路。你可以从最简单的改动开始:在stock.py里加一个动量因子,重新训练,跑一遍回测,看指标有没有变化。然后换一个网络结构,比如把 LSTM 换成一维 CNN,再跑一遍。每次只改一个变量,记录结果,这样你才能知道什么有效。

# 加一个 10 日动量因子 df["momentum10"] = df["close"] / df["close"].shift(10) - 1 df = df.dropna().reset_index(drop=True)

这个因子表示过去 10 个交易日的涨跌幅。加完以后,input_size要从 5 改成 6,训练脚本也要同步改。跑完对比夏普比率和最大回撤,如果变好,说明动量有信息;如果变差,可能是过拟合或者因子冗余。

验证一轮回测是否可信,我一般会做三件事:一是把测试集换成不同时间段,看结果是否稳定;二是把交易成本加上,看利润还剩多少;三是把参数微调一下,看结果是否剧烈变化。如果一改参数结果就天翻地覆,说明策略不稳,实盘要谨慎。

注意:回测好看不等于实盘能赚。这份代码是学习骨架,不是印钞机。用它理解流程、练手改代码,比直接拿去跑实盘更有价值。

从那以后我每次拿到一个新的量化代码包,都会先跑通数据链路,再单独验证模型输出,最后才看回测曲线。顺序反了,很容易被漂亮的收益图带偏。希望这份拆解能帮到你,少踩几个我踩过的坑。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/5 8:55:36

Claude设计文档功能:技术方案智能解析与评审实战指南

1. 这不是“额度翻倍”&#xff0c;而是设计文档协作范式的悄然升级 最近在多个技术团队的 Slack 频道和内部 Wiki 页面里&#xff0c;频繁看到同事贴出一张截图&#xff1a;Claude 界面右上角那个原本灰显的“文档”图标突然亮起&#xff0c;旁边标注着“200K tokens&#xff…

作者头像 李华
网站建设 2026/10/5 8:55:11

YOLO网球数据集实战:1956张图像训练与推理全流程

简介&#xff1a;这份资源面向计算机视觉初学者与目标检测工程实践者&#xff0c;提供一套可直接投入训练的网球场景数据集&#xff0c;覆盖网球与运动员两类目标的识别任务&#xff0c;适用于yolov5至yolo11等主流YOLO系列算法。压缩包共2000个文件&#xff0c;约87.8MB&#…

作者头像 李华
网站建设 2026/10/5 8:55:10

基于504张鹿数据集的YOLO目标检测实战:VOC转YOLO与训练避坑指南

简介&#xff1a;这是一份面向目标检测初学者与算法工程师的鹿类识别数据集&#xff0c;采用Pascal VOC与YOLO双格式标注&#xff0c;可直接用于训练和验证单类别检测模型。压缩包共1514个文件&#xff0c;包含504张jpg原图、504个VOC格式xml标注文件、504个YOLO格式txt标签以及…

作者头像 李华
网站建设 2026/10/5 8:54:40

AMD平台Android模拟器AEHD驱动安装失败全排查指南

看到这行红字的时候&#xff0c;我一点都不意外。Android Emulator Hypervisor Driver for AMD Processors installation failed&#xff0c;基本是AMD平台上装Android Studio模拟器最经典的一道坎&#xff0c;我不止一次被同事和老读者问过同样的问题。你说它难吧&#xff0c;…

作者头像 李华
网站建设 2026/10/5 8:53:58

STC89C52压力变送器嵌入式程序设计实战

1. 压力变送器不是“把压力变成数字”那么简单——从工业现场真实需求倒推程序设计逻辑很多人看到“压力变送器程序设计”第一反应是&#xff1a;不就是读个ADC值、算个公式、串口打出来&#xff1f;我刚接手这个项目时也这么想。直到客户把一台正在产线上跑的旧设备拉到我面前…

作者头像 李华
网站建设 2026/10/5 8:53:55

隐式情感分析新思路:多极性正交注意力机制详解

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

作者头像 李华