做宏观金融实证研究的人,应该都见过这类标题:金融周期、房地产价格、时变冲击,挂在《金融研究》这类中文顶刊上,看着很有距离感。但真正动手复现过一次就会发现,论文正文里只有三五张图和几张表,背后却是一整套从数据对齐、指数构建、模型估计到结果解读的完整流程。这篇博文就把我完整复现的过程记录下来,从论文逻辑拆解到Matlab代码实战,尽量讲清楚每一步在做什么、为什么这么做、有哪些隐藏的坑,给你一条可以直接参考的复现路线。
我不是经济学理论方向的,做这块纯粹是因为研究需要,所以这篇复现笔记更偏实操——不纠结公式推导,重点在于把“金融周期影响房地产价格”这条因果链条在Matlab里真正跑通。无论你是正在找选题的研究生,还是需要验证自己判断的从业者,这篇内容都应该能帮你省掉不少摸索时间。
1. 论文到底在研究什么:复现前的逻辑拆解
很多人在复现之前就急着找数据、跑代码,结果模型估计出来一团乱麻,根本不知道自己跑出来的是什么。我建议先花一天时间把论文的“骨架”拆出来,搞清楚作者为什么这么设计、每一步在回答什么问题。
1.1 为什么金融周期会对房价产生冲击
房地产价格是典型的资产价格,它不只看当下的供需,还受到融资环境、信贷可得性、利率水平这些金融变量的强烈影响。论文的核心逻辑链条可以概括成:金融周期扩张阶段,银行信贷投放加快、融资成本下降,购房需求被激发,资金涌入楼市推高房价;金融周期收缩阶段,信贷收紧、流动性下降,房产作为高杠杆资产首当其冲,价格面临下行压力。
这条链条在现实中有一个很直观的放大效应:房子本身是抵押品,房价上涨时抵押品价值上升,银行更愿意放贷,钱又流向房地产,进一步推高房价。这就是金融加速器效应。论文要做的事情不是简单说“房价和金融周期有关”,而是用计量方法把这种关系动态地、时变地展示出来——不同时期,金融周期对房价的冲击强度可能完全不同。
1.2 论文的实证设计:从相关关系到动态因果
一般的回归只能得到“金融周期对房价有正向影响”这种平均意义上的结论,但顶刊论文不会满足于此。它关心的是:这种影响在不同历史阶段是否稳定?在金融周期的高潮期和低谷期,冲击传导路径是否有差异?短期冲击和长期影响又有什么不同?
所以论文采用向量自回归框架,尤其是带时变参数的VAR模型。传统VAR假设变量之间的关系在整个样本期内保持不变,但金融体系这些年经历了多轮扩张和收缩,变量关系显然不稳定。时变参数模型放开这个假设,允许系数随时间和经济状态变化,这才能捕捉“金融周期->房价”传导的动态特征。这部分是复现的关键,也是Matlab代码中最重的部分。
1.3 复现前必须想清楚的三件事
第一,顶刊复现不等于逐字还原。论文作者未必公开全部数据和代码,你的数据口径、样本区间选择都可能与原文有差异,追求的是“结果方向一致、统计特征可对照”,不是数字完全一样。
第二,分清主模型和辅助模型。有的论文用简单VAR做基准回归,再用TVP-VAR做核心发现,最后加稳健性检验。复现时先把主模型的输出跑出来,再去处理辅助部分,不然工作量会失控。
第三,准备好心理预期。这类模型涉及贝叶斯估计,MCMC迭代需要时间,代码报错率也高。Matlab里跑一次完整估计可能得几个小时。我复现时从白天调到天黑都不出结果的情况不少,遇到这种问题别硬刚,先跑一个缩小的样本验证逻辑,再上完整样本。
2. 数据从哪里来、怎么处理:复现的地基工程
数据是复现项目里最不起眼但最致命的部分。我见过不少人在模型环节反复调试,结果问题出在数据没对齐、缺失值处理粗暴、频率不统一这些“低级错误”上。
2.1 核心变量怎么选:金融周期与房地产价格的代理指标
金融周期在文献里没有统一度量,一般思路是用信贷类变量作为核心代理。常见的做法是用“信贷/国内生产总值”比值的周期成分来代表金融周期,也有用社融存量增速、广义信贷增速等指标组合合成的。想要更全面一点,可以把信贷增速、货币增速、利率水平放一起做主成分分析,提取第一个主成分作为综合金融周期指数。
房地产价格的数据选择很关键。宏观层面常用的有百城住宅价格指数、70个大中城市新建住宅价格指数,两者都公布月度同比或环比数据。做实证时我更推荐用经过指数化处理的价格序列,而不是直接用绝对房价,因为绝对房价有趋势和区域差异,直接进模型容易出问题。
我这次复现采用的标准配置是:金融周期用“信贷/国内生产总值季度比值+利率水平”,房价用百城住宅价格指数的对数序列;样本区间选在2005年到2023年,差不多覆盖了金融周期的高峰和低谷,能保证时变模型有足够的变异来识别参数。
2.2 数据预处理:频率对齐、季节调整和缺失值处理
数据频率不一致是第一个要解决的问题。房价指数是月度数据,信贷和GDP是季度数据,处理方式有两种:一种是把月度房价取季末值或者季度平均值,统一转成季度数据;另一种是把季度数据用插值法扩展到月度。实证研究中季度数据更稳健,因为金融周期本身是低频现象,转成季度数据能减少噪音。我做月度转季度时比较过季末取值和季度均值两种方法,结果对模型方向没有实质影响,但对脉冲响应的幅度有一些影响,比较在意稳定性的建议用季度均值。
季节性调整也很重要。经济数据尤其是信贷和房地产销售,往往有很强的季节性,不调整的话模型会把这些周期性波动误当成金融周期信号。Matlab里可以用deseasonalise函数,或者直接写X-13ARIMA-SEATS的调用,简单点也可以用移动平均法做个粗略调整,但稳健性不如官方算法。
缺失值处理没有统一法则。如果只是某个月份缺失,一般用前后月平均或者线性插值补齐;如果某段区间连续缺失,就别硬补了,直接缩短样本区间更稳妥。这里切忌用零填充,会让模型误判数据特征。
2.3 金融周期变量的三种构建方式与选择建议
第一种是单变量滤波法,最常用的是HP滤波,把“信贷/GDP”序列分解成趋势项和周期项,周期项就代表金融周期。季度数据lambda参数取1600,月度数据取14400,这是经验约定。优点是简单直观,缺点是HP滤波两端存在边界漂移,样本起始阶段的周期成分不可靠。
第二种是多变量主成分法,把信贷增速、广义货币增速、利率水平等指标标准化后做主成分分析,第一主成分作为综合金融周期指数。这种方法能综合多个维度的金融状态,稳健性更好。Matlab的pca函数一行就能调用,但主成分的解释命名没有单变量法那么直观。
第三种是转折点法,借鉴商业周期测度方法,识别金融周期的波峰和波谷,构建“扩张/收缩”的虚拟变量。这类变量更适合做分组分析或者机制检验,不太适合直接进入VAR模型。
我的建议是主模型里用第一种或第二种构造连续变量,第三种作为稳健性检验的替代口径。这样既保持主结果的可解释性,又展示了结论对周期度量方式不敏感。
3. 建模思路与Matlab实现:从传统VAR到时变参数模型
模型部分是整个复现项目的核心。我的做法是分三步走:先跑一个传统VAR建立基准,再用滚动窗口VAR做个初步的时变观察,最后上完整的TVP-VAR模型。每一步都有验证价值,也能帮助定位问题。
3.1 为什么不能只用普通回归:VAR模型的优势
普通回归的问题是内生性严重:金融周期影响房价的同时,房价也会反过来影响信贷和金融条件。单方程回归很难说清楚谁是因谁是果。VAR模型把所有变量都当作内生变量,通过变量间的动态互动来刻画系统,不事先强加因果方向,由数据说话。脉冲响应函数还能展示某个变量受到一单位标准冲击后,其他变量在随后若干期内的响应路径。
Matlab里Econometrics Toolbox直接支持VAR模型,几行代码就能估计。但要注意VAR模型是线性、常系数的,它只能给出样本期的平均影响,无法回答“不同时期影响是否相同”这个论文的核心问题。所以基准用VAR,核心发现看TVP-VAR。
3.2 平稳性检验与滞后阶数选择:动手写代码前的两个检查
VAR模型要求变量平稳或者协整。金融周期成分经过滤波后一般是平稳的,房价我做了对数差分,用价格“增速”或“周期”成分进入模型,而不是原始价格水平。进入模型之前用ADF检验确认:Matlab的adftest函数直接可以输出检验结果,p值小于0.05就说明序列平稳。
滞后阶数的选择我用信息准则判断。aicbic函数可以计算AIC和BIC,选两者中建议的滞后阶数,一般季度数据选到4阶就够,太高的阶数会消耗自由度。我这次试了1到4阶,AIC指向4阶,BIC指向2阶,这种不一致很正常——AIC倾向选择更复杂的模型,BIC更吝啬。我采用BIC的结果,模型更简洁,参数估计更稳定。
3.3 TVP-VAR估计框架:随机游走状态方程和MCMC抽样
TVP-VAR的核心思想是允许回归系数随时间变化。通常假设系数服从随机游走过程,也就是说今天的系数等于昨天的系数加上一个随机扰动。这个设定给了模型足够的灵活性,让系数能缓慢漂移,捕捉结构性变化。
模型估计用贝叶斯MCMC方法完成。原因是时变参数模型的对数似然函数很复杂,传统最大似然方法很难直接求解,MCMC通过反复抽样来逼近参数的后验分布。具体到Matlab实现,Primiceri(2005)和Nakajima(2011)的经典程序基本是标配框架,核心MCMC循环大致包含几个步骤。
MCMC的第一步是初始化所有参数和超参数。第二步是进入大循环,依次从条件后验分布中抽取状态变量(时变系数、联立参数、随机波动率)和超参数。第三步是舍弃前一部分抽样作为预烧期,让马尔可夫链收敛到目标后验分布。第四步是用剩余的抽样结果计算后验均值和区间,作为参数估计和不确定性度量。
% TVP-VAR MCMC 核心骨架(简化示意,非完整可运行代码) % y: T×n 数据矩阵 % nsim: 抽样次数, nburn: 预烧次数 % 设定先验 prior_beta = 0; prior_Vbeta = 10 * eye(k); % 初始化参数 beta = zeros(k, T); alpha = zeros(size(A_init)); h = log(sigma2_init); for iter = 1:nsim % 第1步:给定 alpha, h, 超参数,抽样 beta(使用状态空间平滑) beta = draw_beta(y, beta, alpha, h, prior_beta, prior_Vbeta, Q_beta); % 第2步:给定 beta, h, 超参数,抽样 alpha(联立参数矩阵) alpha = draw_alpha(y, beta, h, prior_alpha, W_alpha); % 第3步:给定 beta, alpha, 超参数,抽样 h(随机波动率) h = draw_stochastic_volatility(y, beta, alpha, prior_h, sigma_h); % 第4步:抽样超参数 Q, W, sigma_h [Q_beta, W_alpha, sigma_h] = draw_hyperparameters(beta, alpha, h); % 记录抽样结果(跳过预烧期) if iter > nburn save_results(beta, alpha, h, iter); end end这段代码只是框架示意,实际实现中条件后验分布的形式和抽样方法有很多细节。比如状态变量通常用模拟平滑方法抽取,随机波动率的抽样需要用到多移动步长算法。工程上我更推荐直接使用Nakajima提供的完整Matlab代码包,在其基础上改数据和变量名,比从零写要快得多。
3.4 参数设置与实际计算:迭代次数、预烧期和收敛判断
MCMC参数设置直接影响结果可靠性。我这次设置的抽样次数是两万次,预烧期两千次。这个规模跑下来需要不少时间——四变量、四阶滞后的TVP-VAR,在普通笔记本上大约要跑两三个小时。如果数据量更大,建议把抽样次数降到一万次,先跑通流程再增加。
判断模型是否收敛,有两条经验:一是看关键参数的轨迹图和自相关图,轨迹图应该像白噪音一样上下波动,没有明显的趋势性漂移;二是看后验分布是否稳定,用不同随机数种子跑两次,结果差异不应太大。Matlab里可以用autocorr函数检查参数的序列自相关,自相关衰减太慢表明抽样效率低,可能需要对参数进行稀疏抽样或者重新参数化。
注意:MCMC结果对随机数种子敏感,正式复现时务必设置固定的随机数种子(比如
rng(42)),保证结果可复现。我一般会同时跑两个种子对比,确认结论一致才写进报告。
4. 实证结果怎么读:脉冲响应、时变特征与现实含义
代码跑通只是第一步,更难的环节是从模型输出中提炼出论文级别的结论。很多人拿到TVP-VAR的估计结果不知道怎么看,我得说这部分是有套路可循的。
4.1 脉冲响应函数:从一单位冲击看房价的动态反应
脉冲响应函数是解读VAR模型的核心工具。它回答的问题是:给金融周期一个标准差的冲击,房价在未来若干个季度内如何反应?传统VAR输出的是期限内所有期的响应点,时变模型输出的则是“不同时间点的脉冲响应”——也就是说,同样一个金融周期冲击,发生在2009年、2015年和2022年,对房价的影响幅度和路径可能完全不同。
Matlab里计算时变脉冲响应的方式比较绕。传统VAR的irf函数可以直接调用,但TVP-VAR因为系数逐期变化,脉冲响应也要逐期算:在每个时间点上,取出当时的VAR系数矩阵,计算相应的脉冲响应序列,最后把所有时间的响应画在同一个三维图或者热力图上。
4.2 金融周期冲击的传导路径:为什么有时强烈、有时微弱
从复现结果来看,金融周期对房价的冲击表现出明显的状态依赖特征。金融体系扩张期,信贷条件和利率对房价的传导更强,脉冲响应的峰值更大、消退更慢;而在金融收缩阶段,一单位金融冲击对房价的边际影响相对有限,房价表现出更强的内生惯性。
这种差异在机制上说得通。扩张期大家的杠杆率普遍上升,对利率和信贷条件更敏感,一有宽松信号,资金会加速流入房地产。收缩期房价预期转弱、投资需求退潮,交易量对金融条件的弹性下降,金融冲击向房价的传导被削弱。论文用这种时变特征来论证金融周期与房价的关系存在“非线性”和“放大机制”,复现出来之后能明显看到这些特征,会很有成就感。
4.3 稳健性检验:换变量、换区间、换模型口径
顶刊论文必然有稳健性检验,这部分也是复现不可或缺的。常见的做法有三种:一是换金融周期度量方式,把信贷与GDP比值换成广义信贷增速或者主成分综合指数;二是缩短和延长样本区间,考察核心结果是否区制依赖;三是换模型设定,用带随机波动率或者不同滞后阶数的模型比较结果。
我在复现时重点做了第一种和第二种。换变量后脉冲响应的方向不变,幅度略有偏差;缩短到最近的样本区间(比如2015年以来)后,金融周期对房价的冲击强度显著变大,这与样本期内金融深化和杠杆率上升的事实相符。稳健性检验的价值就在这里:它不是走过场,而是帮你检验核心结论是否“捏得住”。
5. 复现过程中的坑和排查技巧
这一节是我最想分享的内容。代码报错只是小问题,真正消耗时间的是那种“跑完了但结果不对”的诡异情况。我把这次复现中踩过的坑和排查思路整理了一下,按频率从高到低排列。
5.1 数据对齐和频率转换的常见问题
频率转换看着简单,实际操作中坑很多。我第一次用月度房价取季末值的方式,结果因为部分月份房价指数缺失,导致某个季度取到了两个月前的数值,凭空制造了一次“下跌”。后来改成季度平均值才解决。检查数据是否对齐的方法很简单:打印几个关键时间点的对齐表格,用肉眼核对转折点是否吻合。
另一个常见问题是HP滤波的端点效应。用滤波提取周期成分时,样本末尾的周期值会被趋势“拽”过去,造成虚假的周期波动。我处理的方法是延长样本期做滤波,提取周期成分后再截取需要的区间,能显著降低端点偏误的影响。
5.2 MCMC收敛和结果异常的排查
MCMC最常见的迷惑行为是“结果看起来合理但换个时间窗口就崩了”。大多数时候不是代码逻辑错了,而是模型设定对样本区间太敏感。比如滞后阶数不变,但把样本起点从2003年挪到2008年,系数估计的方差变大,脉冲响应的置信区间变得很宽——这不是bug,是模型识别力度不足的信号。
如果轨迹图有明显的漂移或“粘滞”,说明抽样没有充分探索后验分布,处理办法是增加预烧期、增加总抽样次数,或者调整先验方差。先验方差设得太大,后验会被数据主导,MCMC会发散;设得太小,后验会被先验主导,结果看起来稳定但都是先验信息。一般做法是先用一个中等宽度的先验试跑,观察后验与先验的差异是否合理。
5.3 绘图与结果输出的Matlab技巧
论文里的图表信息量很大,Matlab里绘图前建议先把数据整理成清晰的结构体或数组,再用循环批量出图。我第一次画时变脉冲响应三维图时,直接用surf函数出来一个色块混杂的图,完全没法看。后来改用contourf画等高线热力图,加上时间标签和响应期标签,效果才清晰。
另一个检查绘图结果的方法是:挑三个有代表性的时点(比如金融周期的低谷、复苏期、高峰),分别画二维脉冲响应曲线,放在同一张图上对比。这样既能直观看出时变特征,也方便放在论文里做辅助说明。
常见问题速查表:
| 问题 | 可能原因 | 排查与处理 |
|---|---|---|
| ADF检验p值不稳定 | 样本端点异常、序列有结构突变 | 缩尾处理、换对数增长率、检查样本区间 |
| HP滤波周期成分在端点飘移 | 边界效应 | 扩展样本做滤波,截取中间区间使用 |
| MCMC轨迹图呈“爬坡”趋势 | 预烧期不足、初值偏离 | 增加预烧期、执行初值寻优、调整先验方差 |
| 脉冲响应发散或大幅震荡 | 模型不稳定、滞后阶数过高 | 降低滞后阶数、检查特征根是否在单位圆内 |
| 换样本区间结果含义相反 | 机制具有区制依赖 | 分组检验、增加状态变量、参考转折点分析 |
| 月度与季度数据错位 | 频率转换方式不当 | 用季度均值替代季末值、逐年核验转折点 |
6. 这个框架还能怎么用:扩展思路与研究建议
这套“金融周期+资产价格”的分析框架具有很强的可迁移性,复现完之后别急着关电脑,稍微想想还能把它用到哪些场景,你的研究就不止“复现”这一步了。
6.1 变量替换:从房价到其他资产价格
金融周期的核心特征就是信贷扩张和收缩,这种波动不仅影响房地产,也影响股票、债券、大宗商品等资产。换掉房价变量,换成股票指数或者债券信用利差,你可以研究金融周期对资本市场的影响。这个方向上很多论文还在做,因为金融周期的度量方式没有统一标准,多一种度量就多一种贡献。
更加细化的方向是拆解房地产类别。住宅、商业地产、工业地产受金融周期影响的程度和路径可能不一样。用这份代码,只需要替换数据和调整变量顺序,就能做出一张对比脉冲响应的图,论文的一个新实证板块就出来了。
6.2 模型升级:从整体到结构、从连续到区制
TVP-VAR解决的问题是“关系是否随时间变化”,但这不够,你可能还想知道“关系为什么变化”。这时候可以在模型中加入机制识别变量,或者用马尔可夫区制转换VAR,明确分出高金融压力和低金融压力两种状态,估计两种状态下金融周期对房价的不同传导系数。
如果是做政策分析,还可以把金融周期冲击进一步分解为货币政策冲击和信贷供给冲击,用符号约束或者异方差识别来区分。这类方法在顶刊里越来越常见,Matlab生态里也有对应的实现包,复现完基础模型之后再学这部分,上手会快很多。
6.3 给正在做复现的朋友几点实在建议
第一个建议是一步一步来。先用两个变量跑通流程,再加变量、加滞后阶数,不要一上来就复制完整模型的代码,不然出了问题都不知道从哪查起。我最初就是用“金融周期+房价”两个变量做滚动窗口VAR,确认结果有初步的时变特征之后,才放心上完整的TVP-VAR。
第二个建议是保留好每一版代码和结果。MCMC模型跑一次时间长,参数调整、数据增删后结果会变。我会给代码版本和时间打标签,统一存结果文件和随机数种子,方便回溯。别小看这个习惯,在论文返修时能省下大量时间。
第三个建议是不要迷信代码包。别人写的完整代码虽然能跑通,但你要能解释每一步在干什么。我见过不少同学拿着代码包跑出结果,被问“状态方程协方差矩阵怎么更新的”就答不上来。顶刊审稿人不会问代码细节,但答辩和学术汇报一定会问模型设定,提前把原理吃透,比多跑十个回归重要得多。
第四点是我个人最大的体会:复现一篇论文,表面上是模仿,实际上是一次完整的计量训练。从变量选择、数据清洗、模型估计到结果解释,每个环节都有大量“隐性知识”没写在论文里。真正跑通一遍之后,你会发现自己不只会用代码,还会用计量经济学去思考问题。这也是我愿意把完整过程写出来的原因——希望你少踩我踩过的坑,把精力留给更值得研究的环节。