第一章 过度拟合:历史回测漂亮,实盘却一塌糊涂
做量化投资的人,谁没做过几个「完美」的回测?
曲线漂亮得像教科书上的范例,夏普比率高得吓人,最大回撤小得让人不敢相信。我当时刚入行那会儿,看到这种回测结果,第一反应就是——发财了。
结果呢?实盘一跑,直接被打回原形。亏得我怀疑人生。
为什么会这样?说白了,就是过度拟合。
1.1 什么是过度拟合?
过度拟合,用大白话讲就是:你的模型把历史数据里的「噪音」当成了「信号」来学。
你想想看,市场里每天都有随机波动。有些涨跌纯粹是运气,没有任何规律可循。但你的模型不管这些,它拼命去拟合每一个小波动,最后记住的其实是市场的「杂音」,而不是真正的规律。
我见过最夸张的一个案例:有人用200个参数去拟合5年的日线数据。回测结果年化收益80%,最大回撤不到5%。我当时就说,这玩意儿肯定有问题。果不其然,实盘三个月亏了40%。
核心观点:回测是过去,实盘是未来。过度拟合的本质,是用过去的数据「欺骗」了你自己。
1.2 过度拟合的典型症状
怎么判断你的策略是不是过度拟合了?我总结了几个常见症状,你对照看看:
- 参数极其敏感:稍微改一点点参数,收益就大变样。比如移动平均线从20日改成21日,年化收益从30%变成-10%。
- 策略复杂度高:用了十几个条件叠加,几十个参数组合。越复杂的策略,越容易过拟合。
- 样本外表现断崖式下跌:回测期表现完美,一到样本外测试(比如2018年之后的数据),直接崩盘。
- 交易次数异常多:为了捕捉每一个小波动,模型频繁开仓平仓。交易成本一算,利润全没了。
警告:如果你发现自己的策略在回测中「完美无瑕」,那它大概率是有问题的。真正的策略,回测时应该有一些「不完美」的地方。
1.3 为什么会过度拟合?
我这些年做下来,发现过度拟合的原因无非这么几个:
- 数据窥探偏差:你反复看同一段数据,不断调整参数,直到找到「最好」的那一组。这就像考试前先看了答案,然后说自己考了满分。
- 幸存者偏差:只用了存活下来的股票做回测,退市的、ST的全都忽略了。回测结果当然好看,但实盘里你躲不开这些雷。
- 前视偏差:不小心用了未来的数据。比如用今天的收盘价去预测今天的涨跌,这属于作弊,但很多人不知不觉就犯了。
- 过度优化:为了追求极致的回测指标,不断添加条件、调整参数,直到模型「记住」了所有历史走势。
我记得有一次,一个朋友兴冲冲地给我看他新开发的策略。回测曲线漂亮得不像话,年化收益50%以上。我问他:「你用了多少参数?」他说:「大概30多个吧。」我又问:「你回测了多久?」他说:「从2010年到2020年,10年数据。」
我当时就笑了。30个参数,10年数据,平均每个参数只有4个月的数据来「学习」。这跟瞎蒙有什么区别?
1.4 如何避免过度拟合?
嗯,这里要注意。避免过度拟合不是让你不做回测,而是让你用正确的方法做回测。我分享几个实战经验:
方法一:样本外测试
把数据分成两部分:训练集和测试集。训练集用来开发策略,测试集用来验证策略。如果测试集上的表现和训练集差不多,那说明策略是靠谱的。
小技巧:我个人习惯把数据按时间切分,比如前70%做训练,后30%做测试。千万别随机切分,时间序列数据有顺序性,随机切分会引入前视偏差。
方法二:交叉验证
把数据分成K份,轮流用K-1份训练,1份测试。这样能更充分地利用数据,也能检验策略在不同时间段的表现。
# 一个简单的滚动交叉验证示例
import pandas as pd
import numpy as np
def rolling_cv(data, window_size=252, step_size=63):
"""
滚动交叉验证
window_size: 训练窗口长度(252个交易日约1年)
step_size: 滚动步长(63个交易日约1季度)
"""
results = []
for start in range(0, len(data) - window_size, step_size):
train = data.iloc[start:start + window_size]
test = data.iloc[start + window_size:start + window_size + step_size]
# 在训练集上训练策略
# 在测试集上测试策略
# 记录结果
return results
方法三:简化模型
奥卡姆剃刀原则:如无必要,勿增实体。能用3个参数解决的问题,别用10个。简单的模型往往更稳健。
我自己的经验是:一个策略的参数最好不要超过5个。超过这个数,你就要开始怀疑它是不是过度拟合了。
方法四:加入惩罚项
在优化目标中加入参数数量的惩罚项。参数越多,惩罚越大。这样模型会自动倾向于选择更简单的方案。
实战建议:我一般会用AIC(赤池信息准则)或BIC(贝叶斯信息准则)来评估模型。这两个指标都包含了参数数量的惩罚项,能有效防止过度拟合。
1.5 一个真实的教训
我曾经开发过一个多因子选股策略。回测做了整整三个月,参数调了上百次。最终版本用了7个因子,每个因子还有3-4个子参数。回测结果堪称完美:年化收益35%,最大回撤8%,夏普比率2.5。
我当时信心满满,直接上了实盘。结果呢?第一个月就亏了12%。我赶紧复盘,发现策略在回测期表现最好的那几个因子,在实盘期完全失效了。说白了,那些因子只是碰巧在回测期有效,本质上就是噪音。
从那以后,我给自己定了个规矩:任何策略,如果回测夏普比率超过2,我就要重新审视一遍。因为真正的策略,夏普比率能到1.5就已经很优秀了。
1.6 知识体系总览
下面这张图,是我对过度拟合这个问题的整体理解。你可以把它当作一个检查清单,每次做回测前都过一遍:
1.7 写在最后
过度拟合这个问题,说白了就是「贪」。贪图回测的漂亮数字,贪图完美的曲线。但市场是残酷的,它不会因为你回测做得好就给你赚钱。
我做了这么多年量化,最大的体会就是:回测是用来排除策略的,不是用来选择策略的。一个策略如果连回测都过不了,那肯定不行。但一个策略如果回测太完美,那也肯定有问题。
记住一句话:在量化投资里,没有免费的午餐。任何看起来太美好的东西,背后都有代价。
避坑指南:我曾经因为过度拟合亏过不少钱。现在我的做法是:每个策略必须经过至少3个月的模拟盘测试,才能上实盘。模拟盘期间,我只看不动,让市场来检验策略的真伪。
公众号:蓝海资料掘金营,微信deep3321