# Compute Impulse Response Functions to Structural Shocks using bayesianVARs

#### Stefan Haan1

# Introduction

The structural VAR model of order \(p\) assumes the vector-valued observations \(\left\{ y_t , t = 1, \dots, T \right\}\) are generated by the process2 \[\begin{equation*} y_t' B_0 = y_{t-1}' B_1 + \dots + y_{t-p}' B_p + \omega_t'. \end{equation*}\] The components of \(\omega_t\) are required to be uncorrelated (i.e., the variance-covariance matrix \(\Sigma_{\omega}\) is a diagonal matrix) and referred to as structural shocks.

The model parameter \(B_0\) is not identified. The model deserves to be called “structural”, only if \(B_0\) reflects the instantaneous causal relationships between the variables. Theoretical considerations are used to place restrictions on the entries of \(B_0\) (Lütkepohl 2005, sec. 10.2.2). Following (Rubio-Ramírez, Waggoner, and Zha 2010) and (Arias, Rubio-Ramírez, and Waggoner 2014), in order to identify \(B_0\), we allow the user to specify identifying zero and sign restrictions for several transformations of the structural parameters:

- \(B_0\) itself,
- the contemporaneous effects \(\mathrm{IR}_0 := B_0'^{-1}\),
- the structural coefficients \(B_1, B_2, \dots, B_p\), and
- the long-run effects (sum of the impulse responses over all horizons \(h\)) \[\begin{equation*} \mathrm{IR}_\infty := \left(B_0' - \sum_{l=1}^{p} B_l' \right)^{-1}. \end{equation*}\]

An impulse response function describes the effects of an shock to the system over time. Intuitively, IRFs answer the question: “What is the effect of a shock \(\varepsilon_t\) hitting the system at time \(t\) on \(y_{t+h}\) for \(h = 1,2,\dots\), given that no other shocks hit the system?” (Koop, Pesaran, and Potter 1996). Formally, we define IRFs as the Jacobian \[\begin{equation*} \Theta_h := \frac{\partial y_{t+h}}{\partial \omega_t'}. \end{equation*}\]

If the (homoskedastic) factor model is used, we define the impulse reponses with respect to innovations in the factors \(f_t\) instead: \[\begin{equation*} \frac{\partial y_{t+h}}{\partial f_t'}. \end{equation*}\] In this case, identification of the IRFs is achieved by zero and sign restrictions on the factor loadings \(\Lambda\) (which are also the contemporaneous effects \(\mathrm{IR}_0\)) and/or the long-run effects.

One outstanding feature of bayesianVARs is the ability to account for time-varying innovation variances using the stochastic volatility models implemented in stochvol and factorstochvol (Gruber 2024). For these models however, all columns of \(B_0\) are already identified up to sign (Lütkepohl et al. 2024). This result generalizes to the VAR model with factor stochastic volatility (Haan 2025, Theorem 2). If a heteroskedastic model is fitted with `bvar` (the default), the function `irf` uses the estimated innovation variances at time \(T\).

# Usage examples

We present several practical examples in R that show how bayesianVARs can be used to obtain IRFs. The example Optimism shocks is intended to show typical usage and reproduces Figure 4(a) from (Arias, Rubio-Ramírez, and Waggoner 2014). In the example A Monetary SVAR we show how to relax restrictions that cannot be satisfied. In particular, we replace a zero restriction with a custom “approximately zero restriction” using rejection sampling.

## Optimism shocks

(Beaudry, Nam, and Wang 2011) analyze the relevance of optimism shocks on business cycle phenomena such as a boom in output, investment, consumption, and hours worked. (Beaudry, Nam, and Wang 2011) propose several identification schemes for optimism shocks. All identification schemes have in common that an optimism shock should be associated with an increase in stock prices. Additionally, the optimism shock should not be associated with improvements in technology (measured by total factor productivity) or expansionary monetary policy, which can be competing causes for an increase in stock prices. The most agnostic identification scheme imposes only a zero restriction on productivity and a positive sign restriction on stock prices on the contemporaneous effects.

(Arias, Rubio-Ramírez, and Waggoner 2014) criticize the approach used by (Beaudry, Nam, and Wang 2011) to calculate the IRFs for its upward bias and artificially narrow confidence intervals, and come to the conclusion that the reported results are not significant, if the IRFs are drawn from the correct distribution. (Wang and Woźniak 2025) replicate this using the R package bsvarSIGNs. In this example we replicate this result once more using bayesianVARs.

First, we load the `optimism` dataset from the bsvarSIGNs package.

    library(bsvarSIGNs)
    data(optimism)

We then fit a homoskedastic \(\mathrm{VAR}(4)\) model using bayesianVARs.

    library(bayesianVARs)
    prior_sigma <- specify_prior_sigma(
        M = ncol(optimism),
        type = "cholesky",
        cholesky_heteroscedastic = FALSE
    )
    mod <- bvar(optimism * 100, lags = 4L, prior_sigma = prior_sigma)

We construct following matrix describing the zero and sign restrictions on the contemporaneous effects.

    show(restrictions)

    ##                    shock1 shock2 shock3 shock4 shock5
    ## productivity            0     NA     NA     NA     NA
    ## stock_prices            1     NA     NA     NA     NA
    ## consumption            NA     NA     NA     NA     NA
    ## real_interest_rate     NA     NA     NA     NA     NA
    ## hours_worked           NA     NA     NA     NA     NA

Here, `NA` signifies an unrestricted parameter, `0` a zero restriction on the parameter and `1` imposes a positive sign restriction. Since shocks 2-5 are not identified, we calculate IRFs only for the first shock.

    shock1 <- diag(ncol(optimism))[, 1, drop=FALSE]
    show(shock1)

    ##      [,1]
    ## [1,]    1
    ## [2,]    0
    ## [3,]    0
    ## [4,]    0
    ## [5,]    0

    struct_restr <- specify_structural_restrictions(
        mod,
        restrictions_B0_inv_t = restrictions
    )
    shock1_irf <- irf(
        mod,
        ahead = 40,
        structural_restrictions = struct_restr,
        shocks = shock1
    )

    plot(shock1_irf, quantiles = c(0.16, 0.50, 0.84))

IRFs to an one standard-deviation optimism shock.

The 68% confidence intervals we compute resemble the intervals shown in (Arias, Rubio-Ramírez, and Waggoner 2014, Figure~4(a)). We can see that the confidence intervals of consumption and hours worked include zero at all times. The optimism shock identified in this manner has therefore no statistically significant effect on any of the these variables in our model. Stock prices seem to be highly persistent, with significant effects for at least 40 periods after the initial shock.

## A Monetary SVAR

(Rubio-Ramírez, Waggoner, and Zha 2010) show that a five-variable structural VAR model of monetary policy is globally identified, if some normalization rule for the signs of the structural parameters exists and the following zero restrictions on \(B_0\) are imposed: \[\begin{equation*} B_0 = \begin{pmatrix} & \text{PS} & \text{PS} & \text{MP} & \text{MD} & \text{Inf} \\ \log Y & * & * & 0 & * & * \\ \log P & 0 & * & 0 & * & * \\ R & 0 & 0 & * & * & * \\ \log M & 0 & 0 & * & * & * \\ \log P_c & 0 & 0 & 0 & 0 & * \end{pmatrix}. \end{equation*}\] Variables:

- \(Y\) … gross domestic product (GDP)
- \(P\) … GDP deflator
- \(R\) … nominal short-term interest rate
- \(M\) … M3 money supply
- \(P_c\) … commodity prices

Shocks:

- PS … production sector
- MP … monetary policy
- MD … money demand
- Inf … information in the commodity market

bayesianVARs will report an error, if one attempts to calculate the IRFs to the structural shocks identified by the restrictions above:

    train_data <- 100 * usmacro_growth[
      , c("GDPC1", "GDPCTPI", "GS1", "M2REAL", "CPIAUCSL")
    ]
    prior_sigma <- specify_prior_sigma(
      M = ncol(train_data),
      type = "cholesky",
      cholesky_heteroscedastic = FALSE
    )
    mod <- bvar(train_data, lags = 5L, prior_sigma = prior_sigma)

    restrictions_B0 <- rbind(
      c(1 ,NA,0 ,NA,NA),
      c(0 ,1 ,0 ,NA,NA),
      c(0 ,0 ,1 ,NA,NA),
      c(0 ,0 ,NA,1 ,NA),
      c(0 ,0 ,0 ,0 ,1 )
    )
    restrictions <- specify_structural_restrictions(
      mod,
      restrictions_B0 = restrictions_B0
    )

    irf1 <- irf(mod, ahead = 4, structural_restrictions = restrictions)

    ## Error in irf(mod, ahead = 4, structural_restrictions = restrictions): The restrictions could not be satisfied

How can we deal with this situation? One option is to relax one of the zero restrictions to an “approximately zero” restriction. Good candidates for the zero restriction on \(B_0\) to be relaxed are any of the restrictions in column two (“PS” shock) or three (“MP” shock). Note that if we drop any of those restrictions, the number of zeros does not exceed those of a triangular matrix and bayesianVARs should be able to find structural parameters.

bayesianVARs does not implement “approximately zero” restrictions, but the desired behavior can be achieved by estimating a slightly larger model and then conditioning on the restriction by rejecting all posterior samples which do not meet it.3

First, we draw a much large number of reduced form samples, knowing most of them will be rejected.

    mod <- bvar(
      train_data, lags = 5L, draws = 20*3000, prior_sigma = prior_sigma
    )

We then obtain samples for the structural parameter \(B_0\), dropping the zero restriction “\((B_0)_{3,2} = 0\)”. This can be thought of allowing the contemporaneous effect \(R \rightarrow P\) to be different than zero.

    restrictions_B0_relaxed <- rbind(
      c(1 ,NA,0 ,NA,NA),
      c(0 ,1 ,0 ,NA,NA),
      c(0 ,NA,1 ,NA,NA),
      c(0 ,0 ,NA,1 ,NA),
      c(0 ,0 ,0 ,0 ,1 )
    )

The relaxed restrictions have columns with \(0, 1, \dots, M-1\) zero restrictions and exactly one sign restriction per column. In this case, an unique solution exists for every reduced-form draw.

    restrictions_relaxed <- specify_structural_restrictions(
      mod, restrictions_B0 = restrictions_B0_relaxed
    )
    irf_relaxed <- irf(
      mod, ahead = 4,
      structural_restrictions = restrictions_relaxed
    )
    B0_relaxed <- extractB0(irf_relaxed)

Find the samples which fulfill the approximately zero condition \(\lvert (B_0)_{3,2} \rvert < 0.01\) and make sure enough are remaining.

    B0_31_approx_zero <- abs(B0_relaxed[3,2,]) < 0.01
    sum(B0_31_approx_zero)

    ## [1] 4956

Finally, plot the IRFs, conditional on `B0_31_approx_zero`:

    irf_conditional <- irf_relaxed[,,,B0_31_approx_zero]
    class(irf_conditional) <- class(irf_relaxed)
    plot(irf_conditional)

## Joint credible regions

(Inoue and Kilian 2022) criticize the common practice of plotting the point-wise quantiles of the IRFs, like we did in the previous examples. They draw attention to the fact, that that the point-wise posterior median (or mean) is not necessarily equal to any of the impulse response vectors that satisfy the identifying restrictions.

Following (Inoue and Kilian 2022, sec. 2.4), we allow the user to visualize the \((1-\alpha)~\text{100%}\) joint credible set by sorting all IRF draws \(\{ \Phi^{(r)} \}_{r=1\dots R}\) in ascending order of \[\begin{equation*} \hat Q(\Phi^{(r)}) := \hat{\mathbb{E}}_\Phi\left[L(\Phi^{(r)}, \Phi) \right] = \frac{1}{R} \sum_{s=1}^{R} L\left(\Phi^{(r)}, \Phi^{(s)} \right) \end{equation*}\] and plotting only the first \((1-\alpha)~\text{100%}\) draws. We use absolute loss for the loss function \(L\). The draw with the smallest value of \(\hat Q\) is referred to as the Bayes estimator (shown as the black trajectory in the plot below).

Consider the following example, in which we deliberately do not use any sign-normalization: Using bayesianVARs, we estimate a two factor model on the entire `usmacro_growth` dataset, containing 21 variables.

    prior_sigma <- specify_prior_sigma(
      M = ncol(usmacro_growth),
      type = "factor",
      factor_factors = 2,
      factor_restrict = "none",
      factor_heteroskedastic = FALSE
    )
    mod <- bvar(100 * usmacro_growth, lags = 5L, prior_sigma = prior_sigma)

We require the first factor shock to have no long-run effects on the level of GDP,4 but do not impose any other identifying restrictions.

    show(restrictions_long_run_ir)

    ##                 factors
    ## vars             [,1] [,2]
    ##   GDPC1            NA   NA
    ##   PCECC96          NA   NA
    ##   GPDIC1           NA   NA
    ##   PRFIx            NA   NA
    ##   INDPRO           NA   NA
    ##   CUMFNS           NA   NA
    ##   SRVPRD           NA   NA
    ##   CE16OV           NA   NA
    ##   AWHMAN           NA   NA
    ##   PCECTPI          NA   NA
    ##   GDPCTPI          NA   NA
    ##   GPDICTPI         NA   NA
    ##   CPIAUCSL         NA   NA
    ##   CES2000000008x   NA   NA
    ##   FEDFUNDS         NA   NA
    ##   GS1              NA   NA
    ##   GS10             NA   NA
    ##   M2REAL           NA   NA
    ##   EXUSUKx          NA   NA
    ##   UMCSENTx         NA   NA
    ##   S&P 500          NA   NA

    restr <- specify_structural_restrictions(
      mod,
      restrictions_long_run_ir = restrictions_long_run_ir,
    )

    shock1 <- diag(2)[, 1, drop = FALSE]

Because our identification scheme admits sign switches, roughly half of all trajectories have opposite signs and the medians turn out to be about zero for all time horizons. Yet, zero would be a bad estimate: The trajectory plot (with `hairy=TRUE`) reveals that our model predicts a statistically significant effect, we are just unsure about its sign.

    x <- irf(mod, hairy = FALSE, structural_restrictions = restr, shocks = shock1)
    plot(x, vars = "PCECTPI")

    x <- irf(mod, hairy = TRUE, structural_restrictions = restr, shocks = shock1)
    plot(x, vars = "PCECTPI", quantiles=0.68, default_hair_color = "#FF000005")

# References

Arias, Jonas E., Juan F. Rubio-Ramírez, and Daniel F. Waggoner. 2014. “Inference Based on SVARs Identified with Sign and Zero Restrictions: Theory and Applications.” FRB Atlanta Working Paper Series. https://doi.org/10.2139/ssrn.2580264.
Beaudry, Paul, Deokwoo Nam, and Jian Wang. 2011. “Do Mood Swings Drive Business Cycles and Is It Rational?” Working Paper 17651. Working Paper Series. National Bureau of Economic Research. https://doi.org/10.3386/w17651.
Gruber, Luis. 2024. “Shrinkage Priors for Bayesian Vectorautoregressions Featuring Stochastic Volatility Using the **r** Package **bayesianVARs**.” URL Https://CRAN.R-Project.org/Package=bayesianVARs. Vignette Included in R Package bayesianVARs, Version 0.1.5. https://CRAN.R-Project.org/package=bayesianVARs.
Haan, Stefan. 2025. “Impulse Response Functions for Bayesian Vector Autoregressions.” Master Thesis, Alpen-Adria-Universität Klagenfurt.
Inoue, Atsushi, and Lutz Kilian. 2022. “Joint Bayesian Inference about Impulse Responses in VAR Models.” Journal of Econometrics 231 (2): 457–76. https://doi.org/10.1016/j.jeconom.2021.05.010.
Koop, Gary, M. Hashem Pesaran, and Simon M. Potter. 1996. “Impulse Response Analysis in Nonlinear Multivariate Models.” Journal of Econometrics 74 (1): 119–47. https://doi.org/10.1016/0304-4076(95)01753-4.
Lütkepohl, Helmut. 2005. New Introduction to Multiple Time Series Analysis. Heidelberg: Springer-Verlag Berlin. https://doi.org/10.1007/978-3-540-27752-1.
Lütkepohl, Helmut, Fei Shang, Luis Uzeda, and Tomasz Woźniak. 2024. “Partial Identification of Heteroskedastic Structural VARs: Theory and Bayesian Inference.” https://arxiv.org/abs/2404.11057.
Rubio-Ramírez, Juan F., Daniel F. Waggoner, and Tao Zha. 2010. “Structural Vector Autoregressions: Theory of Identification and Algorithms for Inference.” The Review of Economic Studies 77 (2): 665–96. https://doi.org/10.1111/j.1467-937X.2009.00578.x.
Wang, Xiaolei, and Tomasz Woźniak. 2025. “Bayesian Analyses of Structural Vector Autoregressions with Sign, Zero, and Narrative Restrictions Using the r Package bsvarSIGNs.” University of Melbourne Working Paper, 1–21. https://doi.org/10.48550/arXiv.2501.16711.

1. University of Klagenfurt, mailto:sthaan@edu.aau.at↩︎

2. We suppress the intercept of the equation.↩︎

3. Because we might end up rejecting many samples, a potentially useful feature is the possibility to cheaply generate multiple structural parameter samples for each reduced form parameter sample by passing the parameter `randomized_max_rotations_per_sample` to the method `irf`. However, one should be aware that this can only help with identification uncertainty, not the uncertainty in the reduced form estimates. In this example, the rotation is uniquely determined and the effective sample size will not increase.↩︎

4. Note that the dataset `usmacro_growth` contains log-differences, not the levels of `GDPC1`. To see why the restriction above implies no long-run effects on the level, let \[\begin{equation*} y_t := \log(\text{gdp}_t) - \log(\text{gdp}_{t-1}). \end{equation*}\] For any finite horizon \(H < \infty\), summing up the impulse responses to the first factor shock \(f_{1,t}\) gives us \[\begin{equation*} \sum_{h=0}^{H}\frac{\partial y_{t+h}}{\partial f_{1,t}} = \frac{\partial}{\partial f_{1,t}} \sum_{h=0}^{H} y_{t+h} = \frac{\partial}{\partial f_{1,t}} \left(\log(\text{gdp}_{t+H}) - \log(\text{gdp}_{t-1}) \right) = \frac{\partial \log(\text{gdp}_{t+H})}{\partial f_{1,t}}. \end{equation*}\] The restriction on \(\text{IR}_\infty\) now requires the left-hand side of the equation above to converge to zero as \(H \rightarrow \infty\).↩︎