先说结论:方差惩罚所有偏离,最大回撤只看一个最坏点,两者都不是投资人真正在乎的东西。Chekhlov-Uryasev-Zabarankin(2005)的 CDaR(Conditional Drawdown-at-Risk)取中间路线:对回撤序列做 CVaR——CDaR₉₅ 就是”最差 5% 回撤日的平均深度”。它继承了 CVaR 的全部工程优点:凸、可以写成线性规划、优化时不用碰任何分布假设。我用三资产(股票/债券/趋势)两状态模拟实测:同一目标收益下,最小方差组合和最小 CDaR 组合的权重分道扬镳——趋势资产样本内年化 -1.6%,最小方差只给它 11%,最小 CDaR 给到 21%,几乎翻倍——因为它危机期年化收益 +75%,是全组合唯一的回撤对冲;代价是波动率反而更高(4.5% vs 4.1%)。CDaR 优化用更高的方差买更浅的回撤,这笔交易方差目标永远不会做。
这篇接在回撤主题的分数 Kelly 之后:那篇管”单资产给多少杠杆才不会疼死”,这篇管”多资产怎么配权重让回撤尾部最浅”。
四把尺子量同一条回撤#
先把度量对象定义清楚。给定组合的累计收益路径 ,回撤序列是:
对这条序列,常见的四把尺子:
- 平均回撤 AvDD:。太温和——大量接近零的日子把灾难稀释了。
- 回撤在险值 DaRα:回撤序列的 α 分位数。和 VaR 一样的毛病:只看门槛,不管门槛后面有多深。
- 条件回撤在险值 CDaRα:超过 DaR 门槛的那些回撤的平均值,即”最差 比例回撤日的平均深度”。
- 最大回撤 MaxDD:。只由一个点决定,样本噪声极大——换一个种子它就换一个数。
在等权组合的 5 年样本内路径上,四把尺子给出四个数:AvDD = 1.8%、DaR₉₅ = 8.0%、CDaR₉₅ = 9.3%、MaxDD = 12.1%:

CDaR 的两个极限值得记住: 时 CDaR 退化为平均回撤, 时收敛到最大回撤。它是一个用 α 旋钮在”太温和”与”太噪声”之间连续插值的家族。α=0.95 是实务上最常用的档位:既让尾部主导目标函数,又平均了约 5% 的样本点、不至于被单个极值绑架。
为什么不直接优化 MaxDD?两个理由。统计上,MaxDD 是单点统计量,样本内优化它等于对一个噪声极大的数字过拟合——PBO 那篇的逻辑在这里完全适用。计算上,MaxDD 也能写成 LP,但目标函数只有一个有效约束点,解对数据扰动极不稳定。CDaR 对最差 5% 的日子取平均,等于给尾部目标加了天然的正则化。
关键一步:CDaR 是回撤的 CVaR,所以 LP 白拿#
Rockafellar-Uryasev 证明了 CVaR 优化可以线性化。CDaR 是同一批人把同一个技巧移植到回撤上——把”损失分布”替换成”回撤分布”,整套机器原封不动搬过来:
回撤 本身涉及 running max,处理方法是引入辅助变量 表示历史峰值,用两条线性不等式把它压出来。完整的 LP:
其中 是非复利累计收益(这是让问题保持线性的关键技巧,后面局限里会回来说它)。 在最优解处自动等于 running max——因为压低 总能让目标变小,两条下界约束恰好把它钉在 上。
import numpy as np
from scipy.optimize import linprog
from scipy.sparse import lil_matrix, csr_matrix
def min_cdar_portfolio(R, alpha=0.95, target_ann=None):
"""R: (T, n) 日收益矩阵。变量排布 [x(n), u(T), zeta, z(T)]"""
T, n = R.shape
C = np.cumsum(R, axis=0) # C[t] @ x = W_t
nv = n + T + 1 + T
iu, iz0, izz = n, n + T, n + T + 1
cost = np.zeros(nv)
cost[iz0] = 1.0
cost[izz:] = 1.0 / ((1 - alpha) * T)
A = lil_matrix((3*T + (1 if target_ann else 0), nv))
b = np.zeros(A.shape[0]); r = 0
for t in range(T):
A[r, iu+t] = -1.0 # u_t >= u_{t-1}
if t > 0: A[r, iu+t-1] = 1.0
r += 1
A[r, :n] = C[t]; A[r, iu+t] = -1.0 # u_t >= W_t
r += 1
A[r, :n] = -C[t]; A[r, iu+t] = 1.0 # z_t >= u_t - W_t - zeta
A[r, iz0] = -1.0; A[r, izz+t] = -1.0
r += 1
if target_ann is not None: # 目标收益约束
A[r, :n] = -R.mean(axis=0) * 252
b[r] = -target_ann
Aeq = np.zeros((1, nv)); Aeq[0, :n] = 1.0
bounds = [(0, None)]*n + [(None, None)]*T + [(None, None)] + [(0, None)]*T
res = linprog(cost, A_ub=csr_matrix(A), b_ub=b,
A_eq=Aeq, b_eq=[1.0], bounds=bounds, method="highs")
return res.x[:n], res.funpython1250 个交易日 × 3 资产的问题约 5000 个变量、3750 条约束,HiGHS 求解不到一秒。凸性是白拿的——不管收益是什么分布,全局最优保证找到。这是 CDaR 相对”直接优化经验 MaxDD”或任何非凸回撤指标的决定性工程优势。
实验:危机 alpha 资产的重新定价#
三资产、两状态马尔可夫模拟(平静期约 93% 的日子,危机期约 7%):
| 资产 | 平静期年化 | 危机期年化 | 全样本年化 | 全样本波动 |
|---|---|---|---|---|
| 股票 | +18% | -88% | +23.5%* | 17.5% |
| 债券 | +2.5% | +5% | +6.3% | 4.7% |
| 趋势 | +3% | +75% | -1.6% | 11.8% |
*样本内实现值,该种子下危机日恰好较少。趋势资产是刻意设计的”危机 alpha”:平时几乎不赚钱(模拟里全样本甚至亏钱),只在股票崩盘时大赚——现实原型是长波动策略、尾部对冲基金、部分 CTA。
同一目标收益(年化 7%)下解两个优化:

**趋势资产的配置:最小方差 11% → 最小 CDaR 21%,几乎翻倍。**这是本文最核心的一个数字。方差目标看到的趋势资产:年化 -1.6%、波动 11.8%、和股票相关性平时还是正的——一个纯粹的拖油瓶,11% 的配置只是因为它和债券的低相关勉强有点分散化价值。CDaR 目标看到的是另一个东西:每次回撤加深的日子,恰好是它大涨的日子。它不是分散化工具,是回撤保险。
样本内的账目印证了这一点:最小 CDaR 组合的波动率更高(4.5% vs 4.1%),但 CDaR₉₅ 更低(4.0% vs 4.9%)、MaxDD 更低(5.2% vs 5.9%)。它用 0.4 个百分点的波动率买了 0.9 个百分点的尾部回撤——方差目标里这笔交易根本不成立,因为方差对”上涨的波动”和”下跌的波动”一视同仁,而危机 alpha 资产的波动几乎全是上涨波动。
两条前沿不重合#
把两族最优组合都画到收益-CDaR 平面上:

CDaR 前沿(直接优化 CDaR)处处不差于均值-方差前沿映射过来的曲线——这是定义使然,样本内直接优化谁谁赢。有信息量的是差距的形状:低收益端两条线几乎重合(都重仓债券,怎么优化都一样),目标收益越高差距越大——因为高收益逼着组合持有股票,这时”用什么给股票配对冲”的分歧才显现:方差目标选低波动资产,CDaR 目标选负共回撤资产。
教训:如果你的组合里没有危机 alpha 类资产,CDaR 优化和方差优化差别不大。CDaR 的价值恰恰在于它能给”平时难看、危机救命”的资产正确定价——这类资产在方差框架里永远被低估。
样本外:诚实的检验#
样本外 3 年(危机日占比 9.1%,比样本内的 6.7% 更险恶):

最小 CDaR 组合样本外年化 7.5% vs 最小方差的 6.9%,MaxDD 3.3% vs 3.7%,CDaR₉₅ 基本打平(2.8% vs 2.9%)。方向对,但幅度远小于样本内的差距——这是预期之内的:样本内的 CDaR 优势有一部分是过拟合(优化器精确地记住了样本内每一段回撤的形状),样本外只剩下结构性的部分(危机 alpha 的对冲价值是真的,因为数据生成过程里危机 regime 真实存在)。
如果数据生成过程里没有稳定的危机结构——比如趋势资产的危机收益纯属样本内巧合——CDaR 优化的样本外表现会劣化得比方差优化更快,因为它对尾部样本更敏感、有效样本量更小。CDaR 优化值不值得用,取决于你信不信组合里存在结构性的负共回撤资产,这是一个经济判断,不是统计判断。
工程清单#
- α 别贪高。CDaR₉₉ 在 1250 天样本里只由约 13 个最差回撤日决定,噪声接近 MaxDD。α=0.90~0.95 是样本量和尾部聚焦的平衡点。
- 回撤观测不独立,惩罚是隐性的。一段深回撤会贡献几十个连续的高 ,在目标函数里天然占更大权重——持续时间长的回撤被罚得更重。这是特性不是 bug(投资人对”三年不创新高”的痛感确实高于”急跌急回”),但要知道你在优化的是深度×时间的混合物。
- LP 口径是非复利累计。 保持线性,但和复利净值的回撤有偏差——回撤越深偏差越大(非复利口径会高估深回撤)。求解后要用复利口径重算真实回撤报数,两个口径的数字不要混在一张表里。
- 危机期定义要用样本外的逻辑检验。CDaR 给趋势资产加仓的理由是”它在回撤日涨”。上线前问一句:这个负共回撤是机制性的(长波动头寸、做空 beta)还是统计巧合?机制性的才敢给权重。
局限#
第一,非复利口径的近似在杠杆组合或长回测里恶化明显:非复利累计 -30% 对应复利约 -26%,优化器会把火力错配到”非复利口径最深、复利口径未必”的时段。严格处理要用对数收益近似或迭代校正,代价是丢掉部分线性结构。
第二,CDaR 是样本路径的函数而不仅是收益分布的函数——同一组日收益换个顺序,回撤完全不同。这让它比 CVaR 更依赖”历史路径会重演”的假设,重抽样(block bootstrap 保留自相关)做置信区间比 CVaR 更必要。
第三,本文没建模调仓成本和权重稳定性。CDaR 前沿上相邻目标收益的最优权重跳动比方差前沿更大(尾部目标的解本来就更敏感),实盘要加换手惩罚或权重区间约束。
第四,收益率约束用的是样本均值——所有组合优化的通病(垃圾进垃圾出),CDaR 不解决期望收益的估计问题,它只解决”给定观点后风险怎么度量”的问题。
一句话收尾:方差问”这个资产抖不抖”,CDaR 问”我最疼的那些日子它站在哪边”。第二个问题才是配置真正该回答的。