halo 的技术博客

返回

你有一篮子资产,想知道「当第一支暴跌时,其他几支有多大概率跟着跌」。这听起来是个相关性问题,但传统的多元高斯 copula 会给你一个错误又危险的答案。

2008 年金融危机里,大量结构化产品用高斯 copula 给 CDO 定价,结果在危机来临时相关性「瞬间发散」——所有资产一起跳水,而高斯 copula 假设的上/下尾对称让它根本没把这种下尾联动量化进去。教训很清楚:能刻画尾部依赖的模型,在风险管理里不是锦上添花,是保命。

Vine Copula(藤 Copula) 是绕开这个盲点的主流解法:它不强行用一个 D 维 copula 套住所有变量,而是把高维依赖拆成一棵「藤」,每一层只处理一对变量的条件依赖。于是你可以在某一对用 Clayton(下尾强)、另一对用 Gumbel(上尾强)、再一对用高斯(对称),把结构拼回 D 维联合分布。

本文用纯 numpy 从零实现 C-Vine(以某一变量为根的藤),把 4 个资产的下尾依赖织到 0.71,而同等 Kendall’s tau 的高斯 copula 只有 0.40。


一、为什么高斯 copula 在危机里失灵#

多元高斯 copula 把所有变量的依赖压缩成一个线性相关矩阵 ρ\rho。它的对称性意味着:上尾(大涨)和下尾(大跌)的依赖程度一模一样。但真实市场是非对称的——

  • 平静时各资产各走各的(相关性低);
  • 危机时恐慌传染,所有资产一起跌(下尾依赖极高)。

高斯 copula 用一个对称椭圆去近似,于是它系统性地低估了下尾、高估了上尾

Clayton copula 天生偏向下尾:它的下尾依赖 λL\lambda_L 是显式的、且 λL>0\lambda_L>0(高斯 copula 的 λL=0\lambda_L=0)。数学上,二元 Clayton:

C(u,v;θ)=(uθ+vθ1)1/θ,θ>0C(u,v;\theta) = \big(u^{-\theta} + v^{-\theta} - 1\big)^{-1/\theta},\quad \theta>0

它的 Kendall’s tau 与参数关系干净:τ=θ/(θ+2)\tau = \theta/(\theta+2);下尾依赖 λL=21/θ\lambda_L = 2^{-1/\theta}。把 θ=2\theta=2 代进去,得到 τ=0.5\tau=0.5λL=21/20.707\lambda_L=2^{-1/2}\approx 0.707

问题来了:Clayton 只能建二元对。4 个资产要怎么织?这就是 Vine 的舞台。


二、Vine 的核心思想:把高维拆成二元藤#

一个 D 维 copula 的联合密度可以写成一串条件二元密度的连乘(pair-copula construction,Aas et al. 2009):

f(u1,,uD)=k=1D1j=1Dkcj,j+k1,,j1(Cj1,,j1,Cj+k1,,j1)f(u_1,\dots,u_D) = \prod_{k=1}^{D-1}\prod_{j=1}^{D-k} c_{j,j+k|1,\dots,j-1}\big(C_{j|1,\dots,j-1},\, C_{j+k|1,\dots,j-1}\big)

翻译一下:把变量一个个「挂」到藤上,每一对(可能以更早的变量为条件)都用自己最合适的二元 copula。以 C-Vine(根变量 = 1) 为例,4 个变量的三层藤是:

  • Tree 1(1,2), (1,3), (1,4)(1,2),\ (1,3),\ (1,4) —— 所有边都直接以 X1X_1 为根;
  • Tree 2(2,31), (2,41)(2,3|1),\ (2,4|1) —— 以 X1X_1 为条件;
  • Tree 3(3,41,2)(3,4|1,2) —— 以 X1,X2X_1,X_2 为条件。

每层的条件变量是「藤上更高的节点」,越往下条件越多。

C-Vine 结构: 三层二元藤:Tree1 全部以 X1 为根,Tree2 以 X1 为条件,Tree3 以 X1,X2 为条件。每个条件二元对都是一棵小树

关键好处:每一层都可以用不同的 copula 族。想让某对危机里共跌?挂 Clayton。想让某对大涨时联动?挂 Gumbel。想让某对平时就强相关?挂高斯。Vine 把「选族」的自由度还给了你。


三、从零实现:Clayton 的 h-函数与逆(采样的关键)#

要从 Vine 里采样,需要一对互逆的条件 CDF(h-函数)工具。对二元 Clayton,hh 是把「联合概率」投影到「以某一变量为条件」的边际:

h(ucond,uother;θ)=Cucond=ucondθ1(ucondθ+uotherθ1)(θ+1)/θh(u_{\text{cond}}, u_{\text{other}};\theta) = \frac{\partial C}{\partial u_{\text{cond}}} = u_{\text{cond}}^{-\theta-1}\big(u_{\text{cond}}^{-\theta}+u_{\text{other}}^{-\theta}-1\big)^{-(\theta+1)/\theta}

它的逆 h1h^{-1} 有解析解(Aas et al. 2009,直接照抄即用):

h1(w,ucond;θ)=(1+ucondθ(wθ/(θ+1)1))1/θh^{-1}(w, u_{\text{cond}};\theta) = \Big(1 + u_{\text{cond}}^{-\theta}\big(w^{-\theta/(\theta+1)}-1\big)\Big)^{-1/\theta}

下面这段是本文全部数值实验的引擎,纯 numpy,无外部依赖:

一致性自检(务必做,否则采样会悄悄出错):clayton_h(u_cond, clayton_hinv(w, u_cond), th) 必须等于 w。我用三组随机数验证 allclose(atol=1e-6) 通过——这一步别省,手写反演代数极易符号错位。


四、C-Vine 逆 Rosenblatt 采样(纯 numpy)#

采样思路是 Rosenblatt 逆变换:先抽独立均匀噪声 v1,,vDv_1,\dots,v_D,再从根变量起逐层反解 uiu_i,使得「前向 h-级联」恰好等于 viv_i。对任意树结构都正确的通用做法是「前向算 h-级联 → 二分反解 uiu_i」,不用手写每层的反演代数:

cvine_sample(80000) 后,验证两件事:① 每个边缘都应是 Uniform(0,1)(均值≈0.5,实测通过);② 下尾依赖应逼近理论值。下面这张密度图直观说明为什么 Clayton 能织出危机共跌——它的概率质量堆积在左下角(两个变量同时很小),而高斯 copula 的密度是对称椭圆:

Clayton(theta=2) 二元密度: 左下尾集中 vs 高斯(rho=0.71) 密度: 对称椭圆。左下角聚集正是下尾依赖的来源


五、实测:Vine 把下尾依赖织到 0.71,高斯只有 0.40#

我生成两组 4 维样本:一组走 C-Vine(每层 Clayton,θ=2\theta=2);另一组走高斯 copula,但其线性相关 ρ=sin(πτ/2)=sin(π/4)0.707\rho=\sin(\pi\tau/2)=\sin(\pi/4)\approx 0.707保证两者的 Kendall’s tau 完全相同(都是 0.5),这样对比才公平。

下尾依赖定义:λL(i,1)=P(Ui<0.05U1<0.05)\lambda_L(i,1) = P(U_i < 0.05 \mid U_1 < 0.05),用 5% 分位作为「危机区」。实测结果:

变量对C-Vine (Clayton)高斯 Copula
(1,2)(1,2)0.7170.389
(1,3)(1,3)0.7130.409
(1,4)(1,4)0.7190.399

理论下尾依赖 21/2=0.7072^{-1/2} = 0.707,C-Vine 三对全部贴近(误差来自采样)。而同等 Kendall’s tau 的高斯 copula 只有约 0.4,且理论上它的 λL\lambda_L 应为 0——这里测到的 0.4 完全是 5% 矩形里的有限样本联合概率,不是真正的尾部依赖,但已足够说明它远低于 Vine

下尾依赖: Vine 让资产危机中共跌(0.71), 高斯 copula 几乎为 0(约0.40)。柱越高表示「第一支跌时另一支跟着跌」的概率越大

散点图更直白:Vine 样本的 (U1,U4)(U_1,U_4) 在左下角明显聚集(危机区实线框内点密),高斯 copula 则均匀铺开、左下角无超额聚集。

Vine (U1,U4): 左下角危机区聚集 vs 高斯 Copula: 下尾无聚集。两张散点图同样 4000 点,危机区框(0,0)-(0.05,0.05)内 Vine 明显更密

这就把文章开头那句话落了地:高斯 copula 在危机里失灵,不是因为它「算错了相关性」,而是它的对称性让它根本没能力表达「只跌不涨」的尾部联动。Vine + Clayton 补齐了这块。


六、怎么用到实盘风险管理#

把上面的 UiU_i 换成各资产收益的秩变换(或经 GARCH 过滤后的标准化残差的 CDF):ui=Fi(ri)u_i = F_i(r_i)。然后用 Vine 拟合:

  1. 选结构:C-Vine 根变量通常选「系统性因子最强」的那个(如沪深300、或市值最大的成分股),R-Vine 更灵活但搜索空间大;
  2. 选族 + 估参:每条边独立做「两两拟合 → 选族(AIC)→ 估参」,得到每对的条件 Kendall’s tau;
  3. 算联合 VaR / 组合压力测试:从拟合好的 Vine 采样一万个情景,直接数「组合跌幅 > x%」的频率,比用多元正态假设得到的 VaR 在危机里稳健得多
  4. CoVaR / 系统性风险:固定某机构 ii 处于危机分位,看条件分布下整个组合的其他部分会跌多少。

一句话:Vine 给你的不是「相关性是多少」一个数字,而是一棵能回答「谁在什么时候拖谁下水」的依赖树。


七、诚实的边界(最易踩的坑)#

  1. 藤结构选择 = 维度灾难的真身。D 个变量,R-Vine 的可能结构数是超指数级的。实务上要么用启发式(按 Kendall’s tau 绝对值贪心选边),要么锁 C-Vine/D-Vine。结构选错,族选得再对也救不回来。
  2. 参数估计是「成对」的,不是联合的。Vine 的优雅在于每对边独立拟合,但条件变量的「条件值」本身也来自估计,误差会沿藤向下传播。样本不够时,深层边的参数会非常不稳定。
  3. 条件采样偏倚。本文用二分反解做逆 Rosenblatt,偏倚可控;但若你用「直接套现成 h-逆代数」且某层族换了(比如改成 Gumbel),那个解析逆就完全不对了——必须针对每个族重新推导 hhh1h^{-1}。这就是我坚持用「前向级联 + 二分反解」通用写法的原因:换族不用重写反演。
  4. 高斯 copula 并非一无是处。当你的真实依赖确实对称(比如一串高度相关的同质 ETF),硬上 Clayton 反而引入虚假下尾。族的选择要由数据(上下尾依赖的经验估计)说了算,别先入为主。

八、完整可复现:从数据到图#

把下面整段保存为 vine_demo.py 即可跑出本文全部数字(依赖仅 numpy + scipy.stats,图用 matplotlib)。核心是第三节的 clayton_h / clayton_hinv 与第四节的 cvine_sample,再接一个下尾依赖估计:

跑出来你会看到 C-Vine 三对 ≈ 0.71、高斯 ≈ 0.40、理论 0.707——和本文数字一致。这才是 Vine Copula 真正比高斯 copula 强的地方:它把「危机共跌」从一句经验之谈,变成了可以量化、可以采样、可以进 VaR 模型的尾巴。

Vine Copula 依赖建模:用层级藤把高维尾部联动拆成条件二元对
https://blog.halo26812.eu.org/blog/vine-copula-dependence
Author halo
Published at 2026年7月23日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨