Oil SVAR identification debate — R cross-check¶
Vector autoregressions, Part 8b (R)¶
Validates oilsvar2_python.ipynb. The canonical R package for sign restrictions (VARsignR) is archived, so — as in the Part 2 monetary notebook — we implement the rotation search directly in base R on a vars::VAR fit: draw Haar-uniform rotations, keep those whose impact responses match the supply / aggregate-demand / oil-specific-demand sign pattern, and read off the supply share of the real-oil-price variance. If its distribution matches the Python flat-sign result, the set-identification is confirmed independently.
Data: oilsvar_data.csv — world oil production growth, Kilian real-activity index, real oil price; monthly 1974–2019, VAR(24).
In [1]:
.libPaths('C:/Users/user/R/win-library/4.6')
suppressMessages(library(vars))
d <- read.csv('oilsvar_data.csv'); Y <- d[, c('prod_growth','rea','rpo')]
v <- VAR(Y, p = 24, type = 'const')
C <- t(chol(cov(residuals(v)))) # lower-triangular impact factor
Ph <- Phi(v, nstep = 18) # reduced-form MA, Ph[,,1] = I
set.seed(1); shares <- c()
for (it in 1:60000) {
Q <- qr.Q(qr(matrix(rnorm(9), 3, 3)))
A0 <- C %*% Q
A0 <- A0 %*% diag(sign(A0[3, ])) # normalise each shock so the real oil price (row 3) rises
cls <- rep(NA, 3)
for (c in 1:3) { pp <- A0[1, c]; ra <- A0[2, c]
cls[c] <- if (pp < 0 && ra < 0) 'sup' else if (pp > 0 && ra > 0) 'agg' else if (pp > 0 && ra < 0) 'oil' else NA }
if (any(is.na(cls)) || length(unique(cls)) < 3) next
A0o <- A0[, c(which(cls == 'sup'), which(cls == 'agg'), which(cls == 'oil'))]
ss <- rep(0, 3); for (h in 1:19) { g <- Ph[, , h] %*% A0o; ss <- ss + g[3, ]^2 } # var of real oil price by shock
shares <- rbind(shares, ss / sum(ss))
}
cat(sprintf('accepted %d of 60000 rotations (%.1f%%)\n', nrow(shares), 100 * nrow(shares) / 60000))
cat(sprintf('supply share of real-oil-price variance: median %.2f [%.2f, %.2f]\n',
median(shares[, 1]), quantile(shares[, 1], .16), quantile(shares[, 1], .84)))
cat('cross-check -> Python flat sign restrictions: supply 0.31 [0.10, 0.60] (agree)\n')
Warning message: "package 'vars' was built under R version 4.6.1"
Warning message: "package 'strucchange' was built under R version 4.6.1"
accepted 8888 of 60000 rotations (14.8%)
supply share of real-oil-price variance: median 0.30 [0.10, 0.59]
cross-check -> Python flat sign restrictions: supply 0.31 [0.10, 0.60] (agree)
Same wide, supply-heavy set¶
- The independent R rotation search agrees. Base-R Haar rotations that satisfy the same sign pattern put the supply share of the real-oil-price variance near ~0.3 with a wide band — reproducing the Python result and, with it, the central point: flat sign restrictions are far from agnostic about supply, and attribute much more of the oil price to supply than the recursive scheme.
- The Kilian-Murphy elasticity bound and the Baumeister-Hamilton prior (Python notebook) are what narrow this set back toward the demand story — and they do so by stating an economic belief explicitly, which is the honest way to identify.
References¶
- Kilian, L. & Murphy, D. P. (2012). J. European Economic Association 10, 1166–1188.
- Baumeister, C. & Hamilton, J. D. (2019). American Economic Review 109, 1873–1910.