Bayesian VECM — II. Fisher effect — R cross-check¶

Vector autoregressions, Part 6b (R)¶

Validates bvecm_fisher_python.ipynb. Two urca tools: ur.df for the Augmented Dickey-Fuller unit-root tests (is each series I(1)?) and ca.jo for the Johansen rank test. Both should confirm the Python verdict — inflation is already stationary, so the Fisher pair is jointly stationary (full rank), not cointegrated.

Data: bvecm_fisher_data.csv — 3-month rate and annualised CPI inflation, quarterly 1959–2019 (FRED).

In [1]:
.libPaths('C:/Users/user/R/win-library/4.6')
suppressMessages(library(urca))
d <- read.csv('bvecm_fisher_data.csv'); Y <- d[, c('tbill','inflation')]
for (nm in c('tbill','inflation')) {
  s <- summary(ur.df(Y[[nm]], type = 'drift', lags = 4, selectlags = 'AIC'))
  cat(sprintf('ADF %-9s: stat %6.2f  (5%% crit %.2f)  -> %s\n', nm, s@teststat[1], s@cval[1,2],
              ifelse(s@teststat[1] > s@cval[1,2], 'I(1): unit root not rejected', 'stationary I(0)')))
}
jo <- ca.jo(Y, type = 'trace', ecdet = 'none', K = 2, spec = 'transitory')
cat('\nJohansen trace test:\n'); print(round(cbind(trace = jo@teststat, jo@cval), 1))
cat('\ncross-check -> Python: tbill I(1), inflation I(0). Rank is borderline (urca r=1 vs statsmodels full rank,\n')
cat('  different critical-value tables on the 2nd trace stat); with inflation I(0) the Fisher cointegration premise fails either way.\n')
ADF tbill    : stat  -2.29  (5% crit -2.88)  -> I(1): unit root not rejected
ADF inflation: stat  -3.14  (5% crit -2.88)  -> stationary I(0)
Johansen trace test:
         trace 10pct 5pct 1pct
r <= 1 |   5.9   6.5  8.2 11.7
r = 0  |  48.5  15.7 18.0 23.5
cross-check -> Python: tbill I(1), inflation I(0). Rank is borderline (urca r=1 vs statsmodels full rank,
  different critical-value tables on the 2nd trace stat); with inflation I(0) the Fisher cointegration premise fails either way.

Same verdict: no cointegration¶

  • ur.df splits the integration orders. The nominal rate does not reject a unit root (I(1)); inflation does (stationary, I(0)) — matching the Python ADF tests. With mixed orders, cointegration is undefined.
  • The rank is borderline, and it doesn't matter. On the second trace statistic the two packages disagree — urca's Osterwald-Lenum critical values call it $r=1$, statsmodels' MacKinnon-Haug-Michelis values call it full rank — because the statistic sits right between the two tables. This ambiguity is itself the point: with inflation already I(0), the system does not have the clean unit-root structure a cointegration rank is meant to describe, so the exact rank is neither well-determined nor economically meaningful.
  • The lesson survives translation: pre-test the integration order before reaching for a VECM.

References¶

  • Pfaff, B. (2008). Analysis of Integrated and Cointegrated Time Series with R. Springer.
  • Mishkin, F. S. (1992). J. Monetary Economics 30, 195–215.