3. Structural VAR Modeling
An svar_model object represents a (possibly
Markov-switching) structural vector autoregression – the
structural form is parameterized and estimated directly, so
there is no separate “estimate a reduced form, then rotate it”
step. Almost everything else (data handling, estimation options,
forecasting, decompositions, fan charts, bootstrap, Bayesian
estimation, adding regime switching) works exactly as for
reduced-form VARs; see Reduced-form VAR Modeling for the full
worked example. This page covers what is specific to the
structural case.
3.1. The model
with \(r_{t} = 1, 2, \dots, h\) and transition probabilities \(p_{r_{t}, r_{t+1}}(I_{t})\), and structural shocks \(\varepsilon_{t} \sim N(0, I)\).
\(A_{0}(r_{t})\) is the contemporaneous-impact matrix. It is normalized to have a unit diagonal (
a0_i_i = 1), which fixes the scale of each structural shock.\(A_{1}, \dots, A_{p}\) are the lag-coefficient matrices, and \(C\) the coefficients on the deterministic / exogenous block \(x_{t}\) (constant, declared exogenous regressors, and lags of \(y\)).
The estimated parameters are named by analogy with the matrices:
a0(row, col)– contemporaneous coefficients (off-diagonal entries of \(A_{0}\); the diagonal is fixed at1).a1(row, col), …,ap(row, col)– lag coefficients (a(row, col), with the lag index omitted, refers to all lags).c(row, col)– coefficients on the exogenous / constant block.
row and col are integers or endogenous-variable names,
e.g. a0(R, PAI) or a1(2, 3).
3.2. Creating an SVAR
endog = {'PAIOIL','GROWTH','PAI','R','EXRATE'};
exog = {};
nlags = 4;
const = true;
mdl = svar_model(endog, ...
lag_length = nlags, ...
constant_term = const, ...
deterministic_vars = exog);
(The factory mirrors rfvar_model’s shape; the legacy
constructor signature was svar(varlist, exog, nlags, constant,
markov_chains) positionally.)
3.3. Identification
A structural VAR with \(n\) endogenous variables has
\(n(n - 1)/2\) more free parameters in \(A_{0}\) than
the data can pin down, so identifying restrictions must be
supplied. In RISE these are ordinary parameter restrictions on
a0 (and, if you wish, on the lag coefficients), passed to
estimate in the linear-restrictions cell array – the same
mechanism used for block-exogeneity restrictions in the
reduced-form VAR chapter.
A recursive (Cholesky-type) identification orders the variables and zeroes the entries of \(A_{0}\) above the diagonal, so that variable 1 is not affected contemporaneously by any other shock, variable 2 only by shock 1, and so on:
linres = {};
for ii = 1:numel(endog)
for jj = ii+1:numel(endog)
linres{end+1, 1} = sprintf('a0(%s,%s)=0', endog{ii}, endog{jj}); %#ok<SAGROW>
end
end
Exclusion (zero) restrictions can equally be imposed one at a
time, e.g. 'a0(PAIOIL,R)=0' (“the policy-rate shock has no
contemporaneous effect on oil-price inflation”), and you can mix
them with restrictions on the lag coefficients
('a1(PAIOIL,GROWTH)=0', …).
3.4. Estimation
Estimation is exactly as for a reduced-form VAR – pass the model, a database of time series (see Forecasting and simulation), the estimation sample, an (optional) prior, and the identifying restrictions:
mdlest = estimate(mdl, ...
data = db, ...
estim_start_date = date2serial(db.GROWTH.start), ...
estim_end_date = date2serial(db.GROWTH.finish), ...
estim_linear_restrictions = linres);
Bayesian estimation uses the same var_priors.minnesota
factory introduced in Reduced-form VAR Modeling:
var_prior = var_priors.minnesota(endog, const, exog, nlags, ...
tightness = 0.1, ...
lag_decay = 1.0, ...
ar_first_lag = 0.9);
mdlest_bayes = estimate(mdl, ...
data = db, ...
estim_start_date = date2serial(db.GROWTH.start), ...
estim_end_date = date2serial(db.GROWTH.finish), ...
estim_var_priors = var_prior, ...
estim_linear_restrictions = linres);
After estimation, inspect the structural form:
print_structural_form(mdlest)
3.5. Impulse responses, decompositions, forecasting
Because the model is already structural, no identification
function is needed: the shock names are simply the structural
shocks (one per endogenous variable, by RISE’s naming convention),
and irf / variance_decomposition /
historical_decomposition / forecast are called directly:
myirfs = irf(mdlest); % all shocks, default horizon
myirfs = irf(mdlest, shock_names, 40);
vd = variance_decomposition(mdlest);
hd = historical_decomposition(mdlest);
fkst = forecast(mdlest, db, date2serial('2003Q1'));
For plotting (quick_irfs, plot_fanchart, plot_decomp,
…), parameter uncertainty via bootstrap, Bayesian posterior
sampling, fan charts of the decompositions and IRFs, and
conditional forecasting, see Reduced-form VAR Modeling – the calls
are identical, with a0 / a1 / … parameters in place of
the reduced-form b1 / b2 / … ones, and without the
extra Rfunc (identification) argument.
3.6. Adding regime switching
Pass a Markov-chain structure to the factory and list the
parameters it controls – for an SVAR these are typically a0
(switching contemporaneous transmission) and/or a1, …,
ap:
mc = struct();
mc.name = 'policy';
mc.number_of_states = 2;
mc.controlled_parameters = {'a0(R,:)'};
mc.endogenous_probabilities = [];
mc.probability_parameters = [];
mdl = svar_model(endog, ...
lag_length = nlags, ...
constant_term = const, ...
deterministic_vars = exog, ...
markov_chains = mc);
Time-varying transition probabilities are specified exactly as in
Reduced-form VAR Modeling (an endogenous_probabilities
definition plus the probability_parameters that enter it),
and the switching parameters are given priors through
estim_priors.
Proxy / instrumental SVARs are handled by the related Proxy (instrumental) SVAR Modeling object, and panels of (structural) VARs by the Panel VAR Modeling object.