halo 的技术博客

返回

VaR 回答的是”95% 或 99% 的日子里损失不超过多少”——它管的是一般的坏日子。但风控委员会真正夜不能寐的问题长得不一样:“我们这个组合,十年一遇、百年一遇的单日损失是多少?“这个问题 VaR 答不了:百年一遇对应 99.996% 分位数,任何长度的样本在那个深度都没有几个观测点,经验分位数直接失明。

结论先放这:极值理论(EVT)的区组极大值方法给这个问题一个有数学定理背书的外推工具。Fisher-Tippett-Gnedenko 定理保证:区组最大值的分布(如果收敛)只可能收敛到广义极值分布(GEV)一族,肥尾还是薄尾由一个形状参数 ξ 决定。GARCH-t(5) 模拟 40 年日损失、按月分块(480 块)实测:GEV 拟合估出 ξ=0.24(理论值 1/ν=0.2),KS 检验 p=0.87 不可拒绝;强行用薄尾的 Gumbel(ξ=0)拟合被 KS p=0.008 处决,且它报的 100 年一遇日损失只有 6.9%,GEV 报 14.0%——薄尾假设在最需要模型的地方把风险砍掉一半

极值的中心极限定理#

普通中心极限定理说:iid 随机变量的(标准化后)收敛到正态分布,不管原始分布长什么样。Fisher-Tippett-Gnedenko 定理(1928/1943)是极值世界的对应物:iid 随机变量的最大值 Mn=max(X1,,Xn)M_n = \max(X_1, \dots, X_n),如果经线性标准化后收敛到某个非退化分布,那个分布必属于 GEV 一族

G(x)=exp{[1+ξxμσ]1/ξ}G(x) = \exp\left\{-\Big[1 + \xi\,\frac{x-\mu}{\sigma}\Big]^{-1/\xi}\right\}

三个参数:位置 μ、尺度 σ、形状 ξ。ξ 一个数决定尾部性格

  • ξ > 0(Fréchet 域):幂律尾。t 分布、Pareto 都住这里,且有干净的对应关系 ξ = 1/ν——t(5) 的日损失,其块最大值的 GEV 形状参数理论上就是 0.2。尾巴重到一定程度(ξ≥0.5)连方差都不存在。
  • ξ = 0(Gumbel 域):指数式衰减的尾。正态、对数正态、指数分布住这里。
  • ξ < 0(Weibull 域):尾部有硬上界。金融损失基本用不到。

这个定理的份量在于它把外推从”拍脑袋”变成”有约束的估计”:你不需要知道日损失的真实分布,只要它属于某个吸引域,块最大值的形状就被定理钉死在三参数族里。样本内估出 ξ,样本外的深尾由 GEV 的解析形式接管。

实验设置:40 年日损失,按月分块#

DGP 用 GARCH(1,1)-t(5)(α=0.09, β=0.89,波动聚集 + 肥尾,贴近真实股指),生成 40 年 ≈ 10080 个交易日的日损失,按 21 天分块取每月最大日损失,得到 480 个块最大值:

日损失序列与月块最大值

月最大值序列均值 1.91%、样本内最大 10.35%。对这 480 个数做 GEV 极大似然:

from scipy import stats

# scipy 的 genextreme 参数 c = -xi(注意符号约定!)
c_hat, loc, scale = stats.genextreme.fit(M)      # M: 480 个月块最大值
xi = -c_hat                                       # 0.240

# 对照组:强行 Gumbel(xi=0)
loc_g, scale_g = stats.gumbel_r.fit(M)

# 拟合优度
stats.kstest(M, lambda x: stats.genextreme.cdf(x, c_hat, loc, scale))
# GEV: p=0.873 ✅    Gumbel: p=0.008 ❌
python

估出 ξ=0.24,与理论值 1/5=0.2 一个 bootstrap 标准误内。QQ 图把两个模型的差异钉在深尾:

分布拟合与 QQ 图

左图三条密度曲线在主体部分几乎重叠——块最大值的”普通部分”谁都拟合得了。分歧全在右尾:Gumbel 的指数尾追不上经验点,QQ 图上蓝点在 6% 以上全部翘离对角线。灰色点线是”正态日损失隐含的月最大值分布”(F21F^{21}),错得更远——它连块最大值的主体都对不齐。

回报水平:把 ξ 翻译成风控语言#

GEV 的核心输出是回报水平(return level):m 个块才被超越一次的损失水平,即 GEV 的 11/m1-1/m 分位数。“100 年一遇的最坏单日损失” = 1200 月回报水平:

回报水平曲线

回报周期GEV (ξ=0.24)Gumbel (ξ=0)经验分位数
10 个月3.3%3.2%3.2%
5 年(60 月)6.0%4.6%6.4%
20 年(240 月)9.0%5.6%9.0%
40 年(480 月,样本长度)10.9%6.2%≈10.4%(样本最大)
100 年(1200 月)14.0%6.9%不存在

三个观察:

样本内两个模型难分伯仲,样本外分道扬镳。10 个月回报水平谁都对;到 20 年,Gumbel 已经低估 38%;到 100 年,Gumbel 报 6.9%、GEV 报 14.0%——差一倍。而 100 年一遇恰恰是压力测试和经济资本计算真正要的数字。对数坐标下 Gumbel 的回报水平是直线(指数尾的签名),Fréchet 域是上凸曲线,肥尾的惩罚随外推深度复利增长。

经验分位数在样本内贴着 GEV 走,出了样本就没有了。这就是 EVT 的卖点:240 月回报水平经验值 9.03%、GEV 报 9.01%——模型在能验证的范围内是诚实的,于是外推到 1200 月才有底气。

不确定性必须一起报。参数化 bootstrap(400 次重抽 + 重估)给出 100 年回报水平的 90% 区间 [10.6%, 18.0%]——中心值 14.0% 带着 ±4 个百分点的雾。这不是模型的耻辱而是诚实:用 480 个点外推 2.5 倍样本长度,谁报一个不带区间的精确数字谁才可疑。

块长的偏差-方差权衡#

分块方案是区组极大值方法的第一个工程决策,两头都是坑:

  • 块太短:块内观测太少,块最大值还没进入 GEV 的渐近区,近似偏差大;
  • 块太长:总样本固定时块数太少,参数估计方差爆炸。

固定 10080 天总样本,块长从 5 天扫到 126 天:

块长权衡

ξ 的估计从 0.14(5 天块,严重低估——块太短,最大值被主体分布污染)爬到 0.24(21 天块,贴近理论值),再漂到 0.41(126 天块,只剩 80 个块,置信区间宽到没有信息量)。月块(21 天)在这个设定下恰好坐在偏差消退、方差还没起飞的甜点上——这也是金融应用里月块/季块成为默认的原因。右图显示 20 年回报水平对块长相对稳健(7.3%~9.9%),因为 ξ 偏低时 σ 会补偿——但这种参数间的补偿在更深的外推处会解体。

诚实边界#

iid 假设被波动聚集正面违反。定理要求块内观测 iid,GARCH 序列显然不是。理论后果(Leadbetter 的 extremal index θ):相依序列的块最大值仍收敛到 GEV,但有效样本量缩水为 nθ——极端值扎堆出现,480 个块最大值携带的独立信息少于 480 份。实操修法有两个方向:先用 GARCH 滤波把残差洗成近似 iid 再做 EVT(推荐,McNeil & Frey 2000 的两步法),或直接估 extremal index 打折。本实验没有做这层修正,ξ 估计仍然贴近理论值,但置信区间比报告的更宽

区组极大值 vs POT 的数据效率之争。每块只留一个最大值,其余观测全部扔掉——40 年数据只喂给模型 480 个数。Peaks-over-Threshold 路线(GPD 拟合超阈值)保留所有超过阈值的观测,同样数据通常多出几倍有效样本。POT 的代价是阈值选择这个新的研究者自由度(太低偏差、太高方差,和块长同构的权衡)。共识大致是:数据多、只关心”每期最坏”语义(如月度风险报告)用区组极大值;数据紧、要榨干尾部信息用 POT

外推不是免费的。GEV 给的是”如果尾部行为按样本内规律延续”的条件陈述。结构性断裂——市场微观结构改变、断路器制度、前所未有的政策干预——不在任何统计模型的射程内。1987 年 10 月 19 日的 -22.6% 对当时任何用历史数据拟合的模型都是九个标准差事件;EVT 能把”不可能”修正成”百年一遇”,但它不能预言分布本身被改写的那一天。

参数不确定性在深处主导。1200 月回报水平的 bootstrap 区间宽达 7.4 个百分点,其中大头来自 ξ 的估计噪声(ξ 每偏 0.05,百年水平动 15% 以上)。任何用 EVT 数字做决策的场合,报点估计不报区间等于报喜不报忧。

把这篇和 VaR 回测系列连起来看:KupiecChristoffersenDQ 管的是”95%/99% 的模型每天有没有说谎”,EVT 管的是”最坏情形的量级有没有低估”。前者是日常体检,后者是极限压力测试——一个成熟的风险框架两个都要,而且要知道它们互相替代不了

区组极大值 GEV:用广义极值分布刻画最坏月份
https://blog.halo26812.eu.org/blog/block-maxima-gev-risk
Author halo
Published at 2026年7月27日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨