溢出指数与连通性网络:用 Diebold-Yilmaz 把风险传染画成地图
2008 年雷曼倒下,为什么远在亚洲的股指也跟着崩?风险不是孤立的,它会沿资产间的关系『传染』。Diebold-Yilmaz 连通性框架用 VAR + 广义预测误差方差分解,把『谁在传染谁、传了多少』量化成一张可计算的地图,并派生出总连通度 TCI(系统性风险温度计)和方向性净溢出 NET(谁是传染源)。本文用 5 类资产合成数据,从零复现连通性矩阵、网络图与滚动 TCI,并点明滞后阶、预测期、正交化、样本期四类真实陷阱(中阶)。
2008 年 9 月,雷曼破产。三个月后,一个只投了日经 ETF 的组合也腰斩了——你从来没碰过美国次贷,为什么也被拖下水?
答案只有两个字:传染。
资产不是孤岛。股票的冲击会顺着相关性、资金流、避险情绪,传到债券、黄金、原油、外汇。真正的风险管理,不能只看「我买了什么」,还要看「我买的这些,会被谁传染、又会传染谁」。
Diebold-Yilmaz(DY)连通性框架干的就是这件事:它用一套 VAR + 预测误差方差分解,把「A 冲击对 B 波动的解释力」量化成一个数,然后拼成一张全网地图。从中你能读出两样东西:
- 总连通度 TCI——整张网的「联结紧密程度」,是系统性风险的体温计;
- 方向性净溢出 NET——谁是传染源(净输出),谁是接收方(净接收)。
本文用 5 类资产的自洽合成数据,从零复现这套方法,并给出真实可用的数字。
一、核心思想:用「方差解释力」度量传染#
经典思路:建一个 VAR 模型刻画各资产收益的联动,然后问一个问题——
如果我给资产 j 一个冲击,未来 H 步里,资产 i 的波动(预测误差方差)有多大比例是由这个 j 冲击造成的?
这个比例,就是 A 对 B 的「传染强度」。把全部 i、j 的比例排成矩阵,就是连通性矩阵 。
- 行 :资产 的波动,被各来源解释了多少(行归一,合计 100%);
- 列 :资产 的冲击,解释了别人多少波动;
- 对角 :自身冲击解释自身波动的部分(越大越「独立」)。
DY 的精髓在于:不要求冲击正交(允许相关性),所以用广义预测误差方差分解(GFEVD,Koop-Pesaran-Shi 1996),比早期需要 Cholesky 排序的版本更稳健。
二、合成数据:让股票当「传染源」#
为了能验证方向,我们造一组 5 类资产日收益,故意让股票的滞后项单向驱动其他资产,危机窗口再放大这个传导:
import numpy as np
ASSETS = ["股票", "债券", "黄金", "原油", "外汇"]
N = 5
rng = np.random.default_rng(20260719)
T = 1600
# 常态 VAR(1): r_i(t) = Σ_j A[i,j]·r_j(t-1) + 特异冲击
# 只有股票是「因」:其他资产都含 A[i,0]·r_股票(t-1),反向为 0
A_normal = np.array([
[0.15, 0.00, 0.00, 0.00, 0.00], # 股票: 仅自身持续
[0.28, 0.10, 0.00, 0.00, 0.00], # 债券 ← 股票
[0.22, 0.00, 0.08, 0.00, 0.00], # 黄金 ← 股票
[0.32, 0.00, 0.00, 0.12, 0.00], # 原油 ← 股票
[0.20, 0.00, 0.00, 0.06, 0.05], # 外汇 ← 股票
])
A_crisis = A_normal.copy()
A_crisis[1:, 0] *= 2.4 # 危机期:股票→他者传染放大 2.4 倍
A_crisis[1, 2] = 0.12; A_crisis[2, 1] = 0.10 # 债券↔黄金避险共振
vol = np.array([0.012, 0.004, 0.008, 0.018, 0.006])
Sigma_eps = np.diag(vol ** 2)
r = np.zeros((T, N)); r[0] = rng.normal(0, vol)
for t in range(1, T):
cs = 700 <= t <= 820 # 危机窗口
A = A_crisis if cs else A_normal
r[t] = A @ r[t - 1] + rng.multivariate_normal(np.zeros(N), Sigma_eps)python三、VAR 估计 + 广义方差分解#
先 OLS 估计 VAR(1):
def fit_var1(x):
Y = x[1:]; Z = x[:-1]
Ahat = np.linalg.lstsq(Z, Y, rcond=None)[0].T # k×k
resid = Y - Z @ Ahat
Sigma = resid.T @ resid / len(resid)
return Ahat, Sigma
def gfevd(Ahat, Sigma, H=10):
k = Ahat.shape[0]
Phi = [np.eye(k)]
for h in range(1, H + 1): # MA(∞) 系数递推
ph = sum(Ahat @ Phi[h - l] for l in range(1, h + 1))
Phi.append(ph)
sig = np.diag(Sigma)
num = np.zeros((k, k)); denom = np.zeros(k)
for h in range(H):
Ph = Phi[h]
for i in range(k):
ei = np.zeros(k); ei[i] = 1
denom[i] += ei @ Ph @ Sigma @ Ph.T @ ei
for j in range(k):
ej = np.zeros(k); ej[j] = 1
for i in range(k):
ei = np.zeros(k); ei[i] = 1
num[i, j] += (ei @ Ph @ Sigma @ ej) ** 2 / sig[j]
fevd = num / denom[:, None]
return fevd / fevd.sum(axis=1, keepdims=True) # 行归一python跑完得到连通性矩阵 (行=被影响 i,列=冲击来源 j):

图 1:第一列(股票作冲击来源)每一行都显著非零——说明股票冲击渗透到所有资产;而第一行几乎只有对角亮,说明股票自身的波动很少来自别人。这就是「股票是传染源」在矩阵上的长相。
| 被影响 i ↓ \ 来源 j → | 股票 | 债券 | 黄金 | 原油 | 外汇 |
|---|---|---|---|---|---|
| 股票 | 85.4 | 5.6 | 2.2 | 3.9 | 2.8 |
| 债券 | 76.6 | 13.6 | 3.1 | 2.4 | 4.3 |
| 黄金 | 64.8 | 16.0 | 13.3 | 1.4 | 4.5 |
| 原油 | 65.2 | 4.6 | 1.4 | 28.3 | 0.5 |
| 外汇 | 82.6 | 6.7 | 2.0 | 3.2 | 5.5 |
读表技巧:看第一列——股票冲击解释了债券 76.6%、黄金 64.8%、原油 65.2%、外汇 82.6% 的方差里「来自他者」的那部分。这是典型的「中心—外围」结构。
四、从矩阵到方向性指标#
DY 派生了三个关键量:
- 总连通度 ——全网溢出强度,系统性风险温度计;
- 净溢出 ,其中 是列 离对角之和(净输出), 是行 离对角之和(净接收)。
本文全样本结果:
| 资产 | TO(净输出) | FROM(净接收) | NET |
|---|---|---|---|
| 股票 | 289.3 | 14.6 | +274.7 |
| 债券 | 32.9 | 86.4 | −53.5 |
| 黄金 | 8.7 | 86.7 | −78.0 |
| 原油 | 11.0 | 71.7 | −60.8 |
| 外汇 | 12.1 | 94.5 | −82.4 |
股票 NET = +274.7,是压倒性的净传染源;其余四类全是负的净接收方,外汇最「被动」(NET −82.4)。总连通度 TCI = 70.8%——意味着全市场约七成的波动联动来自跨资产传染,而非各自独立。
把它画成网络图,一目了然:

图 2:股票(红,居中)向四个蓝点放射状输出;箭头粗细即传染强度。这是「一个中心 + 多个外围接收者」的拓扑。
五、连通性会动:滚动 TCI 抓危机#
连通性不是常数。我们每 250 个交易日滚动重算 TCI:
WW = 250
tci = []
for end in range(WW, T):
Ah, Sh = fit_var1(r[end - WW:end])
dd = gfevd(Ah, Sh, H=10)
tci.append((dd.sum() - np.trace(dd)) / N * 100)python
图 3:红带是我们在 DGP 里埋的危机窗口。TCI 从常态区均值 66.9% 飙到峰值 91.2%——危机期资产联动骤升,独立配置的幻觉被打破。这正是 DY 框架最实用的地方:用 TCI 做系统性风险预警。
实跑数字:滚动 TCI 均值 71.0%,危机峰值 91.2%,常态区 66.9%。
六、三个落地用法#
- 系统性风险温度计:把组合里资产的 TCI 做成日更面板。TCI 跳升 = 跨资产联动加剧 = 分散化失效预警,此时应主动降杠杆、加黄金/现金对冲。
- 找真分散:想做「不相关」配置?别只看两两相关系数。用 NET 挑一个 NET 为负的资产(净接收、被动态),它和股票(净输出)的联动在危机里反而可能提供保护。本文中外币/黄金的负 NET 正是这个角色。
- 传染源预警:监测「核心资产 NET 是否持续走高」。当某资产从净接收转为净输出,说明它正变成新的风险策源地(例如某次危机里黄金从避险接收变被动接收),提前调整敞口。
七、四类真实陷阱#
- 滞后阶 p 误设:VAR 阶数决定动态结构。p 太小漏掉长记忆联动,p 太大吃掉自由度、放大估计噪声。实务用 AIC/BIC 选 p,并对 p 做敏感性(1/2/4/8)看 TCI 稳不稳。
- 预测期 H 的取舍:GFEVD 对 H 敏感。H 太短捕获瞬时传染不足,太长把历史都摊进来。DY 原文常用 H=10(日频),但应报告 H=5/10/20 的结果交叉验证。
- 混淆正交化与广义分解:老版 Cholesky 分解结果依赖变量排序(谁在 VAR 里排前面,谁「先动」),换顺序结论会变。本文用 GFEVD 规避,但若你用 Cholesky,务必做排序鲁棒性检验,否则 NET 排序可能是假象。
- 样本期与平稳性:连通性是样本依赖的。只用牛市数据,TCI 会被低估;样本含 08/20/22 危机,TCI 会被高估。且 VAR 对非平稳序列(单位根)会失真——落地前必须做 ADF/PP 检验,必要时用收益率或差分序列。
八、结论#
Diebold-Yilmaz 连通性框架把「风险传染」从 metaphor 变成可算、可画、可监控的指标:
- 结构:VAR(1) + GFEVD 得到连通性矩阵 ,量化「谁冲击解释了谁多少波动」;
- 全局:TCI = 70.8%(本文),是系统性风险体温计,危机期可飙到 91.2%;
- 方向:NET 区分传染源与接收方——本文股票 NET +274.7 是核心策源地,其余均为净接收;
- 动态:滚动 TCI 能抓危机(66.9%→91.2%),是实盘可用的预警线。
但记住四个坑:滞后阶、预测期、正交化排序、样本平稳性——任何一个设错,你画出的「地图」都可能指向错误的传染源。
本文数据均为自洽合成(5 资产 VAR,股票定向驱动 + 危机窗口放大),仅用于演示方法。真实落地时:用 AIC/BIC 选 VAR 滞后阶、对 H 与排序做鲁棒性、先做平稳性检验、并把 TCI 接入日更风险面板。代码已全部跑通,数字即输出。