1. 先搞清楚VAR到底在解决什么问题做时间序列分析的人,大概率都在某个节点被VAR这三个字母拦过路。向量自回归模型(Vector Autoregression)在计量经济学里的地位,差不多相当于回归分析在统计学里的地位——你可以不用,但不能不懂。我第一次真正动手跑VAR,是因为要分析几个宏观指标之间的动态关系:一个变量的变化到底会不会传导到另一个变量?传导需要几期?冲击是短期的还是会持续发酵?这些问题用单方程回归根本答不了,因为单方程只能告诉你X和Y相关,而VAR能告诉你X抖一下,Y在接下来的第1期、第2期、第3期分别会怎么反应。这篇内容我打算把VAR从数据进来到脉冲响应图出来这一整套流程完整走一遍,工具就用Stata。核心关键词会反复出现:平稳性检验、滞后阶数选择、格兰杰因果检验、脉冲响应、方差分解。适合谁看?已经学过一点计量、知道什么是回归、但一打开Stata就不知道第一步该敲什么命令的人;也适合那些跑完var命令、结果出来一堆表格但看不懂、不知道下一步该干什么的人。我默认你手里已经有一份时间序列数据,至少包含3个以上你关心的变量,并且时间跨度在几十期以上——如果只有十几期,老实说VAR不是一个好选择,参数比样本还多,跑出来的结果基本不可信。先说说VAR到底在干嘛。假设你有GDP增长率、通胀率、利率三个变量。VAR的做法是:把每一个变量都写成自己过去若干期的值 其他所有变量过去若干期的值的线性组合。比如GDP的当期值,由GDP的前p期、通胀的前p期、利率的前p期共同解释。三个变量就是三个这样的方程,一起估计。p就是滞后阶数,你自己选。这就是为什么它叫向量——不是一个方程,是一组方程联立;为什么叫自回归——等号右边全是自己的滞后项。这个设定看起来朴素,但它有个巨大的好处:不需要你事先指定谁是因谁是果。单方程回归你必须先假设利率影响GDP,VAR不预设这个方向,它让数据自己说话,把变量之间所有的动态交互都留在模型里。代价是参数多——k个变量、p阶滞后,每个方程有kp1个参数,总共k(kp1)个。三个变量滞后4阶,就是3×(3×41)39个参数。这也是我前面说样本不能太少的根本原因。还有一点必须提前说清楚,这是很多人第一次用VAR最容易误解的地方:VAR的系数本身几乎没有解释价值。你去看估计结果,那一堆系数、标准误、t值,单个系数显著不显著意义不大,因为变量之间高度共线,系数会互相抢解释力。VAR的价值全在系数之外的衍生结果上——格兰杰因果、脉冲响应、方差分解。所以别在系数表上纠结太久,那是给软件看的,不是给你看的。实操前还有两个前置认知要建立。第一,数据必须是平稳的,或者你得先把不平稳的处理掉,否则会出现伪回归,两个毫无关系的变量也能跑出漂亮的显著结果。第二,VAR对滞后阶数非常敏感,阶数选错,后面所有结论都会歪。这两点决定了整套流程的顺序:先检验平稳性 → 不平稳就处理 → 选滞后阶数 → 跑VAR → 做诊断 → 做因果和脉冲响应。顺序不能乱,乱了就是白跑。我见过太多人拿到数据直接var y1 y2 y3, lags(1/4),结果被审稿人或者导师一句你做过单位根检验吗问住。所以下面我按真实操作的顺序,一个环节一个环节往下拆。2. 数据准备与平稳性检验:整条流程的地基2.1 数据导入与格式规整Stata处理时间序列,第一步不是敲模型命令,而是把数据声明成时间序列。这一步做不好,后面所有L.滞后算子、D.差分算子都会报错。假设数据是季度数据,时间变量叫date,格式是2005q1这种。导入之后先做两件事:* 设定时间变量格式并声明为时间序列 gen qdate quarterly(date, YQ) format qdate %tq tsset qdate如果是月度数据就换成monthly()和%tm,年度数据用yearly()和%ty。这里有个坑我踩过:原始数据里的时间列如果是字符串形式的2005-01,直接tsset会报错,必须先转换。转换时注意quarterly()这类函数的第二个参数是输入格式,写错了会静默生成缺失值,而不是报错——等你跑到后面发现样本量莫名其妙少了一大截,回头找半天才发现是这里出了问题。声明完之后用tsset不带参数再敲一次,Stata会回显当前的时间设定,确认一下起点、终点、间隔对不对。如果显示gap之类的提示,说明中间有缺失的时间点,需要tsfill补齐,或者至少心里有数哪些期是断的。变量命名上我建议统一规范,别用中文变量名,也别用var1 var2这种。用有含义的英文缩写,比如gdp、cpi、rate。后面做脉冲响应图的时候,变量名会直接显示在图上,起个能看懂的名字能省掉很多后期改图的麻烦。2.2 单位根检验:ADF的实操细节平稳性检验的标准工具是ADF检验(Augmented Dickey-Fuller)。命令很简单:dfuller gdp, lags(4) trend dfuller cpi, lags(4) dfuller rate, lags(4)但这里面的门道比命令本身多得多。先从最基础的讲起。要不要加trend选项。这取决于你的变量有没有确定性时间趋势。GDP水平值通常有明显上升趋势,要加trend;通胀率、利率、增长率这类通常在0附近波动,不加。判断方法不用猜,画个时序图看一眼就行:tsline gdp cpi rate图上如果变量整体呈斜向上的走势,加trend;如果围绕某个水平线上下波动,不加。这个判断错了会直接影响结论——一个带趋势的序列如果不加trend做ADF,检验会严重偏向不拒绝单位根,你会误判它不平稳。滞后阶数怎么定。lags(4)里的4不是随便写的。ADF检验的回归式里要加入被解释变量差分的滞后项,目的是吸收残差的自相关,让检验统计量的分布成立。滞后太少,残差还有自相关,size distorted,检验不可靠;滞后太多,损失自由度,power下降。常用做法是用信息准则自动选:dfuller gdp, lags(4) trend regress加regress会输出完整的回归结果,你可以看最后一个滞后项的显著性,也可以配合varsoc命令单独判断。实操中最省事的办法是:先跑一遍varsoc(后面会详细讲),看它建议的阶数,ADF就沿用类似阶数。样本不大时,用lags(1)或者根据季度/月度特性选4或12也说得过去,关键是心里要有依据,别随手填。三种检验形式的选择。ADF有三个变体:不带常数项、带常数项、带常数项和趋势项。很多人只记住了加不加trend,忽略了常数项。原则是:先看时序图,序列均值是否为0?显然不为0(利率不会是0均值),所以常数项基本都要带。Stata的dfuller默认带常数项,加trend就是带趋势,不加noconstant就是不带常数。除非你的变量理论上是零均值的(比如某些收益率序列),否则别用noconstant。临界值怎么读。这是新手最容易出错的地方。ADF的检验统计量不服从标准t分布,而服从Dickey-Fuller分布,所以不能拿±1.96去比。Stata输出里会直接给出1%、5%、10%三个临界值,你只需要看自己的统计量是不是小于(注意是小于,因为是左尾检验)临界值。小于5%临界值就在5%水平上拒绝单位根,认为序列平稳。原假设是存在单位根,这一点务必记牢。拒绝原假设 平稳;不拒绝 不平稳。很多人把方向搞反,看到p值大就说平稳,完全颠倒。我习惯把三个变量的检验结果整理成一张表,自己看着清楚,写报告时也直接能用:变量检验形式滞后阶数ADF统计量5%临界值结论gdp含趋势4-1.87-3.41不平稳cpi含常数4-2.65-2.86不平稳rate含常数4-1.42-2.86不平稳d.gdp含常数3-5.23-2.86平稳d.cpi含常数3-3.98-2.86平稳d.rate含常数3-4.51-2.86平稳注意表里对差分后的变量重新做了检验,而且检验形式变了——差分后的序列一般不再需要trend,因为趋势被差分掉了。这个细节很多人漏掉,拿着带trend的设定去检验差分序列,结果又是不平稳,然后怀疑人生。2.3 不平稳了怎么办:差分还是协整检验出来不平稳,有两条路。第一条:差分。全部一阶差分,用D.前缀:gen dgdp D.gdp gen dcpi D.cpi gen drate D.rate差分后的序列通常就平稳了,然后对差分序列建VAR。这是最稳妥、最不容易出错的做法。代价是丢掉水平值里的长期信息,模型解释的是变化率的变化,而不是水平值的变化。如果你的研究问题关心的是短期波动传导,差分完全可以接受。第二条:协整。如果多个不平稳序列之间存在长期均衡关系(比如它们同步漂移,价差稳定),直接差分会丢掉这个信息,这时候应该用VECM(向量误差修正模型)。判断有没有协整,用Johansen检验:vecrank gdp cpi rate, lags(4) trend(constant)这个命令会输出迹统计量和最大特征值统计量,配合临界值判断协整秩。如果秩为0,说明没有协整关系,回到差分VAR;如果秩≥1,就该用VECM。VECM在Stata里用vec命令,设定比VAR复杂,但脉冲响应的操作逻辑是类似的。我个人的经验是:新手阶段先把差分VAR跑通、跑明白,协整和VECM留到有明确理论支撑、样本量足够的时候再上。因为协整检验对滞后阶数、趋势设定、样本区间都非常敏感,稍微换个设定结论就变,很容易把自己绕进去。而且差分VAR的结论通常已经足够回答大部分冲击如何传导的问题。注意:如果做完差分还有变量不平稳,不要急着做二阶差分。先回头检查数据本身——有没有异常值、口径变化、断点。二阶差分在实际经济数据里很少有必要,多数时候是数据质量问题伪装成了非平稳。3. 滞后阶数选择:一个决定全局的参数3.1 信息准则怎么用滞后阶数p是VAR里最重要的一个主观选择。选小了,模型吸收不了真实的动态关系,残差有自相关,脉冲响应会有偏;选大了,参数爆炸,自由度不够,估计不准。标准做法是用信息准则:varsoc gdp cpi rate, maxlag(8)maxlag(8)表示在1到8阶里比较。Stata会输出一张表,包含AIC、SBIC(也叫SC/BIC)、HQIC,每个准则下用*标出最小值所在的行。通常取多数准则共同指向的那个阶数。这里必须提醒:SBIC和AIC经常打架。SBIC惩罚力度大,倾向选小阶数;AIC惩罚轻,倾向选大阶数。我的处理原则是:样本量充足(比如几百期)时优先看SBIC,它的一致性更好;样本量偏小时看AIC和HQIC,避免过度惩罚导致模型欠拟合。如果两个准则相差2阶以上,说明数据结构本身模糊,这时候两个都跑一下,看后续脉冲响应是否稳健——稳健就用小的那个,不稳健就得在报告里说明并做敏感性分析。maxlag的上限怎么定?一个经验法则是不要超过样本量的立方根,季度数据一般不超过8,月度不超过12,年度不超过4。另外要留够自由度:每个方程的参数是kp1,如果k3、p8,就是25个参数,你的样本至少得有它的5倍以上才比较踏实。3.2 残差诊断与阶数复核信息准则只是参考,最终还得看残差。VAR的一个核心假设是残差是白噪声——无自相关、同方差、正态。有自相关说明模型没吸收干净,阶数不够;有异方差或非正态虽然不影响系数的一致性,但会影响推断。检验残差自相关用LM检验:var gdp cpi rate, lags(1/4) varlmarvarlmar会逐阶检验残差是否存在自相关。理想结果是从第1阶到第p阶都不拒绝(也就是没有残余自相关)。如果第1阶就拒绝,说明4阶不够,得加。注意一个细节:varlmar默认检验到滞后1阶,要检验更多阶需要加选项,比如varlmar, mlag(8)。正态性检验:varnorm这个检验原假设是残差服从多元正态。实际数据尤其是金融数据,残差经常显著非正态(尖峰厚尾)。这时候不用慌,系数的估计仍然一致,脉冲响应的点估计也基本可靠,只是置信区间可能不准。可以在报告里注明,或者用bootstrap方法构造脉冲响应的置信区间(后面会讲)。稳定性条件也顺便检查一下:varstable, graphVAR稳定的条件是所有特征值的模小于1,也就是都落在单位圆内。Stata会输出一张表和一个单位圆图。如果有特征值在圆上或圆外,模型不稳定,脉冲响应会发散,后面所有结论都不可信。这种情况通常是阶数太高、变量间存在近似共整、或者样本区间有结构性断点。心得:我一般会做一个阶数阶梯的对比——把p2、3、4各跑一遍,分别看varlmar结果和varstable的模最大值。选那个残差自相关最干净、特征值离单位圆边界最远的阶数,而不是机械地按信息准则的最小值。这一步多花十分钟,能省掉后面反复返工的时间。4. VAR估计与格兰杰因果:先看变量之间有没有先后4.1 跑出基准模型阶数定了,模型就跑:var gdp cpi rate, lags(1/4)如果想在估计后继续做脉冲响应、方差分解,建议在var命令后面直接接上irf create,把结果存成一个IRF文件,或者干脆用var之后再详细操作。估计完成会输出三张系数表(每个变量一张),前面说过,系数本身别过度解读。需要看的一个指标是每个方程的整体拟合和R方,还有一个容易被忽略的——模型整体的对数似然和参数个数,这两项在做似然比检验和变量取舍时会用到。4.2 格兰杰因果检验的正确理解格兰杰因果检验是VAR最常见的衍生应用,命令是:vargranger它会输出一张表,列出某个变量是否是另一个变量的格兰杰原因,配合卡方统计量和p值。这里必须讲清楚它的含义,因为误用太普遍了。格兰杰因果的原假设是:变量X的滞后项对预测Y没有帮助,在Y的方程中系数全为0。拒绝原假设,只能说X的过去信息有助于预测Y,不能说X是Y的原因在因果推断意义上。它测的是可预测性,不是因果性。一个经典的反例:夏天冰淇淋销量和溺水人数高度格兰杰相关,因为共同受气温驱动,谁也不是谁的原因。所以做这个检验一定要有理论支撑,知道为什么这两个变量之间可能存在先后关系,否则很容易得出漂亮但无意义的结论。另一个细节:vargranger是对模型中所有变量两两之间都做检验,看结果时要按行按列对应清楚,别把方向搞反。行是结果变量,列是检验变量——Y不是X的格兰杰原因和X不是Y的格兰杰原因是两张完全不同的原假设。如果只想检验部分变量,可以用test命令手动写约束:* 检验 cpi 和 rate 的滞后项在 gdp 方程中是否联合为0 test [gdp]L.cpi [gdp]L2.cpi [gdp]L3.cpi [gdp]L4.cpi这种写法更灵活,能只看某一个变量、某一阶的系数。5. 脉冲响应与方差分解:VAR真正有价值的部分5.1 脉冲响应的原理与正交化脉冲响应函数(IRF)回答的是:给某个变量一个标准差大小的冲击,其他变量在未来各期会如何反应。这是VAR最核心的输出,但也是坑最深的地方。先说原理。VAR估计出系数之后,可以转成移动平均(MA)形式,冲击的传导路径就体现在MA系数上。但原始的冲击之间是相关的(残差的协方差矩阵非对角),一个变量抖,另一个变量同时也在抖,你没法把它们的效应分开。所以要做正交化——用Cholesky分解把相关冲击变成互相独立的冲击。关键来了:Cholesky分解是有顺序的,顺序决定了谁当期可以对谁有影响。变量排序靠前的,当期只受自身冲击影响;排序靠后的,当期能受到前面所有变量冲击的影响。换句话说,当年的因果方向是被你的排序假设决定的,不是数据决定的。这就是为什么变量排序不能随便敲。排序依据是经济学理论或制度性事实。比如研究货币政策,利率是政策变量,它对产出和通胀的反应有滞后(政策制定需要看数据),但产出和通胀对利率冲击可以当期响应。所以合理的顺序是:产出 → 通胀 → 利率,利率放最后。反过来排就会得出利率当期不影响产出的荒谬结论。实操建议:主要结论用一套有理论依据的排序,然后换几种排序做敏感性分析。如果不同排序下结论方向一致、只是幅度略变,说明结论稳健;如果换个顺序结论就反了,那就别硬下结论,老老实实承认结果对识别假设敏感。命令:irf create myirf, step(12) set(myresults) replace irf graph irf, impulse(gdp cpi rate) response(gdp cpi rate) /// yline(0) xlabel(0(2)12)step(12)表示看12期(季度数据就是3年),set()是保存IRF结果的文件名。irf graph画出图,yline(0)加一条0线方便看清正负,xlabel控制横轴刻度。5.2 置信区间的两种做法脉冲响应的点估计往往不够,必须有置信区间。Stata默认用渐近解析式(基于delta方法),命令加选项即可:irf graph irf, impulse(gdp) response(cpi) ci但前面提过,残差非正态或样本不大时,渐近方法可能不准。更稳妥的是bootstrap:irf create myirf_bs, step(12) set(bootstrap) replace /// boot rep(500) seed(12345)rep(500)是重复次数,bootstrap这类抽样方法一般不少于500次,1000次更稳。seed固定随机种子,保证结果可复现——这一点很重要,不固定种子的话,每次跑出来的置信区间都不一样,读者没法复现你的结果。bootstrap会明显更慢,几百次重复可能要跑几分钟到十几分钟。我的做法是:正式结果用bootstrap,探索阶段用渐近方法快速看方向。另外,bootstrap的置信区间可能不对称,甚至在某些期出现上下界都同号但点估计靠近0的怪象,这是正常的,说明该期效应不稳定。5.3 方差分解:谁的波动贡献大方差分解回答另一个问题:某个变量在未来第h期的预测误差方差,有多少比例来自它自己,多少来自其他变量。命令:irf table fevd, step(12)输出一张表,行是响应变量,列是冲击来源,值就是百分比贡献。这个结果在解释谁主导时特别直观。解读要点:第1期的方差分解基本由排序决定(和脉冲响应同理),重点看第6期、第12期这种中长期的贡献结构。如果某个变量的预测误差方差有70%来自另一个变量,说明后者对前者有实质性影响。反过来说,如果长期下来大部分方差还是由自身解释,那这个变量相对独立。一个常见的误读是把方差分解当成因果强度。它本质上是预测信息的贡献比例,还是那句话,不是因果。另外,方差分解对变量排序同样敏感,尤其是第1期,所以还是那套老规矩:换排序做稳健性。5.4 结果整理与呈现脉冲响应和方差分解做完,图会有一大堆(3个变量×3个冲击9张图)。我的整理习惯是:脉冲响应只画与研究问题直接相关的那几张。比如关心利率冲击对产出的影响,就画那一张,其余放附录。每张图标注清楚冲击变量、响应变量、期数、置信区间水平。方差分解用表格,只报第1、4、8、12期几个关键时点,不用把每一期都列出来。图的格式建议用scheme(s2color)或者自己设一个统一的配色,几篇论文里的图风格一致,看起来专业。另外irf graph支持byopts分组,可以把多张图排成矩阵,但要注意变量多了图会挤,信息反而看不清。6. 实操中的典型问题与排查清单6.1 报错与异常速查跑VAR这套流程,报错和异常结果的类型其实很集中。我按出现频率整理成一张表,遇到问题先查这张表:现象可能原因排查与解决tsset报错time variable not regularly spaced时间点有缺失或重复用duplicates list查重,tsfill补齐,或确认数据本身是不是非等间隔样本量突然变少滞后项吃掉了前面若干期;某变量有缺失值summarize看各变量观测数;tsfill后确认gapvarstable显示有特征值模≥1阶数过高;变量近似共整;结构断点降阶重试;检查变量相关性;做断点检验varlmar第1阶就显著滞后阶数不足加阶;检查是否有遗漏变量脉冲响应发散、置信区间无限扩大模型不稳定回查varstable;降阶或差分vecrank结论与理论不符趋势设定错误;滞后阶数不对试trend(none)、trend(rconstant)等不同设定bootstrap跑半小时没动静重复次数过高或变量过多降到500次;减少step();用nodots关掉进度输出6.2 几个容易踩的坑坑一:用水平值直接跑VAR,不做检验。这是最普遍也最致命的问题。两个独立的随机游走,回归的R方能到0.8,系数高度显著,这就是伪回归。VAR里同样存在,而且因为变量多、参数多,伪回归的表现更隐蔽——脉冲响应看起来有传导,其实是两个独立趋势碰巧同向。所以平稳性检验不是走形式,是必须做的第一道闸。坑二:变量顺序随手写。前面反复强调了,再强调一次:Cholesky分解的排序是有经济含义的假设。写报告时必须明确说明排序依据,最好附上敏感性分析。审稿人和导师最爱问这个。坑三:忽略了滞后阶数对结论的影响。阶数从4改成3,脉冲响应的形状可能就变了。稳健的做法是把p和p±1都跑一下,核心结论不变才敢写。我在实际项目里养成的习惯是:定稿前把关键结果在至少两组设定下复现一遍,一组是信息准则推荐的,一组是相邻阶数。坑四:把格兰杰因果当因果结论写。这个前面说过,但值得再提。规范的表述是X的滞后项对Y有显著的预测信息,而不是X导致Y。如果研究问题确实需要因果识别,得用工具变量、双重差分、断点回归这些方法,VAR提供不了。坑五:bootstrap不设种子。小问题但很烦人——结果没法复现,自己隔几天重跑都跟之前不一样,更别说给别人了。坑六:样本区间有政策或口径变化,没做处理。比如某年统计口径调整,数据在那一期出现跳变。这种断点会让模型不稳定,脉冲响应失真。处理办法:要么把断点前后分开估计,要么加入虚拟变量(需在var外手动处理,或改用其他方法),要么缩短样本区间避开。至少要画个时序图,肉眼扫一遍有没有明显的断点。6.3 一份可以直接照抄的操作清单把整套流程压缩成一份顺序清单,方便对照执行:导入数据,tsset声明时间变量,确认无gap、无重复。tsline画时序图,判断趋势和断点。对每个变量做ADF检验,记录检验形式、滞后阶数、统计量、结论。不平稳的做一阶差分,对差分序列重新检验,确认平稳。varsoc在合理范围内选滞后阶数,结合varlmar、varstable复核。var估计,vargranger看变量间预测关系。irf create保存正交化脉冲响应,bootstrap构造置信区间。irf graph画核心图,irf table fevd做方差分解。换变量排序、换阶数,做敏感性分析。结果整理成表和图,写清楚每一步的设定和依据。这套流程走下来,一份完整的VAR分析就成形了。真正耗时的不是敲命令,而是每个环节的判断和复核——平稳性检验的设定、阶数的取舍、排序的依据、结论的稳健性。命令一共就那么十几个,但每个背后的判断,才是区分跑完了和跑对了的地方。我个人在实际操作中的体会是:VAR这类多变量时间序列模型,最怕的不是算不出来,而是算出来之后不知道结果可不可信。所以每次出图之前,我都会强迫自己回答三个问题——模型稳不稳?排序有没有依据?结论换个设定还在不在?这三个问题都能答上来,结果才敢往外放。