卡玛比率:把「你能不能扛住」压成一个数
有人拿一份成绩单给你看:年化 30%,夏普比率 1.8。数字都不错,你却没法回答一个更要紧的问题——这套东西,我拿得住吗?
「拿得住」不是一个文艺的说法。它是一个非常具体的时刻:账户从最高点往下掉,你每天打开手机看一眼,心里那根弦一天比一天紧,直到某一天你受不了了,全清。清完之后曲线转头往上——你亏在了自己扛不住的地方,而不是亏在方法错了。
夏普比率回答不了这件事。它衡量的是「平均颠簸」,而人崩溃的时刻从来不发生在平均值上。卡玛比率就是冲着这个缺口来的:它把分母从波动率换成了最大回撤——历史上你的账户从最高点跌到最低点,那一次跌得最狠的幅度。
先说人话:它和夏普到底差在哪
想象两条上山的路,终点海拔一样。
第一条路一直缓坡,走起来累但心里稳。第二条路先冲到山腰,然后猛地下切一段几百米深的沟,再爬上来到同一个终点。
如果你在山脚问「哪条路更颠」,把每一小段的起伏都平均一下——两条路可能得分接近,因为第二条大部分时间也挺平缓,那道深沟只占全程的一小截。这就是夏普比率的算法:把所有的起伏一视同仁地平均。
可如果你问的是「哪条路会让人半路放弃」,答案毫无悬念是第二条。让人放弃的从来不是平均坡度,是那道沟有多深、你在沟底待了多久。卡玛比率量的就是这道沟。
一句话讲清两者的分工:
- 夏普比率:每承担一份平均波动,换来多少超额收益。分母是波动率,一个统计量。
- 卡玛比率:每承受一次最深的下坠,换来多少年化收益。分母是最大回撤,一个历史上真实发生过的单点。
夏普与索提诺的完整机制(包括索提诺为什么只惩罚下行波动)在 夏普比率与索提诺比率 里已经讲透,这里不重复。本篇只盯住卡玛独有的那件事:它的分母不是估计出来的,是数出来的。
这个差别比它看起来重要得多,后面全篇都在展开它的后果。
投资层:分母是「极值」意味着什么
把分母从统计量换成极值,换来一个好处,也换来三个麻烦。
好处是它和体感对齐。 你事后回忆一段投资经历,脑子里留下的从来不是标准差,是「那次我账户少了三成」。卡玛比率用的正是这个你真会记住的数。所以拿它做横向比较时,问的其实是一句大白话:为了赚这些钱,我最难受的那一次有多难受?
麻烦从这里开始。
麻烦一:一个点决定一切。 波动率是几百上千个数据点共同算出来的,改动其中一天,结果几乎不动。最大回撤不是——它只由两个日子决定:那个最高点,和那个最低点。中间所有别的日子对它毫无贡献。这意味着卡玛比率的分母是极不稳定的:样本区间往前挪三个月、往后挪三个月,只要那道最深的沟被切出去了,分母立刻变小,卡玛比率瞬间翻倍。而你的方法一个字都没改。
麻烦二:它只知道已经发生过的最坏。 这一条最容易被忽略。最大回撤描述的是「历史上跌过多深」,不是「最多会跌多深」。一段没赶上熊市的样本,它的最大回撤天然就小,卡玛比率天然就高。换句话说,回撤这个分母是系统性偏乐观的——没经历过的坏日子,一天都不会计入其中。样本越短,这份乐观越离谱。
麻烦三:它没有时间维度。 跌 30% 三个月回本,和跌 30% 三年回本,最大回撤一模一样,卡玛比率也一模一样。可这两件事对人的折磨完全不是一个量级。真正把人熬走的往往不是深度而是长度,而卡玛比率对长度完全失明。想补上这个维度得看别的东西,这正是 回撤恢复期 单独存在的理由;回撤本身怎么从数字变成体感,最大回撤:从数字到体感 讲得更细。
系统层:同一条曲线,为什么能算出两个卡玛
上面说的都还是概念。真到了系统里,会冒出一个更麻烦的事实:卡玛比率不是一个有唯一答案的数。
freqtrade 是一套开源的量化交易框架,回测(拿历史数据把规则重跑一遍,看会赚会亏)跑完会输出一大张成绩单。它的文档里贴了一份示例输出,同一次回测,成绩单上出现了两行都叫 Calmar 的数字:一行标着 closed trades(只看已平仓的交易),另一行标着 daily wallet balance(按每日钱包余额算,含未平仓的浮盈浮亏)。两个数字差了大约三倍。(具体数值来自文档的示例样本,换个样本就不是这两个数,重点在它们不相等。)
同一段历史、同一套规则,为什么?因为回撤这条曲线是采样出来的,而两次采样的取点方式不同。
只看已平仓交易的那条曲线,取点在每一笔交易平仓的那一刻。持仓期间账户浮亏 20% 又拉回来,这条曲线上什么都不会发生——那 20% 从没被「记录」过。按每日余额取点的那条曲线则会老老实实把它画出来。同一段煎熬,一个口径看得见,另一个口径看不见。
它的回撤序列计算是这么搭的(下面是源码里的核心几行):
max_drawdown_df["cumulative"] = profit_results[value_col].cumsum()
max_drawdown_df["high_value"] = np.maximum(0, max_drawdown_df["cumulative"].cummax())
max_drawdown_df["drawdown"] = max_drawdown_df["cumulative"] - max_drawdown_df["high_value"]
cummax 是「到目前为止的最高点」,当前值减去历史最高点,就是此刻在水下多深。整段序列里最深的那个点,就是最大回撤。逻辑简单得几乎没有讨论余地——分歧全部发生在「profit_results 这张表里有哪些行」这个上游问题上。
同一份代码里还并排存着两个回撤列:一个是绝对金额的差,一个是把差除以「起始资金加上峰值」得到的相对比例。金额和比例讲的不是一回事:账户从 10 万跌到 8 万,和从 100 万跌到 98 万,绝对回撤都是 2 万,相对回撤一个是 20% 一个是 2%。卡玛比率的分母取的是相对的那一列,这个选择合理,但它意味着你看到的数值口径已经被框死了。
分子那一头也不见得是「年化收益」
教科书里的卡玛比率是「年化收益 ÷ 最大回撤」。真实系统里往往不是照抄公式。
freqtrade 的做法是:先算总收益占起始资金的比例,除以回测天数得到日均收益,再乘 100;这个日均值当分子,相对回撤当分母,最后套进一个和夏普、索提诺共用的年化辅助函数,乘上一个按天数折算的系数(源码里的默认参数是按 365 天,可配置)。
这么一绕,出来的数和「年化收益 ÷ 最大回撤」在量纲上就不是一回事了。它内部自洽、可用于同一系统内不同参数之间排序,但跨系统比数值毫无意义。这是本篇最实用的一条:看到两份来自不同工具的报告,一份卡玛 3.2 一份卡玛 43,先别惊叹,去查各自是怎么算的。
另一种态度:干脆不给这个数
qlib 是微软开源的一套量化研究框架,它的风险分析函数把年化收益、波动率、信息比率、最大回撤各自算好摆出来,却没有提供卡玛比率。想要你自己除。
这个「不提供」本身是有信息量的,因为同一个函数里,最大回撤的算法随累积方式而变:
if mode == "sum":
max_drawdown = (r.cumsum() - r.cumsum().cummax()).min()
elif mode == "product":
max_drawdown = (cumulative_curve / cumulative_curve.cummax() - 1).min()
上面那行是把每日收益率直接相加(算术累积),回撤是收益率累加值的落差;下面那行是复利连乘,回撤是净值相对峰值的百分比跌幅。两者数值不可比,量纲也不同。它的文档还专门写了一句:年化收益用求和而非连乘是有意为之的设计,为的是不让累积曲线被指数放大扭曲。
所以在这套系统里,你拿两个字段相除得到的「卡玛」,在两种模式下根本不是同一个指标。框架不替你除,某种程度上是把这个坑留在明面上。
把它当优化目标:一个值得警惕的用法
freqtrade 的超参数搜索(自动试很多组参数、挑一组最好的)允许你选卡玛比率当目标函数,实现只有一句话——把算出的卡玛取负号返回,因为搜索器找的是最小值。
看着很自然,风险却不小:你在让机器专门去规避那一个最深的坑。
搜索器不理解「回撤」的含义,它只知道分母越小分数越高。而分母由历史上的两个特定日子决定,于是最省力的提分方式,就是找一组参数恰好在那几天空仓。这组参数在样本内漂亮得不像话,出了样本什么都不是——它学会的不是控制风险,是背下了那一次崩盘发生在哪一周。这正是 过拟合机理 里说的那种「贴着历史噪音塑形」,而用极值当目标函数,会把这个倾向放大到极致。判断一组参数是不是真的稳,要看它周围一片参数是不是也都还行,而不是看它自己那个分数有多高。
卡玛比率高,可能只是因为这段历史里没出过大事。 分母是「已经发生过的最深回撤」,一段没赶上真正深跌的样本,分母天然偏小,比值天然好看。看到一个亮眼的卡玛,第一件要问的不是「这方法多强」,而是「这段区间里有没有经历过一次像样的崩盘」。没有的话,这个数字衡量的是运气的取样范围,不是抗跌能力。
失效边界与常见误用
跨系统比数值。 前面说过了,这是最常见也最没必要的错误。不同工具的分子口径(日均还是年化)、分母口径(绝对还是相对、按成交还是按每日余额)、年化系数各不相同。只在同一份报告内部横向比较,别把两份报告的数字放一起排座次。
样本太短就下结论。 波动率至少还是几百个点求出来的,短样本下虽然不稳但好歹是个统计量;最大回撤在短样本里就是纯粹的抽签结果。没有跨过至少一轮完整涨跌的样本,卡玛比率的参考价值非常有限。
以为它替代了夏普。 两个指标看的是曲线的不同侧面:夏普看整体质地是否顺滑,卡玛看最坏时刻有多坏。一个夏普高卡玛低的组合,多半是平时很稳但踩过一次大雷;一个夏普低卡玛高的组合,可能是波动一直不小但从没深跌过。两个一起看,你能大致读出这条曲线长什么样子——具体怎么读,怎么看一条收益曲线 是正主。
忘了它对时间失明。 同样的深度,三个月回本和三年回本,卡玛给出同一个分数。真要评估「能不能扛住」,回撤深度只是一半,另一半是在水下泡了多久。
把它当成未来的保证。 所有基于历史的比率都有这个通病,卡玛尤甚——因为它的分母是历史极值,而未来的极值只会更极端不会更温和:市场总有办法造出一个比你见过的更深的坑。用历史最大回撤当作「最多会亏这么多」的心理预算,是这个指标最危险的用法。
小结
- 卡玛比率 = 收益 ÷ 最大回撤。它和夏普的根本区别在分母:夏普的分母是平均颠簸,卡玛的分母是历史上最深的那一道沟。后者更贴近「你会不会半路放弃」这个真实体验。
- 代价是分母极不稳定:它只由两个日子决定,样本区间挪一挪就可能翻倍;而且它系统性偏乐观——没经历过的坏日子不进分母。
- 同一条曲线能算出好几个卡玛:只看已平仓交易 vs 按每日余额取点,持仓中的浮亏一个看得见一个看不见;绝对回撤 vs 相对回撤又是另一层分岔。
- 真实系统里的分子常常不是教科书的「年化收益」(freqtrade 用日均收益再套年化系数),所以跨系统比卡玛数值没有意义。qlib 干脆不提供这个比率,因为它的最大回撤定义本身就随累积方式而变。
- 拿它当超参数搜索的目标函数要格外小心:以极值当分母,等于鼓励机器去背下那一次崩盘发生在哪一周。
- 它对时间维度完全失明,深度相同、恢复期天差地别的两段经历,得分一样。
一句话记住这篇:这个数问的不是你赚了多少,是你最难受的那一次有多难受——而它只数得清你已经难受过的那些次。
本文所引源码与文档均来自上述快照版本,是阅读代码得出的机制说明,不是运行结果;具体行为请以你手上那个版本为准。回 量化与 AI 投研概念库 看其它概念各自在说什么;本站内容为投资教育,不构成任何投资建议,边界见 免责声明。
本文为投资教育整理,关键数据与结论请结合下列权威来源验证。