跳到正文

回测 VaR 和 ES:Kupiec、Christoffersen 与红绿灯

每个 VaR 回测检验都在把命中序列压缩成一个数字,压缩掉的信息决定了它抓不到什么。从 Kupiec 到 Christoffersen 到 DQ 逐级找回信息,再看 ES 为什么至今没有公认的检验。

第 2 篇 · 共 12 篇 约 11 分钟

风险模型是你基于今天讲给明天的故事。跟任何故事一样,它可能错。知道 VaR/ES 模型是否校准到真实的唯一方法,是等明天来了,看损失有没有超过模型的预测。

回测就是做这个核对的正式统计机器。给定 VaR 预测序列 VtV_t(t=1,…,Tt = 1, \ldots, T)和已实现损失 LtL_t,数一下 Lt>VtL_t > V_t 出现了多少次。模型说 99% VaR,突破率就应该在 1% 附近。一直 3%,模型在低估风险;一直 0.3%,你在过度占用资本(或者只是运气好)。

但”数突破”只是起点。这篇文章的主线是一个信息问题:命中序列 (I1,…,IT)(I_1, \ldots, I_T) 里装着模型失校的全部证据,而每个检验都要把它压缩成一个统计量——压缩时丢掉的信息,就是这个检验抓不到的失效模式。Kupiec 检验只留总数,丢掉了时间;Christoffersen 找回相邻转移,抓住聚集;DQ 检验把整个条件信息集都拉进来。ES 的困难则更根本:它连”命中”这个二元事件都没有,可压缩的原材料本身就难定义。我们按这个顺序走一遍,最后看监管实际在用什么。

回测的记号

设 LtL_t 是 tt 时刻持有期内的已实现损失,Vt=VaR^α(Lt)V_t = \widehat{\text{VaR}}^\alpha(L_t) 是模型在持有期开始时(只用 t−1t-1 及之前的信息)做出的 VaR 预测。定义命中序列:

It=1{Lt>Vt}I_t = \mathbb{1}\{L_t > V_t\}

命中(It=1I_t = 1)意味着已实现损失超过了预测 VaR。在”模型正确校准”的原假设下,

P(It=1)=1−α\mathbb{P}(I_t = 1) = 1 - \alpha

α=0.99\alpha = 0.99 时突破概率是 1%。注意原假设其实是两条:突破概率对(无条件覆盖率),以及 ItI_t 之间相互独立(今天突破不预示明天更容易突破)。一个校准的模型应该产出一串 iid 的 Bernoulli(1−α)(1-\alpha)。检验要做的就是拿观测到的命中序列去反驳这两条中的某一条或全部。

Kupiec 失败比例(POF)检验:只看总数

最简单的压缩方式是把整个序列压成一个数:命中总数 T1=∑tItT_1 = \sum_t I_t。在原假设下 T1∼Binomial(T,1−α)T_1 \sim \text{Binomial}(T, 1-\alpha),对数似然比检验(Kupiec, 1995,也叫无条件覆盖率检验)是

LRPOF=−2log⁡(1−α)T1 αT−T1p^ T1(1−p^)T−T1\text{LR}_{\text{POF}} = -2 \log \frac{(1 - \alpha)^{T_1}\, \alpha^{T - T_1}}{\hat p^{\,T_1} (1 - \hat p)^{T - T_1}}

其中 p^=T1/T\hat p = T_1 / T 是经验突破率——分子是”突破概率恰为 1−α1-\alpha“下的似然,分母是让数据自己说话的似然。原假设下 LRPOF∼χ12\text{LR}_{\text{POF}} \sim \chi^2_1。展开写就是:

LR=2[T1log⁡(T1T(1−α))+(T−T1)log⁡(T−T1Tα)]LR = 2 \left[ T_1 \log\left(\frac{T_1}{T(1-\alpha)}\right) + (T - T_1) \log\left(\frac{T - T_1}{T\alpha}\right) \right]

χ12\chi^2_1 的 95% 临界值是 3.84,LR>3.84LR > 3.84 就在 5% 显著性水平拒绝。

拿数字试一下。α=0.99\alpha = 0.99、T=250T = 250 天、T1=5T_1 = 5 次命中:经验突破率 5/250=2%5/250 = 2\%,是期望值 1% 的两倍。检验统计量是

LR=2[5log⁡(52.5)+245log⁡(245247.5)]≈2[5⋅0.693+245⋅(−0.0102)]≈2[3.47−2.49]=1.96LR = 2 \left[ 5 \log\left(\frac{5}{2.5}\right) + 245 \log\left(\frac{245}{247.5}\right) \right] \approx 2 [5 \cdot 0.693 + 245 \cdot (-0.0102)] \approx 2[3.47 - 2.49] = 1.96

低于 3.84,不拒绝——突破率翻倍,检验都看不出来。换 T1=10T_1 = 10(4% 突破率):

LR=2[10log⁡(10/2.5)+240log⁡(240/247.5)]=2[10⋅1.386+240⋅(−0.0304)]≈2[13.86−7.30]=13.12LR = 2 \left[ 10 \log(10/2.5) + 240 \log(240/247.5) \right] = 2 [10 \cdot 1.386 + 240 \cdot (-0.0304)] \approx 2[13.86 - 7.30] = 13.12

远超 3.84,强拒绝。

这两个算例已经暴露了 Kupiec 检验的性格:对 T=250T = 250、α=0.99\alpha = 0.99,期望命中只有 2.5 次,样本里根本没有多少信息可用,对小偏离的功效非常低——真实突破率是期望两倍时,拒绝率也只有 30% 左右。这一定程度上是有意的:一年 250 天的窗口本来就短,检验太激进会制造大量监管噪声。但代价明摆着——模型可以严重失校而不触发警报。

Basel 红绿灯:把检验换成查表

监管没有直接采用 Kupiec 检验,而是在 1996 年的 Amendment to the Capital Accord 配套框架里给了一张更钝的表:

颜色等级250 天命中数解读
绿10–4模型通过。
黄25–9中间区;追加审查,资本乘数逐级上调。
红310+模型失败。必须改进,资本乘数顶格。

红绿灯看起来像检验,但它在正式统计意义上不是——它是监管的经验法则,好处是零歧义、可跨行比较。跟 Kupiec 摆在一起看很有意思:期望命中 2.5 次,黄区从 5 次开始,而 Kupiec 在 5% 水平上 5、6 次都不拒绝,7 次起才拒绝。也就是说黄区下沿比统计检验更严、上沿又给了模型申辩空间;红区(10+)则在两套标准下都毫无悬念。踩进黄区和红区不是白踩的:市场风险资本乘数的基准是 3,黄区按命中数逐级加 0.4 到 0.85,红区加满 1,把乘数顶到 4。持续待在红区(半年以上)通常直接触发监管指令要求改模型。

FRTB 上线后这套机制没有被废掉——例外计数的红绿灯保留了下来(而且对 99% 和 97.5% 两个水平的 VaR 分别计数),另加了 P&L attribution 检验来核对前台与风险模型的一致性。注意被回测的始终是 VaR 例外,不是 ES 本身——这个伏笔后面会收。

Christoffersen 独立性检验:找回时间

Kupiec 把序列压成总数时,丢掉了命中何时发生。一个模型 200 天 0 次命中、然后 50 天内命中 5 次,总数还是 5——大概率绿区,Kupiec 完全无感。但聚集恰恰是最该被检测的失效模式:在特定 regime 里系统性失效的模型,比 iid 地偶尔漏一次的模型危险得多,因为它挂掉的那些天挤在一起,正是你最需要模型的日子。

Christoffersen (1998) 的独立性检验找回了被丢掉的时间信息中最便宜的一部分:相邻两天的转移。比较两个模型的似然——独立模型只用一个参数 π\pi(命中概率处处相同),一阶 Markov 模型用两个参数 π0,π1\pi_0, \pi_1(昨天没命中/命中之后,今天的命中概率):

LRIND=−2log⁡L0L1=−2[log⁡L0−log⁡L1]LR_{\text{IND}} = -2 \log \frac{L_0}{L_1} = -2 \left[\log L_0 - \log L_1\right]

展开是

LRIND=−2log⁡πT01+T11(1−π)T00+T10π0T01(1−π0)T00⋅π1T11(1−π1)T10LR_{\text{IND}} = -2 \log \frac{\pi^{T_{01} + T_{11}} (1-\pi)^{T_{00} + T_{10}}}{\pi_0^{T_{01}} (1-\pi_0)^{T_{00}} \cdot \pi_1^{T_{11}} (1-\pi_1)^{T_{10}}}

其中 TijT_{ij} 是命中序列里 It−1=iI_{t-1} = i 且 It=jI_t = j 的转移次数,π=(T01+T11)/(T00+T01+T10+T11)\pi = (T_{01} + T_{11}) / (T_{00} + T_{01} + T_{10} + T_{11}) 是总经验命中率,πi=Ti1/(Ti0+Ti1)\pi_i = T_{i1} / (T_{i0} + T_{i1}) 是给定昨天状态 ii 时今天命中的经验概率。独立时 π0=π1=π\pi_0 = \pi_1 = \pi,两个似然重合、统计量为 0;命中聚集时 π1≫π0\pi_1 \gg \pi_0,统计量被拉大。渐近分布是 χ12\chi^2_1。

把上面那个 Kupiec 抓不到的场景真的算一遍。250 天,命中落在第 {201,202,203,209,215}\{201, 202, 203, 209, 215\} 天——5 次命中全挤在最后 50 天。数转移(共 249 个):T01=3T_{01} = 3(第 201、209、215 天,前一天都没命中)、T11=2T_{11} = 2(第 202、203 天)、T10=3T_{10} = 3(第 204、210、216 天)、T00=241T_{00} = 241。于是 π=5/249≈0.0201\pi = 5/249 \approx 0.0201,π0=3/244≈0.0123\pi_0 = 3/244 \approx 0.0123,π1=2/5=0.4\pi_1 = 2/5 = 0.4——昨天命中之后,今天命中的经验概率是平时的三十多倍。代入:

LRIND=−2[(5log⁡0.0201+244log⁡0.9799)−(3log⁡0.0123+241log⁡0.9877+2log⁡0.4+3log⁡0.6)]≈9.89LR_{\text{IND}} = -2\left[\big(5 \log 0.0201 + 244 \log 0.9799\big) - \big(3 \log 0.0123 + 241 \log 0.9877 + 2 \log 0.4 + 3 \log 0.6\big)\right] \approx 9.89

9.89 远超 3.84:独立性被强烈拒绝。而同一份数据的 Kupiec 统计量还是 1.96——安然通过。这就是”压缩掉时间”的代价的具体样子。

Christoffersen 还建议把两个检验合并,同时考核覆盖率和独立性:

LRCC=LRPOF+LRINDLR_{\text{CC}} = LR_{\text{POF}} + LR_{\text{IND}}

原假设下是 χ22\chi^2_2(5% 临界值 5.99)。上面的例子里 LRCC=1.96+9.89=11.85LR_{\text{CC}} = 1.96 + 9.89 = 11.85,组合检验同样拒绝。顺带一提,Christoffersen & Pelletier (2004) 后来提出了基于命中间隔时长分布的 duration 检验,思路一样——独立时间隔应该是无记忆的——功效在某些备择下更好。

DQ 检验:找回整个信息集

相邻转移仍然只是时间信息的一小部分。命中可能不依赖昨天的命中,却依赖昨天的 VaR 水平、波动率或任何 t−1t-1 时刻可见的变量——只要能用已知信息预测今天是否突破,模型就没有把信息用干净。Engle & Manganelli (2004) 的 Dynamic Quantile(DQ)检验把这件事做成一个回归:把中心化的命中指示对它的滞后与其他预测变量回归,

Hitt−(1−α)=β0+β1 Hitt−1+β2 VaRt+ϵt\text{Hit}_t - (1 - \alpha) = \beta_0 + \beta_1\, \text{Hit}_{t-1} + \beta_2\, \text{VaR}_t + \epsilon_t

其中 Hitt=1{Lt>VaR^t}\text{Hit}_t = \mathbb{1}\{L_t > \widehat{\text{VaR}}_t\}。模型校准时,左边这个变量对任何 t−1t-1 时刻已知的回归量都应该零相关,所以联合检验全部系数为零:

DQ=β^⊤X⊤X β^α(1−α)DQ = \frac{\hat{\boldsymbol\beta}^\top \mathbf{X}^\top \mathbf{X}\, \hat{\boldsymbol\beta}}{\alpha(1-\alpha)}

X\mathbf{X} 是 T×pT \times p 的回归量矩阵(这里 p=3p = 3:截距、滞后命中、VaR 水平),β^\hat{\boldsymbol\beta} 是 OLS 估计,原假设下渐近 χp2\chi^2_p。回归量可以按需要扩充,这正是 DQ 的优势:想检验哪种可预测性,就把对应变量放进去。对依赖性和设定错误,它的功效普遍高于 Kupiec 和 Christoffersen。

回测 Expected Shortfall:连”命中”都没有了

到这里为止,所有检验都建立在同一块地基上:存在一个干净的二元事件——损失超没超过 VaR——把它的序列拿来压缩、检验。ES 把这块地基抽掉了。ES 是一个量(最差 1−α1-\alpha 部分的平均损失),不是一个门槛;要检验的是条件期望对不对,而条件事件本身又依赖于 VaR 预测——被检对象和检验条件纠缠在一起。这就是 ES 回测比 VaR 难的结构性原因,也是它至今没有公认监管检验的原因。现有的方法大致三路。

第一路来自 McNeil & Frey (2000):只看突破日,检查超额损失的均值。在 Lt>V^tL_t > \hat{V}_t 的日子里定义超额残差

Zt=Lt−ES^tZ_t = L_t - \widehat{\text{ES}}_t

模型校准时 E[Zt∣Lt>V^t]=0\mathbb{E}[Z_t \mid L_t > \hat{V}_t] = 0——突破日的平均损失就该等于预测的 ES。检验本质上是把 ZtZ_t 限制在命中日上做 tt 检验:

tES=Zˉ(1)S(1)/N(1)t_{\text{ES}} = \frac{\bar Z_{(1)}}{S_{(1)} / \sqrt{N_{(1)}}}

其中 Zˉ(1)\bar Z_{(1)}、S(1)S_{(1)}、N(1)N_{(1)} 是命中日子集上的均值、标准差和个数(原文用 bootstrap 定 p 值,因为尾部残差非正态)。这个方法在工业界用得最广,弱点也明显:N(1)N_{(1)} 就是命中数,250 天大约 2.5 个,检验建立在个位数的观测上。

第二路是 Du & Escanciano (2017),思路是绕开”只有突破日才有信息”的困境:用概率积分变换 ut=Ft(Lt)u_t = F_t(L_t) 把每天的损失都变成 [0,1][0,1] 上的均匀变量,再定义累积违约

Ht=(ut−α)+1−αH_t = \frac{(u_t - \alpha)^+}{1 - \alpha}

它可以理解为”把 (α,1](\alpha, 1] 上的所有 VaR 水平的命中指示积分起来”——不突破的日子贡献 0,突破得越深贡献越接近 1。模型校准时 HtH_t iid 且 E[Ht]=(1−α)/2\mathbb{E}[H_t] = (1-\alpha)/2,于是无条件检验就是对 HtH_t 的均值做 tt 检验,条件检验查它的自相关。相比只数突破,HtH_t 保留了突破深度的信息——正是 ES 关心的那部分。

第三路是 Acerbi & Szekely (2014) 的直接检验。他们的第二个统计量在损失记号下是

Z2=1T(1−α)∑t=1TLt ItES^t−1Z_2 = \frac{1}{T(1-\alpha)} \sum_{t=1}^T \frac{L_t\, I_t}{\widehat{\text{ES}}_t} - 1

模型校准时 E[Z2]=0\mathbb{E}[Z_2] = 0;Z2>0Z_2 > 0 说明实际尾部损失超过 ES 预测(ES 报低了),Z2<0Z_2 < 0 说明 ES 报高了。临界值靠模型分布做模拟得到——这是它的实用代价,也是它的坦诚之处:检验的功效依赖你敢不敢用自己的模型生成零分布。

监管现状把前面的伏笔收上:FRTB 资本用 ES 计算,回测却仍然对 VaR 例外计数。没有哪一路 ES 检验被立成标准,多数银行的做法是内部并行跑多个 ES 回测、看方向是否一致。

亲手跑一遍

import numpy as np
from scipy import stats

# 简化版 VaR 回测
np.random.seed(3)
T = 250
alpha = 0.99

# 真实模型正确校准
losses = -np.random.normal(0.001, 0.015, T)
var_pred = 2.326 * 0.015 - 0.001     # 假设模型正确时的 99% VaR
hits = (losses > var_pred).astype(int)

# Kupiec POF
T1 = hits.sum()
LR_pof = 2 * (T1 * np.log(T1 / (T * (1-alpha))) +
              (T - T1) * np.log((T - T1) / (T * alpha)))
print(f"Kupiec LR: {LR_pof:.3f}  chi2_1, 0.95 = 3.84")

# Christoffersen 独立性:数转移
T00 = ((hits[:-1] == 0) & (hits[1:] == 0)).sum()
T01 = ((hits[:-1] == 0) & (hits[1:] == 1)).sum()
T10 = ((hits[:-1] == 1) & (hits[1:] == 0)).sum()
T11 = ((hits[:-1] == 1) & (hits[1:] == 1)).sum()
pi0 = T01 / (T00 + T01 + 1e-12) if (T00 + T01) > 0 else 0
pi1 = T11 / (T11 + T10 + 1e-12) if (T11 + T10) > 0 else 0
pi  = (T1 - hits[0]) / (T - 1)   # leave-one-out 风格

LR_ind = 0
if (T00 + T01) > 0 and (T11 + T10) > 0 and pi not in (0, 1) and pi0 not in (0, 1) and pi1 not in (0, 1):
    LR_ind = -2 * (np.log((1 - pi)**(T00+T10) * pi**(T01+T11)) -
                   np.log((1-pi0)**T00 * pi0**T01 * (1-pi1)**T10 * pi1**T11))
print(f"Christoffersen LR_ind: {LR_ind:.3f}")
print(f"Christoffersen LR_cc = LR_pof + LR_ind: {LR_pof + LR_ind:.3f}")

# 红绿灯
print(f"Total hits: {T1}  ({T1/T*100:.2f}%)  zone: " + 
      ("green" if T1 <= 4 else "yellow" if T1 <= 9 else "red"))

换几个种子跑,你会看到统计量的波动有多大——这是 2.5 次期望命中的样本量在说话。正确校准的模型下,LRPOF\text{LR}_{\text{POF}} 大约 95% 的时间低于 3.84,红灯只在严重失校时亮。

反过来说,波动大意味着假阳性不可避免。回测是二元拒绝:模型明明正确,5% 显著性水平也意味着每 1000 个模型里约有 50 个纯属巧合地挂掉。银行手里通常有几十个 VaR 模型,任何一天都可能有一个偶然失败。所以对单次检验失败的正确反应是调查而不是加资本:先手动重算失败那几天的 VaR、核对输入,再确认已实现损失本身算得对不对,然后才谈诊断——是 regime 变化、模型设定错误,还是历史序列里混进了一个错误价格。孤立的失败多半是巧合;持续的失败(连续两个月以上)才大概率指向真实的模型错误。

回测能告诉你什么、不能告诉你什么

拿实际数据跑过回测的团队,通常会看到三个反复出现的形态。构建良好的模型命中率贴近期望——99% VaR 一年 2 到 4 次命中属正常,年年 5 到 10 次就是失校。命中普遍带一点聚集——收益的波动率聚集会传导成 VaR 命中的聚集,Christoffersen 检验能看见。而最重要的形态是:即使好模型也会在 regime 切换时集体失效——2008、2020 都是例子,命中又聚集又超量,模型以为自己运行在正常世界里,其实世界已经换了。

第三个形态划出了回测的能力边界。回测只能核对模型与已经发生过的数据的一致性;跟过去毫无相似之处的事件,它原理上就检测不到。这不是把检验做得更精细能解决的问题,要靠压力测试、情景分析和反向压力测试来补——那是另一篇的主题。

对读风险报告的人,回测还有一个朴素的用途:它是检验风险团队本身的检验。对方引用 99% VaR 500 万美元,而 250 天回测显示 10% 的突破率,那这个数字错在伤害你的方向上——该追问的不是市场,是模型。期望值记住一个就够:99% VaR、250 个交易日,命中该在 2.5 次上下。5 次,黄区,去调查;10 次,红区,模型错了;0 到 1 次,模型太保守,资本占多了——保守不是免费的。

参考文献

Acerbi, C., & Szekely, B. (2014). Backtesting expected shortfall. Risk Magazine, December 2014.

Basel Committee on Banking Supervision. Supervisory Framework for the Use of Backtesting in Conjunction with the Internal Models Approach to Market Risk Capital Requirements. 1996.

Christoffersen, P. F. (1998). Evaluating interval forecasts. International Economic Review, 39(4), 841-862.

Christoffersen, P. F., & Pelletier, D. (2004). Backtesting value-at-risk: a duration-based approach. Journal of Financial Econometrics, 2(1), 84-108.

Du, Z., & Escanciano, J. C. (2017). Backtesting expected shortfall: accounting for tail risk. Management Science, 63(4), 940-958.

Engle, R. F., & Manganelli, S. (2004). CAViaR: conditional autoregressive value at risk by regression quantiles. Journal of Business & Economic Statistics, 22(4), 367-381.

Kupiec, P. H. (1995). Techniques for verifying the accuracy of risk measurement models. Journal of Derivatives, 3(2), 73-84.

McNeil, A. J., & Frey, R. (2000). Estimation of tail-related risk measures for heteroscedastic financial time series: an extreme value approach. Journal of Empirical Finance, 7(2-3), 271-300.

McNeil, A. J., Frey, R., & Embrechts, P. (2015). Quantitative Risk Management: Concepts, Techniques and Tools (rev. ed.). Princeton University Press. Ch. 13.