如何识别量化策略过拟合:gs-quant 实战体检指南
【免费下载链接】gs-quantPython toolkit for quantitative finance项目地址: https://gitcode.com/GitHub_Trending/gs/gs-quant
回测曲线漂亮,实盘却亏掉 20%——多数情况不是市场变了,而是量化策略过拟合在作怪。gs-quant 是一个 Python 量化金融工具包,其中的 timeseries 模块和 risk 模块提供了滚动风险度量、情景冲击等工具,可以帮你完成策略样本外测试这类检查。下面用一个具体策略走一遍完整的过拟合识别流程。
回测很漂亮,为什么实盘就翻车?
去年你上线了一个动量策略:回测夏普 3.5,最大回撤 8%,曲线平滑得像画出来的。实盘三个月,回撤 20%。
复盘时你会发现一个细节:回测用的那段行情,正是你反复调参的那段行情。策略并没有学会"动量",它只是把那段数据的噪声背了下来。
这就像背答案的差生:发卷前全对,换一套题就崩。所以第一步不是加参数,而是承认策略只对"考过的那套题"有效。
过拟合长什么样:屏幕上能看见的三个信号
样本内和样本外差一大截
同一段收益,切前后两半算指标,夏普从 3.0 掉到 0.8。差距越大,说明策略赚的钱越多来自"记住"而不是"学会"。所以把样本外夏普设为硬门槛,低于预期一半就回炉。
参数一调就崩
回看窗口 30 天时夏普 2.8,改成 29 天掉到 1.1。真实有效的逻辑通常对参数不敏感,敏感说明参数是碰出来的。所以调参时别只记录最优值,记录一整片参数邻域的表现。
换段数据就不灵
在 2019–2021 上涨段成立,放到 2022 震荡段直接亏损。单段行情无法区分"真规律"和"那一段的巧合"。所以任何策略上线前,至少要在一个风格不同的市场阶段跑过样本外检验。
gs-quant 的体检工具:你"怕什么"就查什么
怕参数是碰来的:看参数敏感性
把关键参数在邻域内扫一遍,看指标是否平稳。指标随参数大幅起伏,说明你找到的是噪声里的尖峰,不是规律:
for lookback in [20, 30, 40, 50]: s = run_strategy(lookback) print(lookback, sharpe_ratio(s.equity()))参数敏感性怎么算:邻域内夏普的标准差若超过均值的一半,就按"参数过度优化"处理。
怕只看了一段行情:用滚动窗口拆段
sharpe_ratio和 max_drawdown 都接受窗口参数 w,可以输出逐期滚动值,一眼看出策略在哪些月份贡献收益、哪些月份在扛回撤:
from gs_quant.timeseries.econometrics import sharpe_ratio, max_drawdown print(sharpe_ratio(equity, w=63).tail(), max_drawdown(equity, w=63).tail())若滚动夏普长期贴近 0 且靠少数几个窗口撑高全期均值,这个均值没有参考意义。
怕数据本身有偏:先做数据清洗
收益序列里有尖峰、日期错位,都会让回测虚高。statistics 模块里的 winsorize 可以压掉极端值;analysis 模块的 diff、lag 帮你核对信号和成交之间有没有用到"未来数据"。涉及组合层面压力测试时,risk 模块的 MarketDataShockBasedScenario 可以构造冲击情景。
一条策略的完整体检流程:从切数据到出结论
以"动量策略,回看 30 天,大市值股篮子,每日调仓"为例,按顺序做五件事:
- 切数据:按时间顺序 70% 训练、15% 验证、15% 测试,测试段全程封存:
n = len(equity) train, valid, test = equity[:int(n*0.7)], equity[int(n*0.7):int(n*0.85)], equity[int(n*0.85):] print(sharpe_ratio(train), sharpe_ratio(valid), sharpe_ratio(test))- 只在训练段调参,记录样本内夏普与对应的参数组合。
- 样本外一次性检验:用封存段跑一遍,不再回头改参数;改了就不算样本外了。
- 滚动对比:对训练段和封存段分别算滚动夏普与滚动回撤,看收益来源是否集中在个别窗口。
- 参数扰动:回看窗口在 15–60 天范围内扫描,输出指标分布。
多资产策略还可以先把篮子按风格聚类成几段分别检验,避免策略只在某一类资产上成立:
结论口径:三段夏普单调衰减且测试段仍为正,参数邻域指标平稳,才算通过;任何一条不满足,回炉而不是上线。
这些指标你可能看反了
| 指标 | 常见误读 | 更可靠的判断口径 |
|---|---|---|
| 夏普比率 | 越高越好 | ⚠️ 样本内超 3 更像危险信号;以样本外夏普为门槛 |
| 最大回撤 | 越小越稳 | 看滚动回撤在各时段的方差,单点最小值会骗人 |
| 参数尝试次数 | 试得多显得专业 | 尝试越多越可能"碰"中噪声;把尝试记录留档可复查 |
所以把"样本外夏普 ≥ 样本内夏普的一半"写成代码里的硬性断言,而不是写在脑子里。
📌 今天就能做:把你最新策略的收益曲线按时间切成三段,各算一次滚动夏普,把三个数贴进团队群。工具获取:git clone https://gitcode.com/GitHub_Trending/gs/gs-quant,从 README 开始。
【免费下载链接】gs-quantPython toolkit for quantitative finance项目地址: https://gitcode.com/GitHub_Trending/gs/gs-quant
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考