← 返回模块
4.4.2.4beta 可读 · 未来付费校验通过内容版本 2026-05-28

压力测试、FRTB 与机构风险体系

4.4.2 · 风险模型与风险管理 · 量化全流程

某 H 股 + A 股双地区运营私募的首席风险官:周五下午三件事压在桌上。(1) 风控部要把当前持仓在「2015 年 A 股股灾再来一次」情景下重定价——CEO 周一下午开战略会要听数;(2) 监管要求按 2023 年新修《商业银行资本管理办法》算 FRTB 市场风险资本(基金有港股账户接入银行同业柜台,部分敞口需要并表);(3) 投委会要一张「一页式风险报告」(one-page risk summary),把 L1 协方差健康 + L2 跟踪误差归因 + L3 在险价值 + L4 压力测试 + 监管资本数全捏到一页 A4 上。这堂课讲的就是怎么把 L1 / L2 / L3 端到端串成生产风险体系,以及 2023 起 FRTB 监管框架的四大新规——这是 4.4.2 模块的​​资本课​​(capstone)。

L4 拿 L1 给的 ΣBARRA\Sigma_{\text{BARRA}}BBΣF\Sigma_FDD、因子收益时序,拿 L2 给的归因函数,拿 L3 给的 VaR/CVaR/ES 函数,​​不重新推导​​——本课的全部新增内容是四种压力测试 + Basel/FRTB 监管框架 + 一页式机构风险报告。

术语对齐表

本课新增的核心术语,与 data/glossaries/quant-glossary.yaml 标准译名一致:​​压力测试​​(stress test)、​​在险价值​​(value at risk, VaR)、​​条件在险价值​​(conditional VaR, CVaR;FRTB 称 97.5% expected shortfall, ES)、​​最大回撤​​(max drawdown,压力测试的核心读数)、​​跟踪误差​​(tracking error,L2 复用)、​​因子模型​​(factor model)、​​Barra 模型​​(Barra model)、​​协方差矩阵​​(covariance matrix)、​​对冲比率​​(hedge ratio,反向压力测试给出的隐含再平衡)。后续所有讨论用这些标准译名。

四种压力测试类型

下面是 ​Inline-code listing​ 中按固定顺序的四条:

named_scenario:      apply historical factor moves f_t for t in {2008-GFC, 2020-COVID, 2015-SSE-crash, ...} to current portfolio exposures b_p = B^T w; report worst-day, worst-5d, peak-to-trough drawdown, cumulative P&L
historical_replay:   for each business day t in lookback window, compute hypothetical PnL_t = b_p^T f_t * V_0; surface worst individual days rather than aggregating into a quantile
hypothetical_scenario: specify factor shock xi_k = c * sqrt(Sigma_F_kk) for c in {-3, +3}; conditional shock to other factors xi_{-k} = Sigma_F[-k, k] / Sigma_F[k, k] * xi_k; delta_PnL = -b_p^T xi * V_0
reverse_stress:      given target loss L*, solve min xi^T Sigma_F^{-1} xi subject to -b_p^T xi = L*; closed-form xi* = -L* / (b_p^T Sigma_F b_p) * Sigma_F b_p; surfaces the MOST-LIKELY scenario that triggers L*

规则:named + historical answer WHAT IF; hypothetical answers WHAT IF FACTOR X MOVES; reverse answers WHAT SCENARIO TRIGGERS LOSS L*

命名情景(named scenario)

修辞上最有冲击力——「如果 2008 再来一次,我们的账亏多少?」——也是投委会汇报的常规品。规范情景库(CN 版本):

  1. ​2015-06 到 2015-08 沪深300 -45%​​(8 周内,触发于场外​​配资​​杠杆头寸的去化 + 监管收紧;2015-07-08 单日 -7.4% 是 CN 规范单日最差)
  2. ​2015-08-11 RMB 贬值​​(USDCNY 3 日 +3.5%;股票市场后续 2 周 -10%)
  3. ​2016-01 熔断债危​​(新规触发熔断,4 个交易日累计 -15% 后撤销)
  4. ​2018全年去杠杆​​(沪深300 -25%;民营企业信用紧缩;中美贸易摩擦)
  5. ​2020-02-03 COVID 单日 -7.9%​​(沪深300;2015 以来最大单日跌)
  6. ​2021-02 茅指数解套​​(价值反弹,CN 史上最大单季动量崩盘,top-动量十分位 -25%)
  7. ​2021-07 互联网监管​​(滴滴 IPO 整改触发恒生科技 6 个月 -50%)
  8. ​2021-09 起 恒大 / 碧桂园 房地产信用​​(多年地产开发商信用解套)
  9. ​2022-09 到 2022-10 二十大重定价​​(-15% 再 +20% 反弹)

压测引擎把当前账户按每个情景的日因子变动重定价,报累计 P&L。CN 监管要求 (CBIRC 商业银行资本管理办法 2023 修订) 的命名情景包括 2015 A 股崩盘和 COVID 冲击,作为 CN 域内银行交易账户的强制名单。

历史回放(historical replay)

最完整的变体:对回溯窗内每个交易日(典型 1 年或 5 年或「GFC-缩放」= 2007–2009),把那一天的实现单日因子变动套到当前组合上算假设单日 P&L。本质上是历史 VaR 的​​单情景透明化​​——监管和风险官能直接看「哪一个具体日子在当前账上造成最大单日亏损」,而不只是一个 99% 分位数。

假设情景(hypothetical scenario)

「​​如果​​这个因子动一下」层。指定单因子冲击 ξk=cΣF,kk\xi_k = c \cdot \sqrt{\Sigma_{F, kk}}(典型 c=3c = -3+3+3);为了尊重跨因子相关,其他因子的「条件冲击」用多元正态条件均值

ξk=ΣF[k,k]/ΣF[k,k]ξk.\xi_{-k} = \Sigma_F[-k, k] / \Sigma_F[k, k] \cdot \xi_k.

这样一个规模因子(小盘走弱)的负向冲击会自动连带与之正相关的低波因子等。组合在该冲击下的 P&L 是 δPnL=wBξV0=bpξV0\delta\text{PnL} = -w^{\top} B \xi \cdot V_0 = -b_p^{\top} \xi \cdot V_0。规范库(CN):「SHIBOR +200bps」(央行加息)、「USDCNY +5%」(贬值)、「CN 信用利差 +100bps」(地产 / LGFV 压力)、「动量 -3 sigmas」(茅指数解套)、「小盘股 +3 sigmas」(2021 后小盘反弹)。

反向压力测试(reverse stress test)

​倒着问​​:给定目标损失 LL^*(典型 15% V_0 或监管资本阈值),解逆向问题「找到最可能的情景 ξ\xi^* 使 L(w,ξ)=LL(w, \xi^*) = L^*」。最可能的判据用 Mahalanobis 距离

minξΣF1ξs.t.bpξ=L.\min\, \xi^{\top} \Sigma_F^{-1} \xi \quad \text{s.t.}\quad -b_p^{\top} \xi = L^*.

拉格朗日闭式解:ξ=λΣFbp\xi^* = \lambda \Sigma_F b_p,λ\lambda 由约束定;最终 ξ=L/(bpΣFbp)ΣFbp\xi^* = -L^* / (b_p^{\top} \Sigma_F b_p) \cdot \Sigma_F b_p。Mahalanobis 距离 ξ=ξΣF1ξ=L/bpΣFbp\|\xi^*\| = \sqrt{\xi^{*\top} \Sigma_F^{-1} \xi^*} = L^* / \sqrt{b_p^{\top} \Sigma_F b_p} 是「该情景距离因子分布均值多少个标准差」——越小越可能发生。反向压力测试报告:「触发 15% 组合损失最可能的情景是一个 2.3 sigma 冲击,由规模 -1.8 sigma + 动量 -1.4 sigma + 低波 +1.2 sigma 组合而成」——​​最可能的灾难情景​​从 L2 暴露中自动浮出,不需要风险官猜。

Basel 监管演进

下面是 ​Inline-code listing​ 中按固定顺序的五条:

Basel_I_1988:    credit risk only; 8% capital ratio (Cooke ratio)
Basel_II_2004:   operational + market risk via standardised approach (rule-based weights) or internal-models approach (10-day 99% VaR * 3-4x multiplier rising with back-test failures)
Basel_II_5_2009: post-GFC patch — stressed VaR (re-run VaR on stressed 1y window like 2007-09), Incremental Risk Charge (IRC) for default + credit-spread, Comprehensive Risk Measure (CRM) for correlation trading, simple sqrt(10) 1d-to-10d scaling
Basel_III_2010+: liquidity coverage + net stable funding + capital buffers (structural overhaul)
FRTB_BCBS_d457_2019: replaces VaR with 97.5% ES, risk-factor-specific liquidity horizons (10/20/40/60/120 days), NMRF separate stressed charge for factors with <24 real-price observations, desk-level P&L attribution test gating IMA vs SBA; effective EU/UK Jan 2023, US Jul 2025

规则:97.5% ES is the regulatory headline: matches 99% Gaussian VaR by construction but coherent for non-Gaussian

​Basel I​​(1988)——只有信用风险,8% 资本比例(Cooke 比率)。​​Basel II​​(2004)——加入操作风险 + 市场风险(标准法按规则给权重;内部模型法 10 日 99% VaR × 3–4 倍乘数,乘数随回溯检验失败上调)。​​Basel II.5​​(2009)——GFC 后补丁:压力 VaR(在 2007–2009 这样的应力一年期上重跑 VaR 引擎,与日常 VaR 相加进资本)、增量风险 IRC(交易账违约 + 信用利差风险)、综合风险 CRM(相关交易簿);简单的 10\sqrt{10} 把 1 日 VaR 扩到 10 日。​​Basel III​​(2010 起)——流动性覆盖 LCR、净稳定融资 NSFR、资本保留缓冲、逆周期缓冲;结构性大修,非市场风险专项。

FRTB 四大新规

下面是 ​Inline-code listing​ 中按固定顺序的四条:

ES_replaces_VaR:        regulatory risk measure is 97.5% expected shortfall (not 99% VaR); 97.5% ES equals 99% VaR for Gaussian by phi(z_0.975)/(1-0.975) = z_0.99; ES is coherent for non-Gaussian where VaR is not
liquidity_horizons:     replace sqrt(10) with risk-factor-specific LH; 10d major FX/large-cap equity; 20d small-cap equity/major credit-spread; 40d non-major credit-spread; 60-120d illiquid credit / structured / NMRFs
NMRF_charge:            factors with fewer than 24 real (committed) price observations in lookback window get separate stressed-scenario capital charge with NO diversification benefit against IMA
pnl_attribution_test:   daily desk-level reconciliation between risk-system P&L and front-office P&L; Spearman correlation > 0.8 over 250 days AND KS distance < 0.09; 2 consecutive failures = SBA for next year minimum (capital ~30-50% higher)

规则:IMA gives lower capital but requires desk-level back-test compliance — failure pushes desk to SBA

​(i) ES 替代 VaR​​:监管市场风险度量由 99% VaR 改为 97.5% ES;选 97.5% 这个水平是因为高斯下 ϕ(z0.975)/(10.975)=z0.99\phi(z_{0.975}) / (1 - 0.975) = z_{0.99}——97.5% 高斯 ES 在高斯下恰等于 99% 高斯 VaR;但 ES 在非高斯下保留一致性,VaR 不能。​​(ii) 流动性期限​​:简单 10\sqrt{10} 替换为按风险因子的流动性期限。10 天:主要外汇 + 大盘股权益;20 天:小盘股权益 + 主要信用利差;40 天:次要信用利差;60–120 天:非流动信用 / 结构化 / NMRF。资本数按 hLHhδVaRh2\sqrt{\sum_h \text{LH}_h \cdot \delta\text{VaR}_h^2} 聚合。​​(iii) NMRF 收费​​:回溯窗内​​实成交价​​观测少于 24 个的风险因子归类为 NMRF,单独按压力情景计提资本,不享受与 IMA 的多元化抵扣。NMRF 典型来自非流动信用工具、奇异衍生品参数、结构化产品定价输入。​​(iv) 桌面级损益归因检验​​:每个交易桌每日提交风控 P&L(风险系统按因子变动算的)与前台 P&L(实际成交账)的对账。两个汇总统计:过去 250 天的 Spearman 相关 > 0.8;Kolmogorov-Smirnov 距离 < 0.09。失败两个月连续 = 该桌下一年最低跌入 SBA,资本约 +30%–50%。

实现:named_scenario_stress

import numpy as np
import pandas as pd

def named_scenario_stress(
    weights: np.ndarray,
    B: np.ndarray,
    factor_returns_history: pd.DataFrame,
    scenario_dates: list,
    V_0: float = 1.0,
) -> dict:
    # 组合层因子暴露
    b_p = B.T @ weights
    # 抽取情景窗的日因子收益
    f_scenario = factor_returns_history.loc[scenario_dates].values
    # 假设单日 P&L
    daily_pnl = f_scenario @ b_p * V_0
    worst_day_idx = int(np.argmin(daily_pnl))
    worst_day_pnl = float(daily_pnl[worst_day_idx])
    worst_day_date = scenario_dates[worst_day_idx]
    # 滚动 5 日累计
    rolling_5d = pd.Series(daily_pnl).rolling(5).sum()
    worst_5d_pnl = float(rolling_5d.min())
    # 峰谷回撤
    cum_pnl = daily_pnl.cumsum()
    running_max = np.maximum.accumulate(cum_pnl)
    drawdown = cum_pnl - running_max
    max_drawdown = float(drawdown.min())
    total_pnl = float(daily_pnl.sum())
    return {
        "worst_day_pnl": worst_day_pnl,
        "worst_day_date": worst_day_date,
        "worst_5d_pnl": worst_5d_pnl,
        "max_drawdown": max_drawdown,
        "total_pnl": total_pnl,
        "daily_pnl": daily_pnl,
        "cum_pnl": cum_pnl,
    }

签名(参数名 weights / B / factor_returns_history / scenario_dates / V_0、默认 V_0=1.0、返回字典键)与 US 版逐字节一致。

实现:reverse_stress_test

下面这段 Fenced Python 代码块封装​​反向压力测试​​:给定当前权重、L1 的因子载荷 B 与因子协方差 Sigma_F、目标损失阈值 target_loss(典型 15% × V_0),通过闭式解算出​​最可能​​的因子冲击向量 ξ\xi^*。返回的 mahalanobis 距离告诉你「这套灾难情景距离因子分布均值多少个标准差」——越小代表越可能发生,即风险越高。返回的 xi_star_normalised 用因子各自标准差作单位,可以直接读出「-1.8 sigma 的动量冲击」这种自然语言。​​反向压力测试是机构风控官最爱用的工具之一​​:不像命名情景需要找到「类似 2008」的历史模板,反向压测从当前持仓的因子暴露中自动浮出最危险情景——基金经理调仓后,最危险的情景也跟着变。

import numpy as np

def reverse_stress_test(
    weights: np.ndarray,
    B: np.ndarray,
    Sigma_F: np.ndarray,
    target_loss: float,
    V_0: float = 1.0,
) -> dict:
    # 组合层因子暴露
    b_p = B.T @ weights
    factor_variance = float(b_p @ Sigma_F @ b_p)
    # 拉格朗日乘子(目标损失为正数表示亏损)
    lam = -target_loss / (factor_variance * V_0)
    # 最可能的因子冲击
    xi_star = lam * Sigma_F @ b_p
    # Mahalanobis 距离(以因子分布标准差为单位)
    mahalanobis = float(np.sqrt(xi_star @ np.linalg.solve(Sigma_F, xi_star)))
    # 按因子 sigma 单位的标准化冲击
    xi_star_normalised = xi_star / np.sqrt(np.diag(Sigma_F))
    realised_loss = float(-b_p @ xi_star * V_0)
    top_3_factor_indices = np.argsort(np.abs(xi_star_normalised))[-3:][::-1]
    return {
        "xi_star": xi_star,
        "xi_star_normalised": xi_star_normalised,
        "mahalanobis": mahalanobis,
        "target_loss": target_loss,
        "realised_loss": realised_loss,
        "top_3_factor_indices": top_3_factor_indices,
    }

签名(参数名 weights / B / Sigma_F / target_loss / V_0、默认 V_0=1.0、返回字典键)与 US 版逐字节一致。

实现:hypothetical_single_factor_stress(辅助)

import numpy as np

def hypothetical_single_factor_stress(
    weights: np.ndarray,
    B: np.ndarray,
    Sigma_F: np.ndarray,
    factor_index: int,
    shock_sigmas: float,
    V_0: float = 1.0,
) -> dict:
    # 在因子 k 上施加 c sigmas 冲击
    K = Sigma_F.shape[0]
    xi = np.zeros(K)
    xi[factor_index] = shock_sigmas * np.sqrt(Sigma_F[factor_index, factor_index])
    # 其他因子的条件均值冲击(尊重相关性)
    for j in range(K):
        if j == factor_index:
            continue
        xi[j] = Sigma_F[j, factor_index] / Sigma_F[factor_index, factor_index] * xi[factor_index]
    b_p = B.T @ weights
    delta_pnl = float(-b_p @ xi * V_0)
    return {"delta_pnl": delta_pnl, "xi": xi}

一页式机构风险报告:capstone 实现

把 L1 / L2 / L3 / L4 的全部产出压成 5 段。下面是 CN 实例的产出结构(数字示意):

============================================================
Daily Risk Report — 2024-05-15 — 沪深300 指增 1 号
V_0 = 100,000,000 RMB

Section 1 — Covariance summary (L1)
  cond(Sigma_BARRA) = 45 (健康, <100)
  top-5 factor by Sigma_F diagonal: 新能源 / 电子 / 食品饮料 / 金融 / 医药
  total Sigma factor/specific split: 84% / 16%

Section 2 — Risk attribution (L2)
  annualised sigma_p = 18.2%  annualised TE vs 沪深300 = 3.8%
  TE 因子/特异: 75% / 25%   sigma_p 因子/特异: 84% / 16%
  top-5 PCTR stocks: 宁德时代 9.1%, 贵州茅台 8.3%, 招商银行 7.2%, 五粮液 6.5%, 比亚迪 6.1%
  top-3 |b_a|: 价值 +0.6 sigma; 动量 +0.3 sigma; 规模 -0.4 sigma

Section 3 — Tail risk (L3, 1 日)
  95% VaR: hist 3.1M  param 2.7M  MC-t 3.4M
  99% VaR: hist 5.8M  param 4.2M  MC-t 6.5M
  99% CVaR: hist 7.4M  param 4.8M  MC-t 8.7M
  flag: param 与 MC-t 在 99% 差异 55%(超 50% 阈值)

Section 4 — Stress tests (L4)
  2008-GFC replay (2008-08-01 to 2008-12-31):
    worst day -7.2M (2008-09-29) | worst 5d -14.5M | max drawdown -28M | total -22M
  2015-A 股 crash (2015-06-15 to 2015-08-26):
    worst day -8.1M (2015-07-08) | worst 5d -19M | max drawdown -38M | total -34M
  hypothetical SHIBOR +200bps: delta_PnL -3.2M
  reverse stress for 15% loss (15M):
    most-likely scenario: 2.3 sigma (规模 -1.8, 动量 -1.4, 低波 +1.2)

Section 5 — FRTB IMA capital
  ES_97.5_today (parametric) = 4.6M
  mean ES_97.5 over 60 days = 4.4M
  Capital_FRTB = max(4.6, 4.4) * 3.0 * 1.0 = 13.8M (13.8% of V_0)
  flag: 资本占比 < 20% 阈值(通过)

THRESHOLDS:  TE 4%  VaR_99 3%  stress drawdown 30%  FRTB capital 20%
FLAGS:       Section 3 (parametric vs MC-t 99% disagreement)
ALL OTHERS:  PASS
============================================================

权益单一账上 FRTB 流动性期限取 10 天,LH 缩放因子 = 1.0;若该账涉及非流动信用工具,需要按 (10 / 10 + 20/20 + 60/60 + 120/120)1/2^{1/2} 等更复杂聚合。

可视化:压力测试瀑布图

Formula Explorer

x^2

把命名情景的日 P&L 序列画成累计曲线;反向压力测试结果画成「因子冲击条形图」(每个因子的 ξnormalised\xi^*_{\text{normalised}});把每周 / 每月的 FRTB 资本时序画成红线对比内部资本 limit 的蓝线。投委会一眼看出哪些情景超 limit、哪些月份资本占比超阈值。

练习

Exercise

你是 50 只主动权益基金的首席风险官 (cn: 50 沪深300板块龙头, V_0 = 100,000,000 RMB)。给定 (i) weights(L2 主动组合), (ii) benchmark_weights(cn: 沪深300), (iii) L1 的 Sigma_BARRABSigma_FD, (iv) factor_returns_history(L1 的 K 因子收益时序,2008-01 到 2023-12), (v) returns_history(L3 历史 VaR 用的资产收益时序)。产出一页机构风险报告,包含以下五段。(a) ​Section 1 — 协方差摘要​​:报告 cond(Sigma_BARRA)Sigma_F 对角排前 5 的因子(波动率排名)、总组合方差 σp2\sigma_p^2 的因子-特异比。(b) ​Section 2 — 风险归因​​(复用 L2 辅助):报告年化 sigma_p、年化 TE、两者的因子-特异比、PCTR 前 5 资产、|b_a| 绝对值前 3。(c) ​Section 3 — 尾部风险​​(复用 L3 辅助):报告 1 日 95% / 99% VaR 与 CVaR 的三方法(历史 / 参数法 / MC-t with nu=5);任一对方法差异 > 50% 打 flag。(d) ​Section 4 — 压力测试​​:调 named_scenario_stress 两次:(i) 2008 GFC 窗 (2008-08-01 到 2008-12-31)、(ii) CN 地区危机 (2015-06-15 到 2015-08-26 A 股股灾);报告 worst_day_pnl、worst_day_date、worst_5d_pnl、max_drawdown、total_pnl。调 hypothetical_single_factor_stress 一次:(iii) 利率因子 SHIBOR +200bps。调 reverse_stress_test(weights, B, Sigma_F, target_loss=0.15 * V_0, V_0=V_0):(iv) 15% 组合损失;报告 mahalanobis、前 3 因子索引及其 xi_star_normalised;一句话写出最可能的灾难情景(比如「2.3 sigma 情景:动量 -1.8 + 规模 -1.4 + 低波 +1.2」)。(e) ​Section 5 — FRTB IMA 资本​​:在 Sigma_BARRA 上用参数高斯算过去 60 天滚动 97.5% ES(sigma_L * phi(z_0.975) / (1 - 0.975));算 Capital_FRTB ≈ max(ES_97_5_today, mean(ES_97_5_over_last_60_days)) * 3.0;报告 Capital_FRTBV_0 百分比。把整套报告排成一张「Daily Risk Report — [date] — [fund name]」一页;任一段超过内部阈值 (TE > 4%, VaR_99 > 3% V_0, 压测 max drawdown > 30% V_0, FRTB 资本 > 20% V_0) 必须 flag。

提示
反向压力测试 xi_star 是因子收益单位;转成「因子 sigma 单位」要除以 np.sqrt(np.diag(Sigma_F)),这样才能直观说「-1.8 sigma 的动量冲击」。
提示
FRTB 简化 IMA 资本 = max(当日 ES, 过去 60 日 ES 均值) × 3.0 × 流动性期限缩放;权益单一账 LH = 10 天,缩放 = 1.0;非线性 / 流动性差头寸要叠 NMRF 罚款。

桥接到 4.4.3

4.4.2 到此结束:L1 给出结构化协方差(Barra 分解),L2 把它读成风险归因(MCTR / TE / b_a / IR),L3 切到分位数风险(三方法 VaR + CVaR + Artzner 一致性),L4 端到端串成机构生产风险体系(四种压力测试 + Basel/FRTB 监管框架 + 一页式报告)。模块 4.4.3《约束式组合优化》(Constrained Portfolio Optimisation)拿 L2 的 PCTR 当​​风险预算​​约束的输入,拿 L3 的 CVaR 当​​尾部风险约束​​的输入,拿 L4 的因子暴露当​​因子中性约束​​的输入,在 CVXPY 中显式求解带交易成本、换手率、行业 / 国家 / 因子上下限的实盘可行组合。简言之:4.4.1 给 MV 理论,4.4.2 给风险度量,4.4.3 给可执行优化——三者构成「组合构造与风险」(Subject 4.4)的完整三角。