学习路线 03:缩减 Sharpe 比率 — 获得诚实的业绩估计
7步学习路线:从理解为什么你最佳的 Sharpe 很可能是被高估的,到为多重检验压缩,到报告诚实的数字。
目标:完成后,你将理解为什么回测报告的 Sharpe 几乎肯定太高,Deflated Sharpe Ratio 如何对此进行校正,以及如何报告诚实的业绩数字。
前置知识:基本统计(Sharpe 比率、p 值)和多重检验概念(从许多中选最佳)。
第 1 步:这是什么?
你运行了 30 个策略变体。最佳的一个 Sharpe 是 1.8。你的投资者很兴奋。你应该担心。
原因:你测试了 30 个策略。在 5% 显著性水平,你会期望 1.5 个仅凭运气显示”显著”正收益。你 30 个中的最佳可能只是最幸运的。
你看到的 Sharpe——1.8——是 30 次从均值为零的分布中抽取的最大值。最大值是有偏估计。Deflated Sharpe Ratio(DSR)修正了这个偏差。
DSR 告诉你:“考虑到你测试了 N 个策略,你最佳的 Sharpe 是真实的概率是多少,什么是被压缩后的估计?”
第 2 步:为什么这很重要?
一个真实场景。一个量化基金公布业绩:5 年 3.2 Sharpe。营销看起来很专业。回测文档很详尽。
然后策略开始表现不佳。不剧烈——但持续。到第 3 年,Sharpe 是 1.1。到第 5 年,是 0.8。
发生了什么?该基金多年来测试了数百个策略变体。他们报告了最佳的。他们报告的 3.2 Sharpe 是数百次试验的最大值。在零技能原假设下,报告最大值的期望可能约为 1.5。
3.2 Sharpe 的 DSR 可能是 1.2——仍然好,但不是 3.2。
如果你不压缩,你在对自己和你的投资者撒谎——关于真实预期表现。
第 3 步:核心机制
DSR 公式根据以下因素向下调整观察到的 Sharpe:
- 试验次数(m):你测试的策略越多,最大值因运气的膨胀越大。
- 样本量(T):数据越多,Sharpe 估计量的方差越低,期望最大值越低。
- 收益分布(偏度、峰度):非正态收益使 Sharpe 估计量更波动,膨胀期望最大值。
压缩后的 Sharpe 是:
其中 是在原假设(真实 Sharpe = 0)下,给定 m 次试验、T 个观测值和观察到的收益分布偏度(γ)的期望最大 Sharpe。
在零假设下,期望最大值随 √(2 ln(m) / T) 增长,对于厚尾收益增长更快。
第 4 步:关键公式
对于正态分布收益:
对于 m=30 策略,T=756(3 年日频数据):
对于非正态收益(考虑峰度 γ):
如果收益是尖峰态(γ² > 0),期望最大值更高。
压缩 Sharpe:
例如:观察最大 Sharpe = 1.8,E_max = 0.095,Sharpe 估计的样本标准差 = 0.3:
这太高了。如果标准误非常小,DSR 可能超过观察 Sharpe。有意义的比较是相对于其他策略的 DSR,不是相对于原始 Sharpe。
第 5 步:实现
import numpy as np
from scipy import stats
def deflated_sharpe_ratio(returns_matrix, risk_free=0.0, periods_per_year=252):
"""
计算一组策略的 Deflated Sharpe Ratio。
"""
n_samples, n_strategies = returns_matrix.shape
# 观察 Sharpe 比率
excess = returns_matrix - risk_free / periods_per_year
mean_excess = np.mean(excess, axis=0)
std_excess = np.std(excess, axis=0, ddof=1)
osr = np.zeros(n_strategies)
valid = std_excess > 0
osr[valid] = mean_excess[valid] / std_excess[valid] * np.sqrt(periods_per_year)
T = n_samples
m = n_strategies
# 零假设下的期望最大 Sharpe
e_max_normal = np.sqrt(2 * np.log(m) / T)
# 根据峰度调整
kurtosis = np.zeros(n_strategies)
for j in range(n_strategies):
ret = returns_matrix[:, j]
if np.std(ret) > 0:
ret_standardized = (ret - np.mean(ret)) / np.std(ret)
kurtosis[j] = np.mean(ret_standardized**4)
gamma_sq = np.maximum(kurtosis - 3, 0)
adjustment = 1 + gamma_sq / 4
e_max_adjusted = e_max_normal * adjustment
# 标准误
se_sharpe = 1 / np.sqrt(T)
# Deflated Sharpe
dsr = np.zeros(n_strategies)
valid = (std_excess > 0) & (se_sharpe > 0)
dsr[valid] = (osr[valid] - e_max_adjusted[valid] * np.sqrt(periods_per_year)) / (se_sharpe * np.sqrt(periods_per_year))
return {
'dsr': dsr,
'osr': osr,
'e_max': e_max_adjusted * np.sqrt(periods_per_year),
'n_strategies': m,
'n_observations': T
}
第 6 步:如何解读结果
比较 DSR,不是原始 Sharpe。 如果你从 30 个策略变体中选择,按 DSR 排名,不是按原始 Sharpe。DSR 考虑了你选择了最大值这一事实。
DSR > 1.0 意味着策略可能是真实的。 更准确地说,对于 T 个观测值,DSR > 1.96 意味着在多重检验压缩后策略在 5% 水平显著。
两者都报告。 “我们最佳策略观察 Sharpe 1.8,在 30 次试验调整后压缩 Sharpe 1.2。“这是诚实的和有信息的。
注意负 DSR。 如果你最佳策略的 DSR 为负,意味着即使压缩后,最佳策略看起来比零假设下的期望最大值还差。这是红旗——要么你最佳策略是无价值的,要么你需要更多数据。
第 7 步:常见陷阱 + 在知识体系中的位置
陷阱:假装你只测试了一个策略。 如果你测试了 100 个变体但只报告最佳的,你必须压缩。在这种情况下 DSR 是不可协商的。
陷阱:使用 m = 1(一个策略)。 m=1 的 DSR 得到标准 Sharpe。可以——DSR 推广到单一策略情况。
陷阱:忽略非正态性。 如果收益是厚尾,E_max 高于正态公式。建议的。使用正态公式会低估膨胀,你的 DSR 会太高。总是根据峰度调整。
陷阱:跨不同 m 比较 DSR。 来自 10 次试验的 DSR = 1.5 的策略比来自 100 次试验的 DSR = 1.5 更令人印象深刻。m 很重要。
在知识体系中的位置:
- 当从许多策略变体中选择时
- 当向投资者报告业绩记录时
- 每当进行多重检验时作为标准 Sharpe 的校正
DSR 是更广泛框架的一部分:多重检验校正和 PBO。它们一起给你一个关于策略真实预期表现的诚实画面。
下一步
准备好下一级了吗?→ 学习路线 04:回测过拟合(PBO)
想要百科参考卡片?→ 多重检验(百科词条)