7.6 Autoregressive distributed models ARDL

The error correction model of the previous section was built in two steps, and it assumed that both variables were integrated of order one. In applied work this double condition is uncomfortable. The unit root tests are not always conclusive, as we saw when we discussed their low power, and a system often mixes variables that are clearly \(I(1)\) with others that look \(I(0)\).

The autoregressive distributed lag model avoids the problem by treating the dynamic directly on the levels, without deciding in advance on the order of integration. It regresses the variable on its own lags and on the current and lagged values of the explanatory variables. The \(ARDL(p,q)\) with one regressor is written:

\[\begin{equation} y_t=\mu+\sum_{i=1}^{p}\phi_i y_{t-i}+\sum_{j=0}^{q}\delta_j x_{t-j}+\varepsilon_t \tag{7.47} \end{equation}\]

Its interest is that the long run relation can be recovered from the estimated coefficients. At the equilibrium the variables no longer move, \(y_t=y_{t-1}=...=y^*\) and \(x_t=x_{t-1}=...=x^*\), so the equation becomes \(y^*(1-\sum\phi_i)=\mu+x^*\sum\delta_j\), and the long run multiplier is:

\[\begin{equation} \beta=\frac{\sum_{j=0}^{q}\delta_j}{1-\sum_{i=1}^{p}\phi_i} \tag{7.48} \end{equation}\]

Pesaran, Shin and Smith have shown that this model admits an error correction form exactly as before, and that a bounds test on the joint significance of the level terms decides whether a long run relation exists. The originality of this test is that it provides two sets of critical values, one computed under the assumption that all the regressors are \(I(0)\) and the other under the assumption that they are all \(I(1)\). If the statistic is above the upper bound we conclude that a long run relation exists, if it is below the lower bound we conclude that it does not, and between the two bounds the test is inconclusive. We therefore no longer need to settle the order of integration beforehand, which is the main practical advantage of the approach.

In R:

The package ARDL selects the orders automatically and provides the bounds test.

suppressPackageStartupMessages(library(ARDL))

dat_ardl <- data.frame(y = as.numeric(y_co), x = as.numeric(x_co))

# the orders are selected by the AIC
ardl_auto <- auto_ardl(y ~ x, data = dat_ardl, max_order = 4, selection = "AIC")
ardl_fit  <- ardl_auto$best_model

cat("selected orders (p, q):", ardl_auto$top_orders[1, 1], ardl_auto$top_orders[1, 2], "\n")
#> selected orders (p, q): 1 4
# the long run multiplier
lr_mult <- multipliers(ardl_fit)
Table 7.27: long run multipliers of the ARDL in R
Term Estimate Std. Error t value Pr(>|t|)
(Intercept) 2.0738 0.0621 33.4213 0
x 1.4849 0.0108 137.2335 0

The long run coefficient attached to \(x\) is again close to \(1.5\), which is reassuring: the \(ARDL\) finds the same long run relation as the Engle-Granger regression, but without having required us to test the integration of the series first.

# the bounds test of Pesaran, Shin and Smith
bt <- bounds_f_test(ardl_fit, case = 2)
bt
#> 
#>  Bounds F-test (Wald) for no cointegration
#> 
#> data:  d(y) ~ L(y, 1) + L(x, 1) + d(x) + d(L(x, 1)) + d(L(x, 2)) + d(L(x,     3))
#> F = 89.39, p-value = 1e-06
#> alternative hypothesis: Possible cointegration
#> null values:
#>    k    T 
#>    1 1000

The statistic is far above the upper bound at the usual levels, so the existence of a long run relation is confirmed.

# the error correction form of the same model
ecm_ardl <- uecm(ardl_fit)
ecm_coef <- data.frame(
  coefficient = rownames(summary(ecm_ardl)$coefficients),
  estimate    = summary(ecm_ardl)$coefficients[, 1],
  p_value     = summary(ecm_ardl)$coefficients[, 4]
)
Table 7.28: error correction form of the ARDL in R
coefficient estimate p_value
(Intercept) 1.7928 0.0000
L(y, 1) -0.8645 0.0000
L(x, 1) 1.2837 0.0000
d(x) 1.1518 0.0000
d(L(x, 1)) -0.0575 0.1400
d(L(x, 2)) 0.0037 0.9195
d(L(x, 3)) 0.0318 0.3676

In Python:

The class ARDL of statsmodels estimates the same model. The orders are given explicitly here, and the long run coefficients are read in the attribute params of the error correction representation.


from statsmodels.tsa.ardl import ARDL, ardl_select_order

y_ardl = np.asarray(y_co_py, dtype=float)
x_ardl = np.asarray(x_co_py, dtype=float).reshape(-1, 1)

sel = ardl_select_order(y_ardl, 4, x_ardl, 4, ic="aic", trend="c")
ardl_py = sel.model.fit()

# the long run multiplier, computed from the estimated coefficients.
# statsmodels returns the coefficients as a plain array, so we pair them
# with the names kept in the model.
names = list(ardl_py.model.exog_names)
vals  = np.asarray(ardl_py.params)
ar_terms = [v for k, v in zip(names, vals) if k.startswith("y.L")]
dl_terms = [v for k, v in zip(names, vals) if k.startswith("x")]
beta_lr = sum(dl_terms) / (1 - sum(ar_terms))

ardl_out_py = pd.DataFrame({
    "p (lags of y)": [len(ar_terms)],
    "q (lags of x)": [len(dl_terms) - 1],
    "long_run_beta": [round(beta_lr, 4)]
})
Table 7.29: ARDL long run multiplier in python
p (lags of y) q (lags of x) long_run_beta
1 2 1.4845

The long run multiplier computed by hand from the coefficients matches the one returned by the R package, which is a useful check that the two specifications are indeed the same.