绩效报告:五个指标各自的失效场景
我预期的"排名冲突"没出现——找它的过程比结论更有用
夏普、Sortino、Calmar——三个都叫"风险调整收益"。
我原本要演示的是:它们会给出互相矛盾的排名。
实测结果:在 5 只标的上,三个指标的排名完全一致,最大排名差 0 名。
预期落空。但找它的过程,比原来的结论更有用——排名冲突出现在"表现接近、而净值形态不同"的时候。换一组对象(同一标的的策略 vs 买入持有),冲突立刻出现了。
这一节讲的不是公式(公式网上都有),是每个指标在什么时候不能信。
体检报告上有身高、体重、BMI、体脂率。
BMI 说你超重,体脂率说你正常——这不是仪器坏了,是两个指标对"胖"的定义不同(一个只看身高体重,一个看脂肪占比)。
绩效指标也一样。夏普、Sortino、Calmar 对"风险"的定义各不相同。
只报一个,等于替读者选了一个定义,而没告诉他。
一、完整绩效报告
同一条 MA5/20 策略,5 只标的:
| 标的 | 累计% | 年化% | 波动% | 最大回撤% | 夏普 | Sortino | Calmar | 最长水下(天) | 偏度 | 超额峰度 |
|---|---|---|---|---|---|---|---|---|---|---|
| sh.600000 | 58.59 | 2.82 | 17.11 | -36.36 | 0.17 | 0.19 | 0.08 | 1207 | 0.89 | 15.48 |
| sh.600009 | -14.70 | -0.96 | 20.90 | -59.91 | -0.05 | -0.05 | -0.02 | 1706 | 0.29 | 10.19 |
| sh.600010 | 19.55 | 1.08 | 28.43 | -80.08 | 0.04 | 0.04 | 0.01 | 2729 | 1.24 | 11.44 |
| sh.600011 | 46.37 | 2.33 | 24.68 | -55.32 | 0.09 | 0.11 | 0.04 | 1507 | 0.73 | 11.31 |
| sh.600015 | -8.90 | -0.56 | 17.82 | -48.23 | -0.03 | -0.03 | -0.01 | 2743 | 0.37 | 17.24 |
"最长水下天数"这一列,是绝大多数报告不给的,而它往往最能说明问题。
sh.600015 有 2743 天在水下——按每年 243 个交易日算,超过 11 年没创新高。年化 -0.56% 这个数字很温和,而 11 年不创新高是另一回事。
二、排名冲突:预期落空,然后换个方式找
第一次尝试:同一策略在 5 只标的上
| 标的 | 夏普 | Sortino | Calmar |
|---|---|---|---|
| sh.600000 | 1 | 1 | 1 |
| sh.600011 | 2 | 2 | 2 |
| sh.600010 | 3 | 3 | 3 |
| sh.600015 | 4 | 4 | 4 |
| sh.600009 | 5 | 5 | 5 |
最大排名差:0 名。完全一致,没有冲突。
这与我的预期相反,需要解释,而不是换个数据重跑。
原因:这 5 只的表现差距足够大(夏普从 -0.05 到 0.17)。三个指标虽然定义不同,但在差距大的样本上,会给出同一个顺序。
排名冲突出现在"表现接近、而净值形态不同"的时候。
所以正确做法不是换数据,是换一组更能暴露差异的对象。
第二次尝试:同一标的的"策略 vs 买入持有"
这两条曲线形态截然不同(一条频繁进出、一条一直持有),而收益又接近:
| sh.600011 | 年化% | 最大回撤% | 夏普 | Sortino | Calmar |
|---|---|---|---|---|---|
| 策略 | 2.33 | -55.32 | 0.094 ✓ | 0.109 | 0.042 ✓ |
| 买入持有 | 2.61 | -67.18 | 0.075 | 0.111 ✓ | 0.039 |
夏普说策略赢,Sortino 说买入持有赢,Calmar 说策略赢。
5 只标的里,1 只出现了这种冲突。
比例不高,但它足以说明问题:当你只报一个指标时,你不知道另外两个会不会给出相反的结论。
三、夏普的两个失效场景
失效一:厚尾
夏普的分母是标准差。而 p3.1 实测过:收益率是厚尾的,4σ 事件的实际频率是正态预期的 102 倍。
策略净值同样如此:
| 标的 | 超额峰度 | 3σ 以上实际天数 | 正态预期 | 倍数 |
|---|---|---|---|---|
| sh.600000 | 15.48 | 96 | 10.7 | 8.9 倍 |
| sh.600009 | 10.19 | 83 | 10.8 | 7.7 倍 |
| sh.600010 | 11.44 | 120 | 10.7 | 11.3 倍 |
标准差在厚尾分布下系统性低估尾部风险 → 夏普系统性高估策略质量。
失效二:它同样惩罚上行波动
一个"平时不动、偶尔暴涨"的策略,上行波动会拉高标准差 → 夏普被压低。
而这种形态,恰恰是很多趋势策略的正常样貌(看上表的偏度列:全部为正,0.29~1.24)。
这正是 Sortino 存在的理由:分母只用下行波动。
四、稳定性:哪个指标样本外最不可靠
把每只标的的数据一切为二,比较前后半段:
| 标的 | 夏普前 | 夏普后 | Sortino前 | Sortino后 | Calmar前 | Calmar后 |
|---|---|---|---|---|---|---|
| sh.600000 | 0.32 | -0.05 | 0.38 | -0.05 | 0.20 | -0.02 |
| sh.600009 | 0.23 | -0.38 | 0.28 | -0.43 | 0.15 | -0.12 |
| sh.600010 | -0.06 | 0.15 | -0.06 | 0.18 | -0.02 | 0.10 |
| sh.600011 | 0.14 | 0.01 | 0.16 | 0.01 | 0.07 | 0.01 |
| sh.600015 | 0.03 | -0.14 | 0.04 | -0.14 | 0.02 | -0.05 |
前后半段相关:夏普 -0.502 | Sortino -0.537 | Calmar -0.574
样本只有 5 只,这三个相关系数不足以下任何结论。
我把它们放出来,是为了演示方法,不是为了得出"绩效指标不可外推"这个判断——那需要几百个策略样本才谈得上。
但它指向一个应当被认真对待的问题:Calmar 的分母是单次事件。
一次极端回撤就能决定它,而那次回撤会不会重演,没人知道。三个指标里,它的分母样本量最小(n=1),理论上也最不稳定。
🔧 动手做:证明"过去的风险调整收益"预测不了未来(7 分钟)
夏普、Sortino、Calmar 都号称"风险调整后的收益"。那前半段表现好的,后半段还好吗?跑 python metrics.py,看【四】稳定性——每只标的前半段 vs 后半段的三个指标。
你会看到(实测):前后半段的相关性是负的——夏普 -0.50、Sortino -0.54、Calmar -0.57。也就是说:前半段夏普高的,后半段反而更可能低。
想明白:Calmar 最差(-0.57),因为它的分母是最大回撤 = 单次事件——一次极端回撤就定死它,而那次回撤会不会重演,没人知道(样本只有 5 只,数值仅作方向参考,但方向本身就是警告)。所以:别拿历史夏普/Calmar 排名去挑策略或基金——它不仅不预测未来,在这个样本上还反着来。 五个指标一起看,并盯最长水下天数。
五、报告纪律
- 五个指标一起报——年化、最大回撤、夏普、Sortino、Calmar
- 加上最长水下天数——它回答"我要熬多久",而这是持有人最真实的体验
- 加上偏度与峰度——它们告诉读者"夏普在这个样本上可不可信"
- 加上参数清单(p4.2)——否则以上全部无法复核
只报夏普,等于把"风险"这个词的定义权,悄悄交给了标准差。
📌 免责:本课为技术教学,标的为沪深300 成分股按代码序取样(非精选),所有回测为历史模拟,不构成投资建议。
这一节最值得带走的,是那次预期落空:
- 第一次尝试:同一策略在 5 只标的上,三个指标排名完全一致(最大排名差 0)
- 原因:表现差距足够大时,三个指标会给出同一顺序;冲突出现在"表现接近、形态不同"时
- 第二次尝试:换成"策略 vs 买入持有",1/5 出现冲突(sh.600011:夏普与 Calmar 说策略赢,Sortino 说买入持有赢)
其余三条实测结论:
- 夏普的两个失效场景:厚尾(策略净值超额峰度 10
17,3σ 事件是正态预期的 7.711.3 倍)+ 它同样惩罚上行波动 - 最长水下天数:sh.600015 有 2743 天在水下——超过 11 年没创新高,而它的年化只是 -0.56%
- 稳定性:前后半段相关全为负(-0.50~-0.57),但样本只有 5 只,不足以下结论——放出来是为了演示方法
报告纪律:五个指标一起报 + 最长水下 + 偏度峰度 + 参数清单。
下一节把这些做成图:净值、回撤、月度热力、盈亏分布、基准对比——承接 p1.8 的绘图工程,包括那条一行代码的血缘水印。
🔎 来源与核验· 4 条,点开核对
