【维克】多重检验陷阱:为什么你找到的“规律“可能是假的?

【维克】多重检验陷阱:为什么你找到的“规律“可能是假的?
年化20%量化笔记 · 第32篇WHY 为什么测的策略越多你越容易被自己骗一个让量化新手崩溃的真相我带过一个徒弟叫小陈编程能力很强入行第一个月就写了个自动化回测框架。他的工作流是这样的先从网上搜罗了30多个技术指标——RSI、MACD、布林带、ATR、OBV、威廉指标……然后排列组合每个指标试3-5组参数跑了几百个策略版本。第三天他兴奋地找到我维克哥我测了200多个策略组合有15个p值小于0.05最好的那个年化收益35%夏普比1.8我问他你做了样本外测试吗还没有。你知道200次检验里光靠运气就会出现多少次p0.05吗他愣住了。我拿笔在纸上算给他看200次检验每次5%假阳性率预期出现200×0.0510次假阳性。你有15个显著结果其中至少8-10个可能纯粹是运气。他花了一周时间调出来的最优策略大概率是数据噪声的产物。这就是多重检验问题——你测的东西越多找到的规律越可能是假的。问题的本质概率论跟你开的一个残酷玩笑先理解一个基础概念当显著性水平α0.05时意味着如果策略本身完全无效你有5%的概率得到一个p0.05的显著结果。换句话说每测20个垃圾策略就有1个会看起来显著。这听起来好像问题不大但放到实际场景中就恐怖了你测试的策略数量预期假阳性数量全是垃圾策略时实际中你的感受201找到一个好策略502-3我有好几个有效信号1005我的框架太牛了成功率5%以上20010我的量化系统远超同行50025我是天才。测得越多你越觉得自己是天才但实际上你只是在概率的筛子里捞到了几块运气渣子。这不是理论问题——是实打实的钱量化交易不是学术论文。论文里的假阳性顶多被撤稿交易策略里的假阳性直接亏钱。我见过太多这样的案例•一个做加密货币量化的团队测了500多个因子组合挑出12个显著的因子构建组合策略回测年化40%。实盘运行3个月亏损8%。•一个个人交易者每天优化参数一周内把均线周期从5/20调到7/21再到8/19终于找到一组完美参数回测夏普比2.5。上线后连续止损。他们的共同错误不是能力不行而是不知道自己在被多重检验问题反噬。这也是为什么学术界有个说法叫数据挖掘偏差Data Mining Bias——你在数据里挖得越深找到的规律越多但这些规律越可能是数据本身的噪声而非真实的市场规律。HOW 如何应对多重检验问题——从识别到校正方法一Bonferroni校正——最简单粗暴的门槛提升意大利统计学家Bonferroni提出了一个极其优雅的解决方案如果你做了N次检验把每次的显著性标准从α提高到α/N。举个例子•你测了20个策略 → 显著性标准从0.05提高到0.05/200.0025•你测了100个策略 → 显著性标准提高到0.05/1000.0005•你测了500个策略 → 显著性标准提高到0.05/5000.0001只有p值低于这个更严格的标准才认为策略是显著的。原理很直观如果每次检验的假阳性率被压到足够低那么即使做很多次检验整体的假阳性率也被控制住了。实际操作// pythonimport numpy as np# 假设你有n个策略的p值列表p_values [0.001, 0.012, 0.003, 0.045, 0.008, 0.032, ...]n_tests len(p_values)# Bonferroni校正alpha 0.05corrected_alpha alpha / n_testsprint(f测试次数{n_tests})print(f原始显著性水平{alpha})print(f校正后显著性水平{corrected_alpha:.6f})# 哪些策略通过了校正for i, p in enumerate(p_values):if p corrected_alpha:print(f策略{i1}: p{p:.4f} → ✅ 通过校正)else:print(f策略{i1}: p{p:.4f} → ❌ 未通过)优点简单、严格、容易实现缺点过于保守——当测试次数很多时比如500次校正后的标准极其苛刻可能把真正有效的策略也过滤掉了方法二Holm-Bonferroni校正——Bonferroni的温和版本Bonferroni太保守了Holm提出了一个改进方案1.把所有p值从小到大排序2.最小的p值与α/N比较3.如果通过第二小的p值与α/(N-1)比较4.以此类推直到某个p值没通过后面全部判定为不显著// pythondef holm_bonferroni(p_values, alpha0.05):n len(p_values)sorted_indices np.argsort(p_values)sorted_p np.sort(p_values)results []for i, (idx, p) in enumerate(zip(sorted_indices, sorted_p)):threshold alpha / (n - i)passed p thresholdresults.append((idx 1, p, threshold, passed))if not passed:# 后面的全部判定为不显著for j in range(i 1, n):results.append((sorted_indices[j] 1, sorted_p[j], 0, False))breakreturn results# 使用results holm_bonferroni(p_values)for strategy_id, p, threshold, passed in results:status ✅ 显著 if passed else ❌ 不显著print(f策略{strategy_id}: p{p:.4f}, 阈值{threshold:.4f} → {status})比Bonferroni更灵活统计功效更高不容易漏掉真正有效的策略同时仍然控制整体假阳性率。方法三Benjamini-HochbergBH方法——控制错误发现率如果你做的检验特别多比如筛选几百个因子Bonferroni和Holm都太严格了。这时候可以用BH方法——它不控制至少出现一次假阳性的概率而是控制所有被判定为显著的结论中假阳性的比例。目标在所有被标记为显著的策略中假阳性的比例不超过α。// pythondef benjamini_hochberg(p_values, alpha0.05):n len(p_values)sorted_indices np.argsort(p_values)sorted_p np.sort(p_values)# 计算BH阈值thresholds [alpha * (i 1) / n for i in range(n)]# 找到最大的k使得p(k) threshold(k)passed_count 0for i in range(n):if sorted_p[i] thresholds[i]:passed_count i 1# 标记结果results []for idx in range(n):p p_values[idx]passed p thresholds[passed_count - 1] if passed_count 0 else Falseresults.append((idx 1, p, passed))return results, passed_countresults, count benjamini_hochberg(p_values)print(f共有{count}个策略通过BH校正)BH方法在量化因子筛选中特别实用——当你从500个候选因子中筛出20个时BH保证这20个里面假阳性的比例不超过5%。方法四样本外验证——最朴素也最可靠的土办法所有统计校正方法都有一个前提你的数据是固定的。但量化交易中我们还有更直接的武器——把数据分成两份。做法1.用前70%的数据训练集做策略开发、参数优化2.用后30%的数据测试集做验证3.只有在测试集上同样显著的策略才认为可能有效时间轴|———— 训练集70%————|———— 测试集30%————|策略开发、参数优化 独立验证可以用各种统计方法 只看结果关键原则测试集的数据在策略最终确定之前绝对不能看一眼。如果你反复在测试集上调试、改参数、重新测试——恭喜你你把测试集也变成了训练集多重检验问题又回来了。实操建议我的多重检验防御体系实际工作中我把这几个方法组合使用第一层减少不必要的检验├── 不是所有指标都值得测试。先用经济学逻辑筛选只测有理论支撑的假设├── 参数不要穷举。选3-5组有代表性的参数而不是从1到100遍历└── 记录每一次检验算清楚你到底做了多少次测试第二层统计校正├── 测试次数 20 → 用Bonferroni或Holm├── 测试次数 20-100 → 用Holm-Bonferroni├── 测试次数 100 → 用Benjamini-Hochberg└── 无论哪种方法都要在策略文档中记录原始p值和校正后p值第三层样本外验证├── 训练集/测试集拆分70/30或80/20├── 策略在训练集上开发在测试集上验证├── 测试集结果必须与训练集方向一致都是正收益└── 测试集上的效应不能衰减超过50%第四层经济逻辑终审├── 统计上通过了 → 最后问一个问题这个策略为什么能赚钱├── 如果说不清楚经济学逻辑即使统计显著也不上线└── 市场不是随机数生成器每个规律背后必须有可解释的机制WHAT 你带走的三个认知和一份防御清单核心认知1. 多重检验是量化交易者最隐蔽的敌人不像过拟合那样容易被理解多重检验问题更阴险——你可能每一步都看起来很科学p0.05、回测结果漂亮但因为测试了太多次大部分发现只是统计噪声。你不知道哪个是真的哪个是假的——只有实盘能告诉你答案但那时候已经太晚了。2. 不同场景用不同的校正方法•少量检验20次Bonferroni简单严格•中量检验20-100次Holm-Bonferroni平衡严格度和灵敏度•大量检验100次Benjamini-Hochberg控制错误发现率•无论哪种场景样本外验证都是最后一道防线3. 最好的防御是减少不必要的检验与其事后校正不如事前节制。每一次检验都应该有明确的经济学假说支撑而不是盲目穷举。量化不是测得越多越好而是测得越精准越好。☐立即统计你最近一次策略开发中总共做了多少次假设检验包括参数调整、不同时间窗口、不同指标组合。这个数字很可能比你想象的大10倍☐本周选择一种校正方法推荐从Holm-Bonferroni开始对你现有的策略结果重新做一次校正看看有多少显著策略还能存活☐本月在策略开发流程中强制加入检验次数记录环节——每测一次就记一笔累计到一定数量后自动触发校正流程☐长期习惯建立训练集/测试集拆分机制所有策略必须通过样本外验证才能进入模拟盘模拟盘通过才能进入实盘一句话总结你测了200次找到的最优策略大概率是200次里最幸运的那次而不是最好的那次。量化交易最贵的学费往往不是亏在错误的策略上而是亏在看起来对但实际上是假的策略上。年化20%量化笔记 · 第32篇 · 维克下一篇相关不等于因果交易中必须警惕的统计谬误