A股量化投资入门实战:机器学习策略demo从数据到回测全流程 简介这是一份面向具备一定Python基础、对炒股与量化投资尚不熟悉的初学者打造的入门级demo源码围绕机器学习在A股量化策略中的应用展开帮助读者快速理解数据收集、特征工程、模型构建与回测评估的完整流程。资源包共14个文件以5个py脚本、6张png图表、2个txt说明及1个gitignore为主Python文件分别承担回测、特征处理、模型训练与数据读取等模块职责图片则直观展示决策树预测股价涨幅、最大回撤、K线走势等关键结果压缩包整体约727KB结构清晰便于按模块学习。目前已有156人学习下载。通过这份源码读者可对照运行从数据处理到策略回测的全流程观察不同机器学习算法在价格预测中的表现并借助回测结果理解止损、仓位控制等风险管理思路为后续独立编写量化策略打下实践基础。1. 从一份能跑通的 A 股量化 demo 说起它到底解决了什么很多人第一次接触量化投资卡住的地方不是不会写 Python而是不知道一个完整策略从数据到回测到底长什么样。网上搜「机器学习 量化投资策略」出来的要么是纯理论推导要么是残缺的代码片段跑不起来也验证不了。这份ai_qua2323weweer.zip就是冲着这个痛点来的——它把数据获取、特征工程、模型训练、回测评估串成了一条能跑通的链路用 A 股市场做样本适合有 Python 基础但对炒股和量化一无所知的人拿来拆解。压缩包里除了main.py、backtest.py、feature.py、model.py、data.py这几个核心脚本还附了柱状图、最大回撤、K 线图、决策树预测股价涨幅等运行截图以及tushare_token.png提示你需要自己配数据源凭证。说白了它不是一个能直接拿去实盘的策略而是一个让你看清「量化策略长什么样」的脚手架。2. 拆开压缩包五个 Python 文件各自扛什么活2.1 模块分工与调用关系拿到源码先别急着pip install花五分钟把文件职责理清楚后面调参和排错会省很多事。这个 demo 的结构是典型的流水线式设计main.py是总调度其余四个模块各管一段。文件职责关键输入关键输出data.py拉取 A 股历史行情、清洗缺失值tushare token、股票代码列表规整的 DataFramefeature.py从原始行情构造技术指标特征行情 DataFrame特征矩阵 Xmodel.py构建并训练机器学习模型特征矩阵、标签 y训练好的模型对象backtest.py用历史数据模拟买卖、算收益模型预测信号、价格序列收益曲线、最大回撤main.py串联全流程以上全部回测报告与图表stock_list.txt里放的是股票池requirements.txt锁定了依赖版本.gitignore说明作者是按工程习惯组织的。img目录下的截图不是装饰是你跑完后用来对照结果是否正常的参照物——比如最大回撤.png能帮你判断回测逻辑有没有写反。2.2 环境准备与依赖安装先确认 Python 版本这类 demo 一般跑在 3.8 到 3.10 之间比较稳。建虚拟环境是基本操作别嫌麻烦血泪经验是直接在系统环境里装依赖后面版本冲突能让你重装系统。# 创建并激活虚拟环境 python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate # 安装依赖requirements.txt 里通常包含这些 pip install -r requirements.txtrequirements.txt里大概率会有pandas、numpy、scikit-learn、tushare、matplotlib这几个。如果安装tushare时报错常见原因是网络问题或版本过旧可以指定版本重试。装完后用pip list核对一下重点看scikit-learn的版本因为不同版本里DecisionTreeClassifier的默认参数有差异会影响你复现截图里的决策树结果。2.3 数据源配置token 是绕不过去的门槛tushare_token.png这张截图就是在提醒你数据获取需要凭证。tushare 的免费额度对 demo 级别的回测够用但需要注册后拿到 token。# data.py 中通常会有类似这样的初始化代码 import tushare as ts # 把这里的 token 替换成你自己的 ts.set_token(你的tushare_token) pro ts.pro_api() # 拉取单只股票日线数据 df pro.daily(ts_code000001.SZ, start_date20200101, end_date20231231)逻辑说明set_token只需调用一次之后pro_api()返回的接口对象可以复用。daily接口返回的是未复权数据做量化回测时要注意复权问题否则除权除息日会出现价格跳空导致特征失真。参数上ts_code的格式是「代码.交易所」000001.SZ是深交所600000.SH是上交所。如果你拉数据返回空 DataFrame先检查 token 是否过期再确认股票代码格式和日期范围。3. 特征工程与模型训练把行情变成模型能吃的数字3.1 从价格序列构造有效特征原始行情只有开高低收和成交量直接丢给模型效果很差。feature.py的核心任务就是把这些序列转成有预测意义的特征。常见做法是构造动量类、波动率类、成交量类指标。# feature.py 中特征构造的典型写法 import pandas as pd import numpy as np def build_features(df): df df.sort_values(trade_date).reset_index(dropTrue) # 动量特征过去 5 日、10 日收益率 df[ret_5] df[close].pct_change(5) df[ret_10] df[close].pct_change(10) # 波动率特征过去 10 日收益率标准差 df[vol_10] df[close].pct_change().rolling(10).std() # 成交量特征当日成交量与 5 日均量之比 df[vol_ratio] df[vol] / df[vol].rolling(5).mean() # 标签未来 5 日涨跌方向涨为 1 跌为 0 df[label] (df[close].shift(-5) df[close]).astype(int) df df.dropna() return df逻辑说明pct_change(5)算的是 5 日累计收益率反映中期动量。rolling(10).std()衡量波动率波动率放大往往伴随趋势转折。vol_ratio捕捉放量行为放量突破在 A 股里是比较有效的信号。标签用shift(-5)构造未来 5 日方向注意这会造成最后 5 行标签为 NaN必须dropna掉否则训练时会报错。参数上窗口期不是固定的5 日和 10 日只是 demo 默认值你可以改成 3 日或 20 日观察模型表现变化。3.2 决策树模型的训练与调参model.py里用的是决策树截图决策树预测股价涨幅.png就是它的输出。选决策树而不是神经网络是因为它可解释性强能直接看到哪些特征重要对入门者友好。# model.py 中模型训练的核心代码 from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score def train_model(df): feature_cols [ret_5, ret_10, vol_10, vol_ratio] X df[feature_cols] y df[label] # 按时间顺序切分不能随机打乱 split int(len(X) * 0.8) X_train, X_test X[:split], X[split:] y_train, y_test y[:split], y[split:] clf DecisionTreeClassifier( max_depth4, # 控制树深防止过拟合 min_samples_leaf50, # 叶子节点最少样本数 random_state42 ) clf.fit(X_train, y_train) pred clf.predict(X_test) print(测试集准确率:, accuracy_score(y_test, pred)) return clf逻辑说明时间序列数据绝对不能随机切分train_test_split默认的 shuffle 会把未来信息泄露到训练集导致回测虚高这是新手最容易翻车的地方。max_depth4是刻意压低的决策树不加限制可以无限生长训练集准确率能到 99% 但测试集一塌糊涂。min_samples_leaf50保证每个叶子有足够样本支撑避免模型记住噪声。如果你把max_depth调到 10 以上大概率会看到训练准确率飙升但回测收益反而下降这就是过拟合的典型表现。3.3 回测逻辑别让未来函数毁掉结果backtest.py是整个 demo 最需要盯紧的部分。回测的核心是模拟「如果当时按信号操作收益会怎样」但很容易写出用到未来数据的代码。# backtest.py 中简化的回测循环 def run_backtest(df, model): df df.copy() df[signal] model.predict(df[[ret_5, ret_10, vol_10, vol_ratio]]) # 信号滞后一期避免用当日收盘信号做当日交易 df[position] df[signal].shift(1) # 当日收益率 df[daily_ret] df[close].pct_change() # 策略收益 持仓信号 × 次日收益 df[strategy_ret] df[position] * df[daily_ret] # 累计净值 df[cum_ret] (1 df[strategy_ret]).cumprod() # 最大回撤 df[peak] df[cum_ret].cummax() df[drawdown] (df[cum_ret] - df[peak]) / df[peak] max_dd df[drawdown].min() print(累计收益:, df[cum_ret].iloc[-1] - 1) print(最大回撤:, max_dd) return df逻辑说明shift(1)是关键一步它保证你今天看到的信号明天才执行模拟真实交易中「收盘后算信号、次日开盘操作」的节奏。如果不加这个滞后等于用当天收盘价预测当天涨跌再当天买卖回测收益会好得不真实。cumprod()算累计净值cummax()算历史高点两者相除得到回撤序列。最大回撤是负数越接近 0 越好。跑完后对照最大回撤.png如果你的回撤超过 -50%要么是模型有问题要么是回测逻辑写错了。4. 避坑与排查跑不通、结果离谱时先看这几条4.1 现象tushare 返回空数据或报权限错误原因通常有三个token 没设置、token 过期、或者调用的接口超出免费额度。解决方法是先打印ts.get_token()确认 token 已写入再去 tushare 官网看接口权限说明。免费账户对daily接口有频率限制短时间内大量拉取会被临时封禁建议在循环里加time.sleep(0.5)。4.2 现象回测收益高得离谱年化几百个百分点这是典型的未来函数问题。检查backtest.py里信号有没有做shift检查特征构造时有没有用到当日收盘之后才知道的数据。另一个隐蔽的坑是标签构造用了shift(-5)但特征里不小心混入了未来信息。解决方法是把回测信号整体滞后一期并且用样本外数据验证。4.3 现象决策树准确率 99% 但实盘逻辑不成立原因几乎一定是过拟合。决策树不加max_depth和min_samples_leaf限制可以无限分裂直到每个叶子只有一个样本训练集完美拟合但毫无泛化能力。解决方法是在model.py里把树深压到 3 到 5 层叶子最小样本数设到 30 以上然后观察测试集准确率是否在 50% 到 60% 之间——这个区间对股票方向预测才是正常的。4.4 现象matplotlib 画图中文显示成方块原因是默认字体不支持中文。在main.py或画图脚本开头加两行配置即可。import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] # Windows 用黑体 plt.rcParams[axes.unicode_minus] False # 正常显示负号Mac 系统把SimHei换成Arial Unicode MS。改完如果还不行清一下 matplotlib 的字体缓存再重跑。4.5 现象requirements.txt 安装时报版本冲突常见于pandas和numpy版本不匹配。解决方法是先装numpy再装pandas或者直接用pip install -r requirements.txt --no-deps跳过依赖解析手动补齐缺失的包。如果scikit-learn版本和 demo 作者不一致导致 API 报错查一下你装的版本里DecisionTreeClassifier的参数名有没有变多数情况向下兼容。5. 进阶玩法把 demo 改成你自己的策略实验台跑通默认流程只是起点这个 demo 真正的价值在于它给你留了改的空间。我一般会从三个方向动手换模型、换特征、换股票池。换模型最直接。model.py里把DecisionTreeClassifier换成RandomForestClassifier或GradientBoostingClassifier接口几乎不用改但要注意随机森林的n_estimators别设太大100 到 200 棵足够再多训练时间线性增长而收益提升有限。换成LogisticRegression的话记得先对特征做标准化否则量纲差异会让系数失去意义。换特征需要回到feature.py。demo 里只用了动量和波动率你可以加均线交叉、RSI、MACD 柱状图斜率这些经典指标。但每加一个特征都要问自己这个特征在交易时点是否可得如果用了未来数据回测再好看也是自欺欺人。我习惯每加三个特征就跑一次回测对比最大回撤和收益曲线避免一次性堆太多导致无法归因。换股票池是最容易被低估的一步。stock_list.txt里如果只有几只股票结论没有统计意义。常见做法是拉沪深 300 成分股对每只股票单独训练模型再汇总信号或者把所有股票数据拼在一起训练一个通用模型。前者更稳健但计算量大后者训练快但容易忽略个股差异。我一般先用 20 只股票做快速验证确认流程没问题再扩到全市场。验证方法上除了看累计收益和最大回撤建议加一个基准对比——比如买入持有沪深 300 ETF 的收益曲线。如果你的策略跑不赢基准那模型再复杂也没有意义。这个对比图我每次都会画它比任何单一指标都更能说明问题。从那以后我每次拿到新的量化 demo都强制先跑一遍默认参数、记下基准结果再动任何一行代码。这样后面改出问题时至少知道是改坏了还是本来就这样。希望帮到你。本文还有配套的精品资源点击获取