4、过拟合的量化指标:过拟合概率(PBO)、方差分析、策略参数稳定性测试、蒙特卡洛模拟
说实话,很多做量化的人都有过这种经历:回测曲线漂亮得不像话,一上实盘就崩。我以前也踩过这个坑,后来才明白——光靠眼睛看曲线是不够的,得用数学工具把过拟合给「揪」出来。
这一节,我带你看看四个硬核指标。它们能帮你量化判断:你的策略到底是真的找到了规律,还是纯粹在拟合噪音。
4.1 过拟合概率(PBO)
PBO,全称是 Probability of Backtest Overfitting。这玩意儿是 Bailey 等人提出来的,核心思想很简单:如果策略真的有效,那么它在不同参数下的表现应该相对稳定;如果过拟合了,那么最优参数和次优参数之间的差距会非常大。
怎么算?我习惯用「排名检验法」。大致流程是这样的:
- 把样本内数据分成若干段,比如 10 段。
- 对每一段,跑一遍所有参数组合,记录每个参数组合的夏普比率排名。
- 看样本外数据中,这些参数组合的排名是否还保持稳定。
如果样本内排名第一的参数,到了样本外直接掉到倒数,那 PBO 值就会很高。我个人觉得,PBO 超过 0.5 就要高度警惕了。
- PBO < 0.3:过拟合风险较低
- 0.3 ≤ PBO < 0.5:中等风险,需要进一步验证
- PBO ≥ 0.5:高度过拟合,建议重新设计策略
这里有个小坑——PBO 对参数空间的大小很敏感。你想想看,如果你只测了 5 组参数,那 PBO 算出来可能不准。我建议至少测 50 组以上的参数组合,结果才有统计意义。
4.2 方差分析
方差分析,听起来挺学术的,说白了就是看「不同参数对策略收益的影响有多大」。如果某个参数稍微变一点点,收益就剧烈波动,那这个参数很可能是在拟合噪音。
我常用的方法是 ANOVA(方差分析)。具体来说,就是把参数作为因子,把夏普比率或收益率作为响应变量,然后看 F 统计量和 p 值。
# 伪代码示例:ANOVA 分析
import statsmodels.api as sm
from statsmodels.formula.api import ols
# 假设 df 包含参数 A、参数 B 和对应的夏普比率
model = ols('Sharpe ~ C(Param_A) + C(Param_B) + C(Param_A):C(Param_B)', data=df).fit()
anova_table = sm.stats.anova_lm(model, typ=2)
print(anova_table)
输出结果里,重点关注 p 值。如果某个参数的 p 值大于 0.05,说明它对策略表现没有显著影响——这种参数你大可以固定下来,别让它增加过拟合风险。
4.3 策略参数稳定性测试
这个测试,我习惯叫它「参数扫雷」。核心思想是:一个稳健的策略,它的参数应该有一个「平坦区」——在这个区域内,参数怎么变,收益都差不多。
怎么做?我一般画一张热力图。横轴是参数 A,纵轴是参数 B,颜色深浅代表夏普比率。如果最优参数周围是一片「红色高原」,那说明策略稳健;如果只有孤零零一个「红色尖峰」,周围全是蓝色低谷,那八成是过拟合了。
参数稳定性测试的量化指标,我推荐用 「参数敏感度系数」:
敏感度系数 = (最优参数夏普 - 邻域参数平均夏普) / 最优参数夏普
这个系数越小越好。我个人的经验是:系数小于 0.2 算稳健,大于 0.5 就要小心了。
4.4 蒙特卡洛模拟
蒙特卡洛模拟,说白了就是「用随机性来检验确定性」。你想想看,你的策略回测只有一条路径,但市场有无数种走法。蒙特卡洛模拟就是帮你生成成千上万条「如果历史重演」的路径,看看策略在大多数情况下是否还能赚钱。
我常用的方法有两种:
- 残差重采样法: 把策略的每日收益率序列拆出来,然后随机打乱顺序,重新生成收益率序列。这样能保留收益率的分布特征,但破坏了时序相关性。
- 参数扰动法: 在最优参数附近加一点随机噪声,然后重新跑回测。重复 1000 次,看收益率的分布情况。
# 伪代码示例:蒙特卡洛模拟(残差重采样)
import numpy as np
# 原始策略收益率序列
returns = strategy_returns # 假设这是一个 numpy 数组
n_simulations = 1000
simulated_sharpes = []
for i in range(n_simulations):
np.random.shuffle(returns) # 打乱顺序
simulated_sharpes.append(np.mean(returns) / np.std(returns))
# 看模拟结果的分布
pct_5 = np.percentile(simulated_sharpes, 5)
pct_95 = np.percentile(simulated_sharpes, 95)
print(f"90% 置信区间: [{pct_5:.2f}, {pct_95:.2f}]")
如果模拟出来的夏普比率 90% 置信区间下限大于 0,那说明策略在大多数「平行宇宙」里都是赚钱的。反之,如果区间跨越了 0,甚至大部分是负的,那你的回测结果很可能只是运气好。
- 模拟次数建议至少 1000 次,越多越稳定
- 关注置信区间,而不是单点估计值
- 如果模拟结果中,超过 20% 的路径是亏损的,那策略的过拟合风险很高
4.5 四个指标的综合运用
这四个指标,单独看哪一个都有局限性。我个人的习惯是「四管齐下」:
- 先用 PBO 快速筛查,如果 PBO 太高,直接放弃
- 再用 方差分析 找出哪些参数是「噪音参数」,固定它们
- 然后用 参数稳定性测试 找到平坦区,确认最优参数不是孤立的尖峰
- 最后用 蒙特卡洛模拟 做压力测试,看看策略在各种随机场景下的表现
只有四个指标都通过了,我才会考虑把策略放到模拟盘上跑。嗯,这套流程虽然繁琐,但能帮你省下不少实盘亏钱的血泪教训。
这张图就是我平时用的评估流程。从左到右,四个指标依次检验,任何一个不过关就返回重新设计。别嫌麻烦,我见过太多人跳过这些步骤,直接拿回测结果上实盘,结果亏得连裤衩都不剩。