Structural Analisys of Bayesian VARs with an example using the Brazilian Development Bank

By Gabriel Vasconcelos


Vector Autorregresive (VAR) models are very popular in economics because they can model a system of economic variables and relations. Bayesian VARs are receiving a lot of attention due to their ability to deal with larger systems and the smart use of priors. For example, in this old post I showed an example of large Bayesian VARs to forecast covariance matrices. In this post I will show how to use the same model to obtain impulse response coefficients and perform structural analysis. The type of estimation was based on Bańbura et al. (2010) and the empirical application is from Barboza and Vasconcelos (2019). The objective is to measure the effects of the Brazilian Development Bank on investment. Therefore, we will measure how the investment respond to an increase in loans over the time.


A structural VAR is described by the following equation:

\displaystyle A_0y_t = v + A_1y_{t-1} + A_2y_{t-2} + \dots + A_py_{t-p} + \epsilon_t

where A_j,j=1,\dots,p are squared matrices of coefficients, v is a vector of constants, \epsilon_t is a vector of errors and y_t is the vector with all variables in the system. In this sense, y_t is not a single value like in an univariate Autorregressive model, it contains several variables that are used at the same time in the model. For example, y_t could have the GDP, investment and interest rate. In this case each matrix A_j would be 3\times 3.

In VAR models we do not estimate the equation above in a single step. First we estimate the VAR in its reduced form (this is the equation we use to compute forecasts) and then we use some identification strategy to recover the structural form. The reduced form is presented below.

\displaystyle y_t =c + B_1y_{t-1} + B_2y_{t-2} + \dots + B_py_{t-p} + \varepsilon_t

where B_j = A_0^{-1}A_j, c = A_0^{-1}v, \varepsilon_t = A_0^{-1}\epsilon_t. When we do structural analysis we want to know how some variable respond over time to a shock on some other variable. However, shocks in the reduced form are correlated between equations and can not be isolated. Therefore, an important difference between the reduced form and the structural form is that in the second the error covariance matrix is diagonal, which means uncorrelated shocks.


First we must install the lbvar package from my github:


The dataset is included in the package and it is called BNDESdata. I removed column 17 in this example because it contains a variable (capital goods prices) used only for robustness in other examples in the paper. The data is already treated and ready for the model. We are going to evaluate the effects of the Brazilian Development Bank Loans (BL) on the Gross Fixed Capital formation (GFCF), the GFCF fraction of machinery and equipment (GFCFme) and the GFCF fraction of machinery and equipment manufactured in Brazil (GFCFmeBR).

BNDESdata = BNDESdata[,-17]
colnames(BNDESdata) = c("TT", "CRB", "CDS", "WPROD", "BL", "GFCF", "GFCFme",
                        "GFCFmeBR", "GDP", "IP", "ULC", "CUR", "IR", "ICI",
                        "UNCERT", "ER", "IBOV")

Before estimating the VAR, we must define some parameters for the priors. Our prior is of a random walk for nonstationary variables and of a white noise for stationary variables. We just used a Phillips-Perron test to determine which variables are stationary and which variables are not. We set a value of 1 for the first autorregresive term of each nonstationary equation and 0 for each stationary equation.

There is another parameter we must define called \lambda>0. This parameter controls the importance we give to the prior and the importance we give to the data. Smaller values give more importance to the prior. Bańbura et al. (2010) uses a strategy to determine \lambda which consists of estimating a small VAR by OLS and Bayesian VARs for several values of \lambda. The chosen \lambda is the one that makes the big model more similar to the small model in terms of squared error. Note that the small model does not use all variables, therefore we compare only the equations included in both models.

The codes for the Phillips-Perron test and the \lambda  are presented below. I used a small range for the \lambda to save computational time given that I already knew that the best value was in this interval.

## = Phillips-Perron test
prior = apply(BNDESdata,2,function(x)pp.test(x)$p.value)
prior[prior > 0.05] = 1
prior[prior <= 0.05] = 0

## = lambda estimation
lambda = fitLambda(BNDESdata,c("GFCF","BL","IR"),
                   seq(0.6,0.65,0.0001), p=13,
                   p.reduced = 13, delta=prior)

The VAR we want to estimate has 17 variables and 13 lags. This accounts for 3774 parameters in the reduced form if we include the intercept. The name Large Bayesian VARs is very much appropriate. The code below estimates the model, computes the recursive identification (see the full article for more details) and the impulse responses. The last step requires some simulation and it may take a few minutes to run.

## == Estimate the Reduced Form == ##
model = lbvar(BNDESdata, 13, delta = prior, lambda = lambda)

## == identification == ##
ident = identification(model)

## == Impulse Responses == ##
ir = irf(model, ident, 48, unity.shock = FALSE, M=1000)

Now we can plot the impulse responses and see the results. The figures below show the effects of a shock in the bank loans on the three variations of GFCF.

plot(ir,"BL","GFCFme",alpha=c(0.05,0.1),xlim=c(0,36),ylim=c(-0.01,0.015),ylab="GFCF ME",xlab="Time",main="(b)")
plot(ir,"BL","GFCFmeBR",alpha=c(0.05,0.1),xlim=c(0,36),ylim=c(-0.01,0.015),ylab="GFCF ME-BR",xlab="Time",main="(c)")

plot of chunk unnamed-chunk-7

The effects of the bank are bigger if we move to the machinery and equipment measures because they represent a large portion of the bank’s portfolio. The responses are significant in some horizons. The shock was of one standard deviation, which accounts for a 20% increase in loans. This shock increases the GFCF by less than 2% if we look at the sum of the first 6 months. However, to understand the magnitude of this effect we must look at the fraction of the Brazilian Development Bank on total investment. Our results show that an increase of 1 BRL in loans accounts for an increase of approximately 0.46 BRL in the total GFCF. This may look like a small value first sight. We explain this results with two hypothesis. First, there is some degree of fund substitution where companies use the government bank just because interest rates are lower but they do not suffer from significant credit constraints. Second, There is a crowding-out effect because the government tends to increase the interest rate when the bank puts more money in the economy.

Finally, a good way to evaluate a VAR model in a macroeconomic framework such as this one is to look at how the variables behave in response to the monetary policy. The figures below show how the GFCF behaves when the government increases interest rates (IR).

plot(ir,"IR","GFCFme",alpha=c(0.05,0.1),xlim=c(0,36),ylim=c(-0.02,0.01),ylab="GFCF ME",xlab="Time",main="(b)")
plot(ir,"IR","GFCFmeBR",alpha=c(0.05,0.1),xlim=c(0,36),ylim=c(-0.02,0.01),ylab="GFCF ME-BR",xlab="Time",main="(c)")

plot of chunk unnamed-chunk-8


Bańbura, Marta, Domenico Giannone, and Lucrezia Reichlin. “Large Bayesian vector auto regressions.” Journal of Applied Econometrics 25.1 (2010): 71-92.

de Menezes Barboza, R., & Vasconcelos, G. F. (2019). Measuring the aggregate effects of the Brazilian Development Bank on investment. The North American Journal of Economics and Finance.

This entry was posted in R and tagged , , , , , , , . Bookmark the permalink.

7 Responses to Structural Analisys of Bayesian VARs with an example using the Brazilian Development Bank

  1. PS says:

    Thank you very much, Dr. Vasconcelos. How to determine the lag order in large VAR? Is it through the same procedure as in regular VAR (using information criteria, general-to-specific etc)?


  2. Alex says:

    interesting post. Just a remark on the code: it looks to me like you forgot to multiply with \delta_{i} in the “ps prior”, or am I overlooking something here?


    • insightr says:

      No, you are right. I forgot to push it. It is ok now. Thanks =)


      • Array says:

        also in the identification function you write: covmat_u_sqrt=diag(diag(choles)); isn’t there a sqrt() call missing? shouldn’t it be covmat_u_sqrt = diag(sqrt(diag(choles)))?


      • insightr says:

        No. That is correct. It is just a way to do identification and keep the diagonal of the A matrix as one. To check, just do
        a = solve(ident$A)%%ident$covmatu%%t(ident$A)

        and you will see that this will recover the model$covmat with a small approximation error.


  3. Rafael says:

    Do you use the same procedure of Bernanke et al.(2005) in identification using fast and slow variables, in terms of response of a shock?


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s