statsmodels中ARDL模型如何数学建模趋势与季节性成分
statsmodels中的ARDL模型本质是带确定性解释项的最小二乘动态回归,不会对输入序列预先做趋势/季节性分解,所有趋势、季节效应都以线性确定项的形式直接加入回归方程右侧,和自回归项、分布滞后项的系数一同通过OLS估计。
趋势项的数学规则
趋势项完全由建模时传入的trend参数控制,可选配置对应加入的确定项如下:
trend="n":不加入任何确定性趋势项,模型过原点trend="c":仅加入常数截距项,为最常用配置,即示例代码中使用的参数trend="t":仅加入线性时间趋势项,时间变量t按观测顺序从1开始逐期递增1trend="ct":同时加入常数截距+线性时间趋势trend="ctt":同时加入常数截距+线性时间趋势+二次时间趋势($t^2$项)
以设定的场景为例:因变量为$X$,自变量为$W、Y、Z$,ardl_select_order输出最优阶数为(3,1,3,2)(即AR阶数为3,三个自变量的最高分布滞后阶分别为1、3、2),若选择trend="ct",模型完整形式为:
$$
X_t = \underbrace{\beta_0 + \beta_1 t}{\text{确定性趋势部分}} + \underbrace{\sum{i=1}^3 \phi_i X_{t-i}}{\text{AR(3)自回归部分}} + \underbrace{\sum{j=0}^1 \gamma_j W_{t-j} + \sum_{j=0}^3 \delta_j Y_{t-j} + \sum_{j=0}^2 \theta_j Z_{t-j}}_{\text{分布滞后部分}} + \epsilon_t
$$
注意:分布滞后项从当期值(j=0)开始覆盖到最高滞后阶,比如W的最高滞后阶为1,代表模型会同时纳入当期$W_t$和滞后1期$W_{t-1}$两个变量。
季节性成分的数学规则
statsmodels的ARDL类没有内置SARIMA式的季节自回归/季节移动平均滞后结构,季节性效应通过两种方式实现:
- 固定季节效应(最常用):根据数据频率手动构造季节虚拟变量,作为额外外生变量传入
exog参数。比如季度频率数据构造3个0-1虚拟变量(避免多重共线性,留1个季度作为基准组),月度频率数据构造11个月度虚拟变量,虚拟变量的系数就代表对应时段相对基准时段的固定季节差值。 - 季节滞后动态效应:如果需要纳入季节维度的动态滞后关系(比如季度数据加入滞后4期的自回归项、自变量的季节滞后项),需要手动构造对应滞后序列,作为额外变量传入模型。
如果采用季度固定季节效应,上述模型会在方程右侧追加季节项部分$\lambda_2 Q2_t + \lambda_3 Q3_t + \lambda_4 Q4_t$,其中$Q2/Q3/Q4$为对应季度的虚拟变量。
代码示例与注意事项
提供的示例代码中设置trend="c",拟合的模型仅包含常数截距,无额外时间趋势与季节项,对应丹麦货币需求数据的模型形式为:
$$
lrm_t = \beta_0 + \sum_{i=1}^3 \phi_i lrm_{t-i} + \sum_{j=0}^1 \gamma_j lry_{t-j} + \sum_{j=0}^3 \delta_j ibo_{t-j} + \sum_{j=0}^2 \theta_j ide_{t-j} + \epsilon_t
$$
如果需要加入线性趋势与季度季节效应,参考实现如下,注意手动构造趋势/季节项后不要在trend参数中重复传入对应配置,避免完全多重共线性:
import numpy as np import pandas as pd from statsmodels.datasets.danish_data import load from statsmodels.tsa.api import ARDL from statsmodels.tsa.ardl import ardl_select_order data = load().data data = data[["lrm", "lry", "ibo", "ide"]] # 为数据集生成季度频率时间索引(示例数据共55个观测) data.index = pd.date_range(start="1974Q1", periods=len(data), freq="Q") # 构造线性时间趋势 data["trend"] = np.arange(1, len(data)+1) # 构造季度虚拟变量,以第一季度为基准组 data["Q2"] = (data.index.quarter == 2).astype(int) data["Q3"] = (data.index.quarter == 3).astype(int) data["Q4"] = (data.index.quarter == 4).astype(int) # 合并所有外生变量:原自变量+趋势项+季节虚拟变量 exog = data[["lry", "ibo", "ide", "trend", "Q2", "Q3", "Q4"]] sel_res = ardl_select_order( endog=data.lrm, maxlag=3, exog=exog, maxorder=3, ic="aic", trend="c" # 已手动添加趋势项,此处仅保留截距 ) res = sel_res.model.fit() print(res.summary())
内容的提问来源于stack exchange,提问作者Mehul Gupta

