
用 Python 揭秘均值回归策略:你的收益从何而来?
2026年重磅升级已全面落地!欢迎加入专注财经数据与量化投研的【数据科学实战】知识星球!您将获取持续更新的《财经数据宝典》与《量化投研宝典》,双典协同提供系统化指引;星球内含 350 篇以上独有高质量文章,深度覆盖策略开发、因子分析、风险管理等核心领域,内容基本每日更新;同步推出的「量化因子专题教程」系列(含完整可运行代码与实战案例),系统详解因子构建、回测与优化全流程,并实现日更迭代。我们持续扩充独家内容资源,全方位赋能您的投研效率与专业成长。无论您是量化新手还是资深研究者,这里都是助您少走弯路、事半功倍的理想伙伴,携手共探数据驱动的投资未来!
如果有人告诉你他的量化策略夏普比率达到 0.86,年化收益 14.6%,你会心动吗?
最近读到一篇有趣的实验文章。作者用 Python 构建了一个回测系统,生成了 1000 个完全基于「噪声」的交易策略,结果最好的那个看起来居然像模像样。这个实验揭示了量化研究中一个非常容易被忽视的陷阱 —— 选择偏差(Selection Bias)。
对于学习 Python、对量化感兴趣的小伙伴来说,这个实验非常值得了解。本文带你一起看看作者是怎么做的,并用 Python 复现核心思想。
作者搭建了一个完整的回测流水线,主要参数如下:
关键设计:这些信号本来就不应该有效。实验目的不是找到好策略,而是看看从一堆噪声里「挑出最好的」会有多么误导人。
1000 个策略里,73 个夏普超过 0.75,但全部都是噪声!更可怕的是,中位数信息比率(相对 SPY)是 -0.37,说明所谓的「收益」基本都是市场 Beta,和策略本身没关系。
这是最核心的发现。当你测试的策略数 N 越大,「最佳夏普」就会机械性地升高:
策略本身没变好,你只是搜索得更狠了而已。
作者拿样本内排名前 20 的策略放到样本外去跑:
平均夏普被成本拉低 0.303,CAGR 被拉低 6.05 个百分点。
下面我们用 Python 简单复现「Best-of-N 陷阱」的核心思想,让大家直观感受一下:
import numpy as npimport matplotlib.pyplot as plt# 设置随机种子,保证结果可复现np.random.seed(42)# 模拟 1000 个完全随机的「策略」# 每个策略生成 10 年的日收益(约 2520 个交易日)n_strategies = 1000n_days = 252 * 10# 生成纯随机收益(均值 0,年化波动 20%)random_returns = np.random.normal( loc=0, scale=0.20 / np.sqrt(252), size=(n_strategies, n_days))# 计算每个策略的年化夏普比率def annual_sharpe(returns): """计算年化夏普比率""" mean_daily = returns.mean() std_daily = returns.std() return (mean_daily / std_daily) * np.sqrt(252)# 计算所有策略的夏普sharpes = np.array([annual_sharpe(r) for r in random_returns])# 模拟 Best-of-N 现象# 从 1000 个策略中随机抽取 N 个,看看「最佳夏普」如何变化N_levels = [10, 50, 100, 250, 500, 1000]n_simulations = 2000 # 蒙特卡洛模拟次数print("【Best-of-N 选择偏差实验】")print("=" * 40)for N in N_levels: # 重复 2000 次,每次抽 N 个取最大值 best_values = [] for _ in range(n_simulations): sample = np.random.choice(sharpes, size=N, replace=False) best_values.append(sample.max()) # 输出平均最佳夏普 print(f"测试 {N:>4d} 个策略 -> 最佳夏普均值:{np.mean(best_values):.3f}")# 绘制夏普分布直方图plt.figure(figsize=(10, 5))plt.hist(sharpes, bins=50, color='skyblue', edgecolor='black')plt.axvline(np.median(sharpes), color='red', linestyle='--', label=f'中位数:{np.median(sharpes):.2f}')plt.axvline(np.max(sharpes), color='green', linestyle='--', label=f'最大值:{np.max(sharpes):.2f}')plt.xlabel('年化夏普比率')plt.ylabel('策略数量')plt.title('1000 个纯噪声策略的夏普分布')plt.legend()plt.tight_layout()plt.show()运行后你会发现:测试的策略越多,「看起来最好」的那个就越漂亮,但本质上它们都是噪声。
这个实验最有价值的不是某个具体策略,而是它用 1000 次实验告诉我们:当你在足够大的搜索空间里寻找「好结果」时,运气一定会给你一个看起来很美的答案。
对于刚入门 Python 量化的同学,与其追求一个夏普 1.0+ 的「圣杯策略」,不如先把回测框架的严谨性、样本外验证、交易成本建模这些基本功打扎实。好的研究流程比好的回测结果重要得多。
记住一句话:The numbers are real. The alpha isn't.(数字是真的,超额收益是假的。)
2026年全面升级已落地!【数据科学实战】知识星球核心权益如下:
星球已沉淀丰富内容生态——涵盖量化文章专题教程库、因子日更系列、高频数据集、PyBroker实战课程、专家深度分享与实时答疑服务。无论您是初探量化的学习者,还是深耕领域的从业者,这里都是助您少走弯路、高效成长的理想平台。诚邀加入,共探数据驱动的投资未来!
好文推荐
1. 用 Python 打造股票预测系统:Transformer 模型教程(一)
2. 用 Python 打造股票预测系统:Transformer 模型教程(二)
3. 用 Python 打造股票预测系统:Transformer 模型教程(三)
4. 用 Python 打造股票预测系统:Transformer 模型教程(完结)
6. YOLO 也能预测股市涨跌?计算机视觉在股票市场预测中的应用
9. Python 量化投资利器:Ridge、Lasso 和 Elastic Net 回归详解
好书推荐