第1章:SVAR模型——通过约束识别结构性冲击

大家好,我是你们的老朋友。今天咱们聊聊SVAR模型。

说实话,我刚入行那会儿,看到“结构向量自回归”这几个字,第一反应是——这玩意儿是不是又得背一堆数学公式?后来做项目做多了才发现,SVAR说白了就是帮我们回答一个核心问题:经济变量之间的波动,到底是谁先动的手?

1.1 为什么需要SVAR?

咱们先想想,传统的VAR模型能干啥?它能告诉我们,GDP和利率之间有没有关系,能画出脉冲响应图。但有个致命问题——它分不清“相关”和“因果”

举个例子。你看到GDP上升的同时利率也上升。这是央行主动加息抑制过热?还是经济扩张导致利率自然走高?VAR模型只能告诉你“它们一起动了”,但说不清谁是谁的因。

我2018年做过一个货币政策分析项目,当时用普通VAR跑出来的结果,领导看了直摇头:“你这图告诉我利率冲击影响GDP,但万一利率是被GDP拉起来的呢?”嗯,这就是内生性问题。SVAR就是来解决这个的。

核心思想:SVAR通过施加经济理论约束,把“纯统计关系”变成“有因果含义的结构关系”。

1.2 从VAR到SVAR:一个关键转变

咱们先看标准VAR长什么样:

Y_t = A1*Y_{t-1} + A2*Y_{t-2} + ... + Ap*Y_{t-p} + e_t

这里的e_t是简化式残差——它只是预测误差,没有经济含义。你没法说“e_t里有多少是货币政策冲击,多少是技术冲击”。

SVAR要做的事,就是把这个e_t拆开:

e_t = B * ε_t

其中ε_t才是我们真正想要的结构性冲击,比如:

  • ε_1 = 货币政策冲击
  • ε_2 = 技术冲击
  • ε_3 = 需求冲击

B矩阵就是冲击传导矩阵,它告诉我们每个结构性冲击是如何影响各个变量的。

我的经验:很多初学者搞不清e_t和ε_t的区别。我习惯这么记——e_t是“果”,ε_t是“因”。我们观测到的波动是果,背后真正的驱动力是因。

1.3 识别问题:你凭什么说这是结构性冲击?

这里有个大坑。你想想看,e_t是N维向量,ε_t也是N维向量。从数学上讲,有无穷多种B矩阵能把e_t拆成ε_t。你凭什么说你找到的那个B是对的?

这就是识别问题。说白了,我们需要给B矩阵施加约束,让它唯一确定。

常见的约束方式有三种:

约束类型 做法 典型例子
短期约束 假设某些冲击在当期不影响某些变量 货币政策冲击不影响GDP(当期)
长期约束 假设某些冲击的长期累积效应为零 货币冲击长期不影响实际产出
符号约束 限制冲击响应的方向 紧缩货币政策→利率上升、产出下降

我个人最常用的是短期约束,因为直觉上比较好理解。比如我做一个三变量系统(GDP、通胀、利率),我会假设:

  • 利率冲击在当期不影响GDP(政策传导需要时间)
  • 通胀冲击在当期不影响利率(央行反应有滞后)

这样B矩阵里就有几个位置被固定为0,剩下的就可以估计了。

避坑指南:我曾经在一个项目里用了过于严格的短期约束,结果脉冲响应图出现了“先正后负”的诡异形状。后来发现是约束条件与经济理论冲突——你假设货币政策不影响GDP,但数据告诉你它确实影响。所以,约束一定要有理论依据,不能为了识别而识别。

1.4 一个简单的SVAR流程图

下面这张图是我自己总结的SVAR分析流程,每次做项目前我都会看一眼,防止漏步骤:

1. 数据准备 2. 估计简化式VAR 3. 施加约束 4. 识别B矩阵 5. 计算脉冲响应 6. 方差分解 7. 经济解释与稳健性检验 核心: 约束条件决定 冲击的因果含义

1.5 实操中的两个关键点

第一,滞后阶数的选择。我习惯用AIC或BIC准则,但别完全依赖统计量。有一次我跑月度数据,AIC建议12阶,结果模型参数多到爆炸,估计出来的脉冲响应全是噪声。后来我改成6阶,效果反而更好。记住:经济直觉比统计准则更重要

第二,约束的过度识别检验。如果你施加的约束比刚好识别需要的多,就可以检验这些约束是否被数据拒绝。我一般会报告这个检验的p值——如果p值小于0.1,说明你的约束可能有问题。

一个小技巧:做SVAR之前,先跑一个普通VAR看看残差的相关性。如果残差之间相关性很低,说明变量之间已经比较“独立”,这时候SVAR的识别会容易很多。反之,如果残差高度相关,那你得小心了——可能漏掉了某个重要变量。

1.6 一个简单的代码示例(R语言)

下面是我常用的SVAR估计代码片段,用的是vars包:

library(vars)

# 1. 估计VAR
data <- cbind(gdp, inflation, rate)
var_model <- VAR(data, p = 4, type = "const")

# 2. 施加短期约束(Cholesky分解)
# 假设变量顺序:GDP → 通胀 → 利率
# 即:GDP冲击影响所有变量,通胀冲击不影响GDP,利率冲击不影响GDP和通胀
amat <- diag(3)
amat[1, 2] <- 0  # 通胀冲击不影响GDP
amat[1, 3] <- 0  # 利率冲击不影响GDP
amat[2, 3] <- 0  # 利率冲击不影响通胀

svar_model <- SVAR(var_model, Amat = amat, Bmat = NULL)

# 3. 脉冲响应
irf_result <- irf(svar_model, n.ahead = 20)
plot(irf_result)

这段代码里,我用了递归识别(Cholesky分解)。说白了就是给变量排个序,排在前面的变量在当期不受后面变量的影响。这个排序很关键——我见过有人把利率放在GDP前面,结果脉冲响应完全反了。

注意:Cholesky分解对变量顺序非常敏感。我建议你至少尝试2-3种不同的排序,看看结果是否稳健。如果不同排序下结论差异很大,那说明你的识别策略可能有问题。

1.7 小结

SVAR模型的核心,就是通过约束把“统计残差”变成“结构性冲击”。这个过程需要经济理论的指导,也需要你对数据有足够的了解。

我个人觉得,做SVAR最忌讳的就是“为了识别而识别”——随便找个约束就往上套。你想想看,如果约束本身没有经济含义,那得到的“结构性冲击”也不过是披着因果外衣的相关性罢了。

好了,这一章就到这里。下一章咱们聊聊永久冲击与临时冲击的区别——这可是区分短期波动和长期趋势的关键。