第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.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最忌讳的就是“为了识别而识别”——随便找个约束就往上套。你想想看,如果约束本身没有经济含义,那得到的“结构性冲击”也不过是披着因果外衣的相关性罢了。
好了,这一章就到这里。下一章咱们聊聊永久冲击与临时冲击的区别——这可是区分短期波动和长期趋势的关键。