Identification through heteroskedasticity — R cross-check¶

Vector autoregressions, Part 10 (R)¶

Validates hetid_python.ipynb. svars::id.cv (changes-in-volatility) is not installed, so we implement Rigobon's simultaneous diagonalisation directly in base R on a vars::VAR fit: split at the Great Moderation, estimate the two regime covariances, and solve the generalised eigenproblem for the structural impact matrix. It should return the same variance ratios and the same (non-triangular) $B_0$.

Data: bvar_sv_data.csv — GDP growth, inflation, funds rate, quarterly 1959-2019 (FRED-QD).

In [1]:
.libPaths('C:/Users/user/R/win-library/4.6'); suppressMessages(library(vars))
d <- read.csv('bvar_sv_data.csv'); Y <- d[, c('gdp_growth','inflation','tbill')]; dt <- as.Date(d$date)
v <- VAR(Y, p=2, type='const'); E <- residuals(v); td <- dt[-(1:2)]
reg <- td < as.Date('1984-01-01')
S1 <- cov(E[reg, ]); S2 <- cov(E[!reg, ])
L1 <- t(chol(S1)); L1i <- solve(L1)                              # lower-triangular whitening
eg <- eigen((L1i %*% S2) %*% t(L1i), symmetric=TRUE)
B0 <- L1 %*% eg$vectors
cat('structural-shock variance ratios post/pre-1984:', round(sort(eg$values), 2), ' (distinct => identified)\n')
cat('het-ID impact matrix B0 (up to labelling / sign):\n'); print(round(B0, 2))
cat('recursive Cholesky impact:\n'); print(round(t(chol(cov(E))), 2))
# label the eigenvector columns like Python: assign each shock to the variable it loads on most, sign diagonal +
perm <- integer(3); avail <- 1:3
for (i in 1:3) { j <- avail[which.max(abs(B0[i, avail]))]; perm[i] <- j; avail <- setdiff(avail, j) }
Bl <- B0[, perm]; Bl <- sweep(Bl, 2, sign(diag(Bl)), '*')
dimnames(Bl) <- list(colnames(Y), c('gdp shock','infl shock','funds shock'))
cat('labelled B0 (matches Python up to nothing further):\n'); print(round(Bl, 2))
infl_on_gdp <- Bl[1, 2]                                          # inflation shock -> GDP: the element Cholesky zeroes
uppertri <- max(abs(Bl[upper.tri(Bl)]))
cat(sprintf('cross-check -> Python: inflation->GDP = %.2f (Python 1.14); largest upper-triangular |B0| = %.2f => B0 NOT triangular, recursive ordering rejected\n', infl_on_gdp, uppertri))
Warning message:
"package 'vars' was built under R version 4.6.1"
Warning message:
"package 'strucchange' was built under R version 4.6.1"
structural-shock variance ratios post/pre-1984: 0.11 0.26 0.44  (distinct => identified)
het-ID impact matrix B0 (up to labelling / sign):
            [,1]  [,2] [,3]
gdp_growth -1.14  3.81 0.19
inflation  -1.07 -0.40 0.25
tbill      -0.06  0.20 1.15
recursive Cholesky impact:
           gdp_growth inflation tbill
gdp_growth       3.01      0.00  0.00
inflation        0.01      0.94  0.00
tbill            0.19      0.14  0.76
labelled B0 (matches Python up to nothing further):
           gdp shock infl shock funds shock
gdp_growth      3.81       1.14        0.19
inflation      -0.40       1.07        0.25
tbill           0.20       0.06        1.15
cross-check -> Python: inflation->GDP = 1.14 (Python 1.14); largest upper-triangular |B0| = 1.14 => B0 NOT triangular, recursive ordering rejected

Same identification, independent code¶

  • vars + base-R reproduce it. The generalised eigenproblem on the two Great-Moderation regime covariances returns the same variance ratios (0.11 / 0.26 / 0.44, distinct) and — after matching each eigenvector column to its dominant variable and signing the diagonal positive — the same labelled structural impact matrix as the from-scratch Python hetid: the contemporaneous inflation→GDP element is 1.14, matching Python (a Cholesky scheme with output ordered first forces it to zero).
  • And the same verdict. $B_0$ is not lower-triangular — the recursive ordering is not supported by the second-moment identification, confirming the Python result on an independent implementation.

References¶

  • Rigobon, R. (2003). Identification through heteroskedasticity. Review of Economics and Statistics 85, 777-792.
  • Lanne, M., Lütkepohl, H. & Maciejowska, K. (2010). Structural VARs with Markov switching. J. Economic Dynamics & Control 34, 121-131.