Choosing a VAR Model#

This guide helps you select the right VAR estimator and prior for your data. Start with your research question and follow the branches.

Decision Tree#

Step 1: Do you need time-varying volatility?

If your data spans a period with obvious volatility changes — e.g., quarterly macro data covering both the Great Moderation and the Global Financial Crisis of 2008 — use bvarSvFit() (stochastic volatility). Otherwise, continue to Step 2.

Step 2: How many variables?

Variables

Recommendation

Why

m = 1

arimaFit()

Univariate models are more appropriate.

m = 2-5

bvarFit() or varFit()

Standard VAR territory. BVAR is preferred for forecasting.

m = 6-20

bvarFit() with tight prior

Shrinkage is essential. Set overall_tightness = 0.01-0.1 or use bvarHyperopt().

m = 20-100

bvarSvFit() with SSVS

Large system needs variable selection to identify relevant predictors.

Step 3: Levels or growth rates?

Data

Setting

Explanation

Levels (GDP, price index)

ar = 1

Random walk prior. Variables are assumed to be persistent.

Growth rates, log-differences

ar = 0

White noise prior. Variables are assumed to be mean-reverting.

Mixed or uncertain

Use bvarHyperopt()

Let the data choose via marginal likelihood optimization.

Step 4: Do you need structural identification?

If you want to give IRFs a causal interpretation (e.g., “a monetary policy shock reduces output by X%”), you need structural identification:

Method

When to use

Cholesky (irfCompute())

You have a clear recursive ordering (fast-moving → slow-moving variables).

Sign restrictions (svarIdentify())

You want to use sign restrictions to impose economic theory (e.g., “supply shocks raise prices”).

Generalized IRF (girfCompute())

You want ordering-invariant results without structural assumptions.

If you just want forecasts and don’t need causal interpretation, skip structural identification and use reduced-form IRFs.

Quick-Start Recipes#

Recipe 1: Standard 3-variable monetary policy VAR

GDP growth, CPI inflation, federal funds rate. Quarterly data, the classic workhorse specification from Christiano, Eichenbaum & Evans (1999).

library timeseries;

// Load quarterly US macro data — loadd reads column names from the CSV header
data = loadd("macro_quarterly.csv", "gdp_growth + cpi_inflation + fed_funds");

// Estimate — draws are exact (conjugate posterior, no MCMC)
// p=4: 4 quarterly lags = 1 year of history
// ar=0: White noise prior — growth rates are mean-reverting,
//   not persistent. Use ar=1 for levels data instead.
result = bvarFit(data, p=4, ar=0);

// Cholesky IRFs: ordering matters — GDP is most exogenous, FFR most endogenous.
// The ordering in the data (GDP, CPI, FFR) implies GDP doesn't respond
// contemporaneously to monetary policy shocks.
irf = irfCompute(result, 20);   // 20 quarters = 5 years of impulse responses

Recipe 2: Large forecasting model

20+ macro variables from FRED-MD. The Minnesota prior shrinks the large parameter space, and bvarHyperopt() selects the tightness automatically via marginal likelihood (Giannone, Lenza & Primiceri 2015).

library timeseries;

data = loadd("large_macro.csv");

// Let the data choose how tight the prior should be.
// bvarHyperopt maximizes the log marginal likelihood over overall_tightness
// (and optionally soc_tightness, sur_tightness for SOC/SUR priors).
// It returns a hyperoptResult with optimal values and a pre-filled control struct.
ho = bvarHyperopt(data);

// Estimate with the optimized prior
result = bvarFit(data, ctl=ho.ctl, quiet=1);

// Forecast 8 steps ahead with posterior predictive bands
fc = bvarForecast(result, 8);

Recipe 3: Financial volatility modeling

3 asset returns with time-varying volatility. The SV-BVAR captures volatility clustering (GARCH-like behavior) in a multivariate setting, which improves density forecast calibration.

library timeseries;

data = loadd("returns.csv");

// SV-BVAR: 2 lags, white noise prior, 10K draws for reliable tail quantiles
result = bvarSvFit(data, p=2, ar=0, n_draws=10000, n_burn=5000);

// Density forecasts with time-varying volatility bands
dfc = bvarSvForecast(result, 12);

Recipe 4: Oil market SVAR with sign restrictions

Identify supply, demand, and speculative shocks in the oil market following Kilian (2009). Sign restrictions encode economic theory: e.g., a positive supply shock increases production and decreases prices.

library timeseriesecon

// Monthly oil market data: production, global activity, real oil price
data = loadd("oil_kilian.csv");

// Estimate reduced-form BVAR — matches Kilian (2009) specification
// p=24: 24 monthly lags = 2 years (oil markets have long adjustment dynamics)
// ar=0: Data is in log-differences (stationary)
result = bvarFit(data, p=24, ar=0);

// Structural identification via sign restrictions.
// Each row is: [variable, shock, horizon, sign].
//   sign: +1 = positive response required, -1 = negative
sign_restr = { 1  1  1  1,    // Var 1 (production): + to supply shock
                2  1  1 -1,    // Var 2 (activity):   + to supply, - to speculative
                3  1  1  1,    // Var 3 (price):      + to supply
                1  2  1 -1,    // Var 1 (production): - to demand shock
                2  2  1  1,    // Var 2 (activity):   + to demand
                3  2  1  1 };  // Var 3 (price):      + to demand

sir = svarIrfCompute(result, sign_restr);   // Posterior IRF bands with sign-restricted draws

// For time-varying volatility (modern extension), replace bvarFit with
// bvarSvFit and add n_draws=10000, n_burn=5000 as keyword arguments.

Function Comparison#

Function

Prior

Time-varying \(\Sigma\)

MCMC

Best for

Speed (m=3)

varFit()

None (OLS)

No

No

Quick estimation, diagnostics

< 0.001s

bvarFit()

Minnesota

No

No (conjugate)

Forecasting, model comparison

0.05-0.10s

bvarSvFit()

Minnesota

Yes (SV)

Yes (Gibbs)

Heteroskedastic data, density forecasting

1-2s (10K draws)