2、极端风险度量:VaR的局限性与缺陷、CVaR(条件风险价值)的计算、压力测试场景设计、最大回撤与Calmar比率

2.1 VaR的局限性与缺陷:为什么它靠不住?

说到风险度量,很多人第一反应就是VaR(Value at Risk)。我刚开始做量化那会儿,也把VaR当宝贝。直到2015年股灾,我亲眼看着一个用VaR做风控的基金,一天之内亏掉了过去半年的利润。

VaR到底在算什么?说白了就是:在95%或99%的置信水平下,你的最大可能亏损是多少。比如日VaR(95%)=100万,意思是有95%的概率,你一天最多亏100万。

但问题来了——剩下的5%呢?VaR完全不告诉你。这就像天气预报说“明天有95%的概率不下雨”,结果那5%的概率来了场洪水。你想想看,这能叫风险度量吗?

VaR的三大硬伤:

  • 尾部风险失明:只关心分位数,不关心分位数以外的损失有多大。两个组合的VaR可能一样,但一个极端亏损是200万,另一个是2000万。
  • 不满足次可加性:理论上,分散化应该降低风险。但VaR不保证这一点。我见过一个案例,把两个资产分开算VaR是100万,合在一起算反而变成120万——这明显不合理。
  • 对分布假设敏感:用正态分布算VaR,和用t分布算,结果能差好几倍。现实中金融数据哪有那么乖?

我的经验:VaR可以作为参考,但千万别把它当风控的唯一标准。我曾经在回测中加了一个条件:如果VaR超过某个阈值就减仓,结果遇到极端行情时,VaR还没触发,仓位已经亏没了。

2.2 CVaR(条件风险价值):把尾部风险算清楚

CVaR,也叫Expected Shortfall(ES),它解决了VaR的核心问题。CVaR问的是:当亏损超过VaR阈值时,平均会亏多少?

举个例子:假设你有100个交易日的收益数据,VaR(95%)排在第5差的亏损。CVaR(95%)就是取最差的5个亏损,算它们的平均值。这样,尾部风险就被量化了。

# 计算CVaR的简单实现
import numpy as np

def calculate_cvar(returns, confidence_level=0.95):
    """
    计算CVaR(条件风险价值)
    returns: 收益率序列
    confidence_level: 置信水平,默认95%
    """
    # 排序收益率
    sorted_returns = np.sort(returns)
    
    # 找到VaR的分位点
    var_index = int(len(sorted_returns) * (1 - confidence_level))
    var = -sorted_returns[var_index]
    
    # CVaR是尾部损失的均值
    tail_losses = -sorted_returns[:var_index]
    cvar = np.mean(tail_losses)
    
    return var, cvar

# 模拟数据
np.random.seed(42)
returns = np.random.normal(0.001, 0.02, 1000)

var_95, cvar_95 = calculate_cvar(returns, 0.95)
print(f"VaR(95%): {var_95:.4f}")
print(f"CVaR(95%): {cvar_95:.4f}")

你看,CVaR天然满足次可加性。分散化投资,CVaR一定会降低。这在数学上保证了“不要把鸡蛋放在一个篮子里”这个朴素道理。

注意:CVaR也不是万能的。它对数据质量要求更高,如果样本量不够,尾部估计会很不稳定。我建议至少用500个以上的数据点来计算CVaR。

2.3 压力测试场景设计:模拟最坏的情况

CVaR和VaR都是基于历史数据的统计方法。但黑天鹅事件之所以叫黑天鹅,就是因为历史数据里没有。这时候,压力测试就派上用场了。

压力测试的核心思路是:假设一些极端但可能发生的情景,看看你的组合会怎样。我个人习惯把压力测试分为三类:

类型 描述 例子
历史重现 复制过去发生过的极端事件 2008年金融危机、2020年疫情
假设情景 基于逻辑推演的极端情况 利率突然上升500bp、原油暴跌50%
因子冲击 对关键风险因子施加极端变动 波动率飙升、相关性突变

我曾经在2018年设计过一个压力测试:假设中美贸易摩擦全面升级,A股单日暴跌8%。当时很多人觉得这不可能。结果2019年5月6日,上证指数真的跌了5.58%。虽然没到8%,但那个压力测试帮我们提前减了仓。

设计压力测试的几个要点:

  • 相关性会失效:正常行情下不相关的资产,危机时可能一起跌。2008年就是典型,几乎所有资产都在跌,除了现金。
  • 流动性会枯竭:压力测试里一定要考虑“卖不出去”的情况。我见过一个组合,理论上能扛住20%的下跌,但实际因为流动性问题,只跌了5%就爆仓了。
  • 反馈效应:你的减仓行为本身会加剧市场下跌。这个在压力测试里很难量化,但必须意识到。

2.4 最大回撤与Calmar比率:衡量你的“抗揍能力”

最大回撤(Maximum Drawdown, MDD)是我最看重的风险指标之一。它衡量的是:从历史最高点跌到最低点,你最多亏了多少。

举个例子:你的账户净值从100万涨到200万,然后跌到120万,再涨到150万。最大回撤就是(200-120)/200=40%。注意,不是从100万算起,而是从最高点算起。

# 计算最大回撤
def max_drawdown(equity_curve):
    """
    计算最大回撤
    equity_curve: 净值序列
    """
    # 计算历史最高点
    running_max = np.maximum.accumulate(equity_curve)
    # 计算回撤
    drawdown = (equity_curve - running_max) / running_max
    # 最大回撤
    mdd = np.min(drawdown)
    
    return mdd

# 模拟净值曲线
np.random.seed(42)
returns = np.random.normal(0.001, 0.02, 500)
equity = 100 * np.cumprod(1 + returns)

mdd = max_drawdown(equity)
print(f"最大回撤: {mdd*100:.2f}%")

Calmar比率就是把最大回撤和收益结合起来:

Calmar比率 = 年化收益率 / 最大回撤(绝对值)

这个比率越高越好。比如年化收益20%,最大回撤10%,Calmar就是2。我个人觉得,Calmar比率大于2的量化策略,才算得上“稳健”。

避坑指南:我曾经犯过一个错误——只看最大回撤的数值,没看回撤持续的时间。一个策略最大回撤20%,但3个月就回来了,和另一个同样回撤20%但3年才回来的,风险完全不一样。所以我现在还会看“回撤恢复期”这个指标。

2.5 知识体系总览

下面这张图把本章的核心逻辑串起来了。你可以看到,从VaR到CVaR,再到压力测试和最大回撤,其实是一条从“统计风险”到“极端风险”的递进路径。

极端风险度量知识体系 极端风险度量 VaR(风险价值) CVaR(条件风险价值) 压力测试 最大回撤 & Calmar 局限:尾部失明、不满足次可加性 优势:考虑尾部均值、满足次可加性 类型:历史重现、假设情景、因子冲击 Calmar = 年化收益 / 最大回撤

嗯,这张图把四个核心概念串起来了。你可以看到,VaR是基础,但不够用;CVaR补上了尾部风险;压力测试应对未知的黑天鹅;最大回撤和Calmar则是从实战角度衡量你的“抗揍能力”。

我个人建议,在实际的风控体系中,这四个指标要一起用。别指望单一指标能解决所有问题。就像开车,你不能只看速度表,还得看油表、水温表,对吧?


专注资料整理