Bayesian Inference of Structural Vector Autoregressions (SVAR) with the `bvartools` package

with tags r var svar vector-autoregression bvartools

The bvartools allows to perform Bayesian inference of Vector autoregressive (VAR) models, including structural VARs. This post guides through the Bayesian inference of SVAR models in R using the bvartools package.

Data

For this illustration we generate an artificial data set with three endogenous variables, which follows the data generating process

\[y_t = A_1 y_{t - 1} + B \epsilon_t,\]

where

\[ A_1 = \begin{bmatrix} 0.3 & 0.12 & 0.69 \\ 0 & 0.3 & 0.48 \\ 0.24 & 0.24 & 0.3 \end{bmatrix} \text{, } B = \begin{bmatrix} 1 & 0 & 0 \\ -0.14 & 1 & 0 \\ -0.06 & 0.39 & 1 \end{bmatrix} \text{ and } \epsilon_t \sim N(0, I_3). \]

# Reset random number generator for reproducibility
set.seed(24579)

tt <- 500 # Number of time series observations

# Coefficient matrix
A_1 <- matrix(c(0.3, 0, 0.24,
                0.12, 0.3, 0.24,
                0.69, 0.48, 0.3), 3)

# Structural coefficients
B <- diag(1, 3)
B[lower.tri(B)] <- c(-0.14, -0.06, 0.39)

# Generate series
sd_sigma <- 1
series <- matrix(rnorm(3, 0, sd_sigma), 3, tt + 1) # Raw series with zeros
for (i in 2:(tt + 1)){
  series[, i] <- A_1 %*% series[, i - 1] +  B %*% rnorm(3, 0, sd_sigma)
}

series <- ts(t(series)) # Convert to time series object
dimnames(series)[[2]] <- c("S1", "S2", "S3") # Rename variables

# Plot the series
plot.ts(series, main = "Artificial time series")

Model generation

library(bvartools)

# Generate basic model
mod <- create_bvarmodel(series,
                        p = 1,
                        deterministic = "none",
                        structural = TRUE,
                        error = "gamma",
                        iterations = 5000,
                        burnin = 2000)

Prior specification

mod_w_prior <- add_priors(mod,
                          coef = list(v_i = 0),
                          sigma = list(shape = 3, rate = .0001))

Draw posteriors

mod_w_prior <- add_initial_values(mod_w_prior, method = "ols")

post <- add_posterior_coefficients(mod_w_prior)

Evaluation

Summary statistics

summary(post)
## 
## Bayesian SVAR model with p = 1 
## 
## Endogenous variables: S1, S2, S3
## 
## Variable: S1 
## 
##         Mean      SD  Naive SD Time-series SD    2.5%    50%  97.5%  
## S1.l1 0.3293 0.02931 0.0004146      0.0004462 0.27127 0.3289 0.3875 *
## S2.l1 0.1125 0.04041 0.0005714      0.0005714 0.03299 0.1129 0.1922 *
## S3.l1 0.6807 0.04105 0.0005806      0.0005806 0.60108 0.6804 0.7626 *
## S1    1.0000 0.00000 0.0000000      0.0000000 1.00000 1.0000 1.0000 *
## S2    0.0000 0.00000 0.0000000      0.0000000 0.00000 0.0000 0.0000  
## S3    0.0000 0.00000 0.0000000      0.0000000 0.00000 0.0000 0.0000  
## 
## Variable: S2 
## 
##          Mean      SD  Naive SD Time-series SD      2.5%     50%  97.5%  
## S1.l1 0.05834 0.03334 0.0004715      0.0004715 -0.007253 0.05793 0.1257  
## S2.l1 0.31065 0.04071 0.0005757      0.0005757  0.233159 0.30901 0.3926 *
## S3.l1 0.63546 0.05282 0.0007470      0.0007695  0.533515 0.63427 0.7389 *
## S1    0.18132 0.04546 0.0006429      0.0006623  0.093218 0.18069 0.2716 *
## S2    1.00000 0.00000 0.0000000      0.0000000  1.000000 1.00000 1.0000 *
## S3    0.00000 0.00000 0.0000000      0.0000000  0.000000 0.00000 0.0000  
## 
## Variable: S3 
## 
##           Mean      SD  Naive SD Time-series SD     2.5%      50%   97.5%  
## S1.l1  0.25716 0.03311 0.0004682      0.0004582  0.19305  0.25673  0.3228 *
## S2.l1  0.16797 0.04150 0.0005869      0.0005869  0.08465  0.16852  0.2463 *
## S3.l1  0.19279 0.05879 0.0008314      0.0008314  0.07859  0.19242  0.3108 *
## S1     0.05137 0.04562 0.0006452      0.0006452 -0.03864  0.05162  0.1399  
## S2    -0.31421 0.04384 0.0006200      0.0007002 -0.39941 -0.31465 -0.2264 *
## S3     1.00000 0.00000 0.0000000      0.0000000  1.00000  1.00000  1.0000 *
## 
## Variance-covariance matrix:
## 
##         Mean      SD  Naive SD Time-series SD   2.5%    50% 97.5%  
## S1_S1 0.9862 0.06224 0.0008802      0.0008630 0.8735 0.9838 1.119 *
## S1_S2 0.0000 0.00000 0.0000000      0.0000000 0.0000 0.0000 0.000  
## S1_S3 0.0000 0.00000 0.0000000      0.0000000 0.0000 0.0000 0.000  
## S2_S2 1.0372 0.06554 0.0009269      0.0009269 0.9195 1.0333 1.175 *
## S2_S3 0.0000 0.00000 0.0000000      0.0000000 0.0000 0.0000 0.000  
## S3_S3 0.9864 0.06228 0.0008807      0.0009067 0.8711 0.9842 1.116 *

Compare with actual values

solve(B) %*% A_1
##         [,1]     [,2]     [,3]
## [1,] 0.30000 0.120000 0.690000
## [2,] 0.04200 0.316800 0.576600
## [3,] 0.24162 0.123648 0.116526
solve(B)
##        [,1]  [,2] [,3]
## [1,] 1.0000  0.00    0
## [2,] 0.1400  1.00    0
## [3,] 0.0054 -0.39    1

Plotting posterior distributions

t

plot(post, type = "boxplot")

Forecasts

post <- add_forecast_input(post, n_ahead = 10)
post <- add_posterior_forecasts(post)

pred_svar <- predict(post, n_ahead = 10)

plot(pred_svar)

Impulse response functions

irf_svar <- irf(post, n_ahead = 10, impulse = "S1", response = "S3", type = "sir")

plot(irf_svar)

Variance decomposition

fevd_svar <- fevd(post, n_ahead = 10, response = "S3", type = "sir")

plot(fevd_svar)

Compare with frequentist results

Estimate basic VAR

library(vars)

freq_var <- VAR(series, p = 1, type = "none")

Estimate structural coefficients

# Specify A0
a <- diag(1, 3)
a[lower.tri(a)] <- NA

freq_var_a <- SVAR(freq_var, Amat = a, max.iter = 1000)

freq_var_a
## 
## SVAR Estimation Results:
## ======================== 
## 
## 
## Estimated A matrix:
##         S1      S2 S3
## S1 1.00000  0.0000  0
## S2 0.18177  1.0000  0
## S3 0.05078 -0.3132  1

Impulse response function

freq_var_irf <- irf(freq_var_a, n.ahead = 10, impulse = "S1", response = "S3")

plot(freq_var_irf)

Literature

Chan, J., Koop, G., Poirier, D. J., & Tobias, J. L. (2019). Bayesian Econometric Methods (2nd ed.). Cambridge: University Press.

Lütkepohl, H. (2007). New Introduction to Multiple Time Series Analyis (2nd ed.). Berlin: Springer.

Pfaff, B. (2008). VAR, SVAR and SVEC models: Implementation within R package vars. Journal of Statistical Software, 27(4).

I hope this article was helpful. If you like, feel free to

support me with a coffee