第 6 章 · 03 CDaR 条件回撤


文档摘要

第 6 章 · 03 CDaR 条件回撤 本节摘要:半方差盯单日下行,CVaR 盯单日尾部,但都没考虑「价值持续走弱的时间维度」——投资者对「连跌半年账户腰斩」的痛感远大于「单日暴跌后立刻反弹」。CDaR(Conditional Drawdown at Risk,条件回撤风险)直接对齐「回撤」这一最直观的痛感指标:它衡量「最严重的 (1-β) 比例时段内的平均回撤」。本节讲清 类:基于 Chekhlov-Rockafellar-Uryasev (2005) 的凸化,把回撤序列的尾部期望写成线性规划,引入 α(回撤阈值)、u(累计收益)、z(超出)三组辅助变量求解。读完本节,你能用 CDaR 做优化,并说清它与 CVaR 的关键差异。 内容来源:原项目源码 、文档 ,汉化并套用体系化模板。

第 6 章 · 03 CDaR 条件回撤

本节摘要:半方差盯单日下行,CVaR 盯单日尾部,但都没考虑「价值持续走弱的时间维度」——投资者对「连跌半年账户腰斩」的痛感远大于「单日暴跌后立刻反弹」。CDaR(Conditional Drawdown at Risk,条件回撤风险)直接对齐「回撤」这一最直观的痛感指标:它衡量「最严重的 (1-β) 比例时段内的平均回撤」。本节讲清 EfficientCDaR 类:基于 Chekhlov-Rockafellar-Uryasev (2005) 的凸化,把回撤序列的尾部期望写成线性规划,引入 α(回撤阈值)、u(累计收益)、z(超出)三组辅助变量求解。读完本节,你能用 CDaR 做优化,并说清它与 CVaR 的关键差异。

内容来源:原项目源码 pypfopt/efficient_frontier/efficient_cdar.py、文档 docs/GeneralEfficientFrontier.rst,汉化并套用体系化模板。

学习目标

阅读完本节,你应当能够:

  1. EfficientCDaR 替换方差做条件回撤优化。
  2. 说清 drawdown(回撤) 与单日损失的区别。
  3. 理解 CDaR最大回撤 的关系(β=1 时退化)。
  4. 解释 CDaR 比 CVaR 多了哪个时间维度的考量。
  5. 区分 min_cdar / efficient_risk / efficient_return 三个目标。

一、什么是回撤:从「单日」到「累计」的风险视角

Drawdown(回撤):从历史峰值到当前值的相对跌幅,衡量「账面从最高点滑落了多少」。

D(w, r, t) = max_{τ<t}(wᵀr(τ)) - wᵀr(t) = 历史累计峰值 - 当前累计值

它和单日损失有本质差别:

视角 度量 直觉
单日 收益 rₜ 的损失 「今天跌了 3%」
累计 回撤 D(w,r,t) 「相比历史最高,我账户已腰斩」

💡 核心心法:CVaR 把每个时点当成独立样本,只看「单日最惨」;CDaR 把回撤作为带时间结构的序列,衡量「持续走弱期」。一个资产可能单日 VaR/CVaR 都小,但持续阴跌几个月,回撤巨大——只有 CDaR 能捕捉这种痛感。

二、CDaR 的数学定义

类比 CVaR,CDaR 是回撤序列的尾部期望:

CDaR(w, β) = (1/(1-β)) ∫_{D(w,r,t) ≥ α} D(w,r,t) p(r(t)) dr(t)
  • α 是回撤的 VaR(即「DaR」,Drawdown at Risk)
  • 当 β=1,CDaR 退化为最大回撤(Maximum Drawdown)
  • 当 β=0,CDaR 退化为平均回撤

Chekhlov-Rockafellar-Uryasev (2005) 证明:同 CVaR 一样,可以用凸函数 + 线性规划求解。

三、EfficientCDaR 的构造与三组辅助变量

from pypfopt import expected_returns, EfficientCDaR mu = expected_returns.mean_historical_return(df) returns = expected_returns.returns_from_prices(df) ecd = EfficientCDaR( expected_returns=mu, returns=returns, beta=0.95, weight_bounds=(0, 1), solver=None, verbose=False, solver_options=None, )

源码 __init__ 创建了比 CVaR 多一个变量 z:

self._alpha = cp.Variable() # 回撤阈值 (DaR) self._u = cp.Variable(len(self.returns) + 1) # 累计净值序列(多 1 个初值) self._z = cp.Variable(len(self.returns)) # 回撤超出量

核心约束 _add_cdar_constraints 把回撤的递推关系写出来:

def _add_cdar_constraints(self) -> None: self.add_constraint(lambda _: self._z >= self._u[1:] - self._alpha) # z = max(DaR 超出) self.add_constraint( lambda w: self._u[1:] >= self._u[:-1] - self.returns.values @ w # u = 累计净值递推 ) self.add_constraint(lambda _: self._u[0] == 0) # 初值 self.add_constraint(lambda _: self._z >= 0) self.add_constraint(lambda _: self._u[1:] >= 0)

u 序列递推地模拟「累计净值」:u[t+1] = max(u[t] - rₜ·w, ...),这是「running max」的线性化。然后 z 把所有超过 α 的回撤抓出来,目标函数最小化 α + 平均 z。

四、三个目标方法

方法 含义 数学形式
min_cdar() 最小化 CDaR min α + (1/((1-β)T))·Σz
efficient_risk(target_cdar) 给定 CDaR 上限下最大化收益 max μᵀw, s.t. CDaR ≤ target
efficient_return(target_return) 给定收益下最小化 CDaR min CDaR, s.t. μᵀw ≥ target

父类的不可用方法:

def min_volatility(self): raise NotImplementedError("Please use min_cdar instead.") def max_sharpe(self, risk_free_rate=0.0): raise NotImplementedError("Method not available in EfficientCDaR.") def max_quadratic_utility(self, risk_aversion=1, market_neutral=False): raise NotImplementedError("Method not available in EfficientCDaR.")

portfolio_performance 返回 (期望收益, CDaR):

mu, cdar_val = ecd.portfolio_performance(verbose=True) # Expected annual return: 18.0% # Conditional Drawdown at Risk: 12.34%

五、CDaR 与 CVaR 的关键差异

对比维度 CVaR CDaR
输入 单期收益 累计收益序列
关注 单日尾部损失 累计回撤尾部
β=1 退化 VaR(单日最大损失) 最大回撤
时间维度 无(每个时点独立) 有(依赖历史峰值)
辅助变量 α, u 两组 α, u, z 三组
投资者直觉 风控部门 基金投资人
适合场景 短期、监管 长期、对回撤敏感的资金

💡 β=1 = 最大回撤:如果你想直接最小化最大回撤,把 beta 设为接近 1(但 0 ≤ β < 1 校验不让你设 1,可用 0.99 近似)。这是 CDaR 最直觉的入口。

六、完整示例:最小 CDaR

from pypfopt import expected_returns, EfficientCDaR df = ... mu = expected_returns.mean_historical_return(df) returns = expected_returns.returns_from_prices(df) ecd = EfficientCDaR(mu, returns, beta=0.95) ecd.min_cdar() weights = ecd.clean_weights() print(weights) ecd.portfolio_performance(verbose=True)

⚠️ 样本要求更高:CDaR 要观察「峰值-当前」的累计模式,对样本长度的要求比 CVaR 更严——必须包含至少一个完整的「涨-跌-涨」周期,否则回撤估计完全失真。建议至少 5 年日线数据。

本节要点回顾

  1. 回撤(drawdown) 是「累计峰值减当前值」,衡量时间维度的痛感;CDaR 是回撤序列的尾部期望。
  2. β=1 时 CDaR = 最大回撤,β=0 时 = 平均回撤;这是与 CVaR 最直观的区别。
  3. EfficientCDaR 多了 z 辅助变量(共 α、u、z 三组),通过 u 序列模拟累计净值,递推地构建回撤。
  4. 方法:min_cdarefficient_risk(target_cdar)efficient_return(target_return);输出 (收益, CDaR)
  5. CDaR vs CVaR:CVaR 看单期、无时序;CDaR 看累计、有时序,捕捉「连跌」的痛感。
  6. 样本要长:至少包含一个完整牛熊周期,5 年以上日线才靠谱。

至此第 6 章三种通用风险度量讲完。下一章我们转到「收益端」——Black-Litterman 模型,从市场市值反推「市场隐含收益」作为更稳健的先验。


发布者: 作者: 灏天文库 转发
评论区 (0)
U