简介:面向经济学、金融学等非线性时间序列研究者的SSTVARToolbox平滑转换向量自回归模型工具包,专注于解决传统VAR模型难以捕捉状态依赖与非对称动态关系的问题。压缩包共23个文件,以21个Matlab脚本(.m)为主,覆盖模型设定、参数优化、平滑转换函数选择、稳定性检验、脉冲响应及方差分解等核心步骤;另含2份PDF版工具包指南,便于系统查阅。整个资源体积仅112KB,轻量实用。已有323人学习使用,适合具备一定VAR基础、希望向STVAR模型进阶的研究人员。通过该工具包,使用者可快速上手完整的平滑转换向量自回归建模流程,按需调用各功能模块完成从数据预处理、模型识别到结果解释的系列操作,并在实际数据集上模拟、比较不同阈值与滞后结构下的非线性动态,提升时间序列分析的深度与准确性。
1. 为什么 STVAR:从线性 VAR 到状态依赖的非线性建模
传统 VAR 模型用一组线性方程描述多个时间序列的相互影响,估计简单、解释直接,但它的隐含假设是"结构关系在所有时期都稳定"。现实中这个假设经常站不住:货币政策对通胀的传导在衰退期和繁荣期力度不同,股票市场的波动聚集让收益率序列在不同波动状态下的自回归系数明显分化。强行用线性 VAR 拟合这类数据,残差里会残留系统性结构,脉冲响应也会把不同状态下的均值混在一起,结论自然失真。平滑转换向量自回归(STVAR)做的事情是给 VAR 的系数矩阵加一个随状态变量 smooth 过渡的权重,让模型在"低状态"和"高状态"之间连续切换。本文拆解的就是 SSTVARToolbox 这套 MATLAB 工具箱:它把 STVAR 的设定、估计、检验、脉冲响应和预测扇图串成了一条完整流程,适合已经会用 VAR、但需要处理非线性结构的研究者和量化分析人员。这个工具箱的核心价值在于,你不需要自己推导似然函数和梯度,只要准备好数据、选好阶数和转换变量,就能得到一套可诊断、可复现的非线性估计结果。
2. 工具箱文件结构与 STVAR 模型设定:从 stvar.m 到 sstvar.m 的分工
打开 SSTVARToolbox.zip 之后,先别急着跑数据,把文件按功能分组读一遍,能省掉后面大量的试错时间。压缩包里除了两份 PDF 指南,剩下都是 .m 源文件。文件名后缀_accel是加速版本,_gfunc是转换函数的梯度或约束函数,com_sign和com_size这两种前缀则对应 SSTVAR 模型里"符号依赖"和"大小依赖"两种非对称设定。
2.1 模型设定:一个转换函数,两套系数
STVAR 的基本形式可以写成:
y_t = Φ1 x_t + Φ2 x_t * G(s_t; γ, c) + ε_t
其中x_t包含常数项和 y 的滞后项,G是转换函数,s_t是转换变量,γ 控制转换速度,c 是转换位置。当 G 接近 0 时,模型退化为 Φ1 主导;当 G 接近 1 时,系数变为 Φ1 + Φ2。工具箱里的stvar.m实现的就是这个核心估计流程,它接受的参数包括内生变量矩阵 Y、滞后阶数 p、转换变量在 Y 中的列位置、以及平滑参数 γ 和位置参数 c 的初值。文件stvar_d.m和stvar_tests_gfunc.m分别处理一阶导数和约束检验,这两件套配合在一起才能做基于梯度的数值优化。
2.2 文件功能速查表
下面这张表是我在拆包时按调用依赖关系整理的,比直接看文件名更直观:
| 文件 | 功能定位 | 典型调用场景 |
|---|---|---|
stvar.m | STVAR 模型主估计函数 | 给定 Y、p、转换变量,估计 Φ1、Φ2、γ、c |
sstvar.m | SSTVAR 扩展主函数 | 需要同时刻画符号与大小非对称时使用 |
opt_lag_translag.m | 联合选择滞后阶数和转换滞后 | 建模前确定 p 和转换变量滞后 d |
optsmooth.m | 优化平滑参数 γ | 固定 c 后精修转换速度 |
stvar_tests.m | 非线性/模型设定检验 | 判断 STVAR 是否显著优于线性 VAR |
sstvar_com_sign.m/sstvar_com_size.m | 符号依赖、大小依赖的组合检验 | 检验正负冲击、冲击大小的非对称响应 |
sstvar_fanchart.m | 预测扇图绘制 | 生成带置信区间的预测路径图 |
stvar_sim.m | 根据给定参数模拟 STVAR 数据 | 蒙特卡洛实验、估计效果验证 |
2.3 主函数调用:先跑通一个最小例子
以stvar.m的常见调用方式为例,结构如下:
% 假设 data 是 T x K 的矩阵,第一列为内生变量 y1,第二列为转换变量 s Y = data(:, 1); s = data(:, 2); p = 2; % 滞后阶数 d = 1; % 转换滞后:用 s(t-d) 作为转换变量 gamma0 = 2; % 平滑参数初值 c0 = median(s); % 位置参数初值:常用中位数 % 核心估计:返回结构体 result result = stvar(Y, p, s, d, gamma0, c0);这里gamma0的初值不能给 0,因为当 γ = 0 时转换函数变成常数 0.5,模型退化为线性,梯度信息会消失。常见做法是先跑一个网格搜索,把不同 γ 和 c 初值下的似然值对比后再选最优起点。result结构体里一般会包含两个状态的系数矩阵、协方差矩阵、似然值和迭代收敛标志。工具箱对输入矩阵的排列有约定:转换变量可以放在 Y 内部,也可以单独传入,区别在于d的取值逻辑。如果转换变量是内生变量自身,d 指的是在自身时序上的滞后阶数;如果转换变量是外生序列,d 通常设为 0。这个接口细节在 《SSTVAR Guide.pdf》 的第 2 节有明确说明,实操前建议先翻一下,否则很容易把转换变量的滞后和模型内生滞后搞混。
3. 滞后阶数与平滑参数估计:opt_lag_translag 与 optsmooth 的实战调参
STVAR 的建模流程里,最先要定的是两个整数参数:内生滞后阶数 p 和转换滞后 d。这两个参数如果选错,后续所有检验结果都会失真。传统 VAR 里常用 AIC 或 BIC 定阶,但 STVAR 里还需要同时考虑转换函数的滞后影响,所以工具箱单独提供了opt_lag_translag.m,把 p 和 d 放在同一个搜索网格里联合确定。
3.1 联合定阶:别把 AIC 当唯一标准
% 联合搜索滞后阶数与转换滞后 % Ylag_range:候选的 p 集合 % d_range:候选的 d 集合 Ylag_range = 1:4; d_range = 0:2; k_max = 3; % 最多考虑的转换变量个数(SSTVAR 扩展用) % 输出:每个 (p, d) 组合的信息准则结果 [lag_table, best] = opt_lag_translag(Y, s, Ylag_range, d_range);opt_lag_translag.m内部会对每个候选组合估计一次 STVAR,然后计算信息准则值。best结构体里保存的是最优组合的编号和对应参数。这里有一个经验:当样本量不足 200 时,BIC 选出来的阶数往往比 AIC 更可靠,因为 SSTVAR 的参数数量比线性 VAR 多出一倍,AIC 容易过拟合。我在实际数据上对比过,用 AIC 选出的 p 通常比 BIC 大 1 到 2,但样本外预测表现反而更差。如果两个准则给出的最优组合不一致,建议选择更大的样本内惩罚项对应的结果,再跑一次stvar_tests.m做残差自相关检验来兜底。
3.2 平滑参数网格优化
optsmooth.m解决的是 γ 和 c 的精修问题。初值可以从网格搜索里挑,也可以用下面这种方式直接在原始数据上搜:
% gamma 网格:在对数尺度上均匀取值 gamma_grid = 10.^linspace(-1, 2, 20); % 从 0.1 到 100 c_grid = quantile(s, 0.2:0.15:0.8); % 位置参数的候选范围 % 网格搜索:对每个 gamma 和 c 组合计算对数似然 logL_grid = zeros(length(gamma_grid), length(c_grid)); for gi = 1:length(gamma_grid) for ci = 1:length(c_grid) tmp = stvar(Y, p, s, d, gamma_grid(gi), c_grid(ci)); logL_grid(gi, ci) = tmp.logL; end end % 取似然最大的组合作为下一步精修的起点 [gi_best, ci_best] = find(logL_grid == max(logL_grid(:))); gamma_start = gamma_grid(gi_best); c_start = c_grid(ci_best);3.3 参数含义与边界
网格搜索的意义在于给后续数值优化一个可靠的起点。STVAR 的似然函数对 γ 非常不敏感,尤其当 γ 大于 20 之后,转换函数已经接近阶跃函数,似然面的曲率变得极小,直接丢给 fminunc 这类优化器很容易在迭代中走偏。optsmooth.m实际做的事情是按固定步长在 γ 轴上扫描,在每一步对 c 做条件优化,这样能绕过平坦似然面的问题。这里需要注意的边界是:γ 过小意味着模型没有明显区制转换,此时 STVAR 的估计结果应该和线性 VAR 接近,如果发现系数差异很大,多半是识别出了问题;γ 过大则转换函数变成跳跃式,STVAR 退化为门槛模型(TVAR),此时转换函数的平滑假设本身就不再适用。optimal 的 γ 区间一般在 2 到 20 之间,如果网格搜索出来的最优 γ 超过 50,建议检查一下是否数据里有异常值在驱动转换位置。
4. 非对称性检验与脉冲响应:stvar_tests、com_sign/com_size 到 fanchart
模型估计完之后,真正支撑结论的是两组输出:一个是"非线性是否显著"的检验,另一个是"非对称冲击如何传导"的脉冲响应。SSTVARToolbox 里stvar_tests.m管前者,sstvar_com_sign.m和sstvar_com_size.m管后者,sstvar_fanchart.m把结果画成带分布的预测扇图。
4.1 线性原假设检验:stvar_tests 的输出解读
% 对估计结果执行模型设定检验 test_result = stvar_tests(result, Y, p, s, d); % 主要输出字段: % test_result.lm_stat:LM 统计量 % test_result.p_value:检验 p 值 % test_result.arch_stat:条件异方差检验统计量stvar_tests.m实现的思路类似 LM 检验:先估计线性 VAR 得到残差,再把残差对转换函数的梯度回归,看新增解释力是否显著。这把"是否需要用 STVAR"变成一个可判断的假设检验问题,而不是拍脑袋决定。p 值小于 0.05 时,说明线性模型的残差中存在能用转换结构解释的信息;p 值大于 0.1 时,继续用 STVAR 只会增加过拟合风险。在解读检验结果时,有一个常见误区:LM 检验显著只代表"存在某种非线性结构",并不自动支持你选择的转换变量是 s_t 这个设定。稳妥的做法是换两三个候选转换变量,分别跑stvar_tests.m,选 p 值最显著、且系数经济含义最合理的那组。
4.2 符号与大小依赖:com_sign 和 com_size 的用处
com_sign.m和com_size.m这两个函数解决的是更细的问题:冲击方向不同、冲击大小不同,系统的响应是否一样。以sstvar_com_sign.m为例,它会比较正向冲击和负向冲击在脉冲响应上的差异:
% 符号依赖检验结果解读 sign_test = sstvar_com_sign(result, Y, p, s, d); % sign_test.irf_pos:正向冲击响应 % sign_test.irf_neg:负向冲击响应 % sign_test.asymmetry_p:方向非对称的显著性 p 值使用这个函数之前,需要对模型施加符号约束,否则正向和负向冲击的响应差异无法识别。常见做法是限制 Φ2 矩阵的符号结构,比如要求"正向冲击在低状态下的响应大于高状态"。这个工具箱没有内置约束编辑器,你需要根据自己的研究假设构造约束矩阵,再传入sstvar_com_size.m。大小依赖的逻辑类似,检验的是小冲击和大冲击是否成比例地传导,这个在金融风险分析里特别常用,因为它直接对应"尾部风险是否被线性模型低估"的问题。
4.3 预测扇图
% 生成未来 h 步的预测扇图 h = 12; fan = sstvar_fanchart(result, Y, h, 500); % 500 次模拟 % 输出:fan.median:预测中位数 % fan.lb / fan.ub:分位数区间扇图的价值在于把参数不确定性直接展示在预测路径上。sstvar_fanchart.m内部会对参数做 bootstrap 重抽样,对每组参数都模拟一组未来路径,再取分位数。用的时候注意:bootstrap 次数太少(小于 200)时,扇图的分位数边界会很粗糙,建议至少设 500。绘制扇图之后,我一般会把它的预测区间宽度和线性 VAR 的区间宽度对比,如果 STVAR 的区间在某些状态显著更宽,说明那里存在状态依赖的不确定性,这是有信息量的结论,比单纯比较点预测的 RMSE 更有价值。
5. 用 stvar_sim 复现估计流程:模拟数据验证与 _accel 加速排错
验证一个 STVAR 工具箱能不能用、参数能不能识别,最简单高效的方式是先用已知参数生成模拟数据,再用估计函数还原参数。stvar_sim.m帮你省掉了手写数据生成过程(DGP)的步骤,而这正是这套工具箱被很多人忽略的一个隐藏功能。
5.1 模拟——估计——对比的标准循环
% 设定真实参数 true_phi1 = [0.3; -0.1]; true_phi2 = [0.6; 0.2]; true_gamma = 3; true_c = 0.5; T = 500; % 生成模拟数据:s 用均匀分布随机数充当转换变量 s_sim = rand(T, 1); y_sim = stvar_sim(true_phi1, true_phi2, true_gamma, true_c, s_sim); % 用模拟数据反向估计 est = stvar(y_sim, 1, s_sim, 0, 2, median(s_sim)); % 对比真实参数与估计值 disp([true_phi1 + true_phi2, est.phi1 + est.phi2]);stvar_sim.m是一个独立的 DGP 模块,它会根据你给定的 Φ1、Φ2、γ、c 和转换变量序列,逐期生成 y 的值,同时检查生成过程是否平稳。如果能跑通这个循环,说明工具箱的主链路没有断,后面换真实数据时只需要关注数据本身的清洗和滞后结构。这个验证动作还有一个额外价值:它能帮你判断样本量是否足够。用 T = 200 跑一遍,再用 T = 1000 跑一遍,观察参数估计的标准误变化。如果 T = 500 时 Φ2 矩阵的估计值还带着很大的方差,说明这个模型设定在当前样本量下识别力不足,应该考虑减少待估参数,比如限制转换函数只作用于部分方程。
5.2 _accel 加速版本的使用与边界
压缩包里多个文件名带_accel后缀,比如stvar_tests_accel.m、optsmooth_accel.m、opt_lag_translag_accel.m。这些是同一函数的性能优化版本,常见做法是把双层循环向量化,或者把重复调用的似然计算改为预计算。在样本量超过 1000、滞后阶数超过 3 时,加速版本能明显缩短运行时间,但在小样本下差别不大,反而可能因为预分配逻辑复杂而引入边界问题。我的建议是:先用普通版本跑小数据验证正确性,确认无误后再切到_accel版本跑大规模模拟。如果加速版本报错,优先检查输入矩阵的数据类型是不是 single,以及是否缺少d参数的默认值。
5.3 常见排错清单
以下是拆这个工具箱时最常碰到的三类问题:
| 现象 | 原因 | 处理方式 |
|---|---|---|
| 估计结果对初值极其敏感 | γ 初值落在似然面平坦区 | 用网格搜索选多个初值,对比 logL 后取最优 |
| 提示矩阵奇异或不可逆 | 转换变量与滞后项高度共线 | 对转换变量做中心化,或换一个转换变量 |
| 检验函数报错"dimension mismatch" | Y 中包含常数项列 | 确认 Y 只传内生变量,常数项由函数内部处理 |
最后落在stvar_tests_accel.m的使用上:如果在线性 VAR 检验时速度太慢,可以只对残差序列做 ARCH 检验,跳过全模型的 LM 检验步骤,先判断条件异方差是否存在,再决定要不要完整跑 STVAR。这个顺序能把无效迭代的耗时省掉一大半,尤其适合逐月滚动分析的经济数据场景。
本文还有配套的精品资源,点击获取