☰
A股量化投资入门实战:机器学习策略demo从数据到回测全流程
2026/10/25 12:48:02 网站建设 项目流程

简介:这是一份面向具备一定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、股票代码列表规整的 DataFrame
feature.py从原始行情构造技术指标特征行情 DataFrame特征矩阵 X
model.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.txt

requirements.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_code='000001.SZ', start_date='20200101', end_date='20231231')

逻辑说明: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(drop=True) # 动量特征:过去 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_depth=4, # 控制树深,防止过拟合 min_samples_leaf=50, # 叶子节点最少样本数 random_state=42 ) clf.fit(X_train, y_train) pred = clf.predict(X_test) print('测试集准确率:', accuracy_score(y_test, pred)) return clf

逻辑说明:时间序列数据绝对不能随机切分,train_test_split默认的 shuffle 会把未来信息泄露到训练集,导致回测虚高,这是新手最容易翻车的地方。max_depth=4是刻意压低的,决策树不加限制可以无限生长,训练集准确率能到 99% 但测试集一塌糊涂。min_samples_leaf=50保证每个叶子有足够样本支撑,避免模型记住噪声。如果你把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,都强制先跑一遍默认参数、记下基准结果,再动任何一行代码。这样后面改出问题时,至少知道是改坏了还是本来就这样。希望帮到你。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询