svarIrfCompute#

Purpose#

Compute posterior sign-restricted, zero-restricted, and narrative-restricted IRF, cumulative IRF, and FEVD bands from SV-BVAR draws.

Format#

sir = svarIrfCompute(result, sign_restr)#
sir = svarIrfCompute(result, sign_restr, n_ahead=20, narr_restr={}, max_tries=10000, seed=42, quiet=0, ctl={})
Parameters:
  • result (struct) – an instance of a bvarSvResult structure with posterior draws from bvarSvFit().

  • sign_restr (Nx4 matrix) –

    Nx4 matrix of sign restrictions on impulse responses. Each row specifies one restriction:

    1

    Variable index (1 to m) – the responding variable.

    2

    Shock index (1 to m) – the structural shock.

    3

    Horizon (0 = impact, 1 = one step ahead, etc.).

    4

    Sign: 1 for positive response, -1 for negative response.

  • n_ahead (scalar) – Optional keyword, number of IRF horizons to compute. Default = 20.

  • narr_restr (Nx6 matrix) –

    Optional keyword, Nx6 matrix of narrative restrictions. Each row specifies one restriction:

    1

    Type: narrative restriction type (see table below).

    2

    Variable index (1 to m).

    3

    Shock index (1 to m).

    4

    Date 1: observation index (1-indexed) for point restrictions, or start of range.

    5

    Date 2: end observation index for range restrictions (0 if unused).

    6

    Sign: 1 for positive, -1 for negative.

    Narrative restriction types:

    Type

    Name

    Meaning

    1

    shock_sign

    The structural shock j at date t has the specified sign.

    2

    shock_dominance

    Shock j is the dominant contributor to variable i at date t (its contribution exceeds all others).

    3

    decomposition_sign

    The historical decomposition contribution of shock j to variable i at date t has the specified sign.

  • max_tries (scalar) – Optional keyword, maximum number of rotation attempts per posterior draw before giving up. Default = 10000.

  • seed (scalar) – Optional keyword, RNG seed for reproducible rotation draws. Default = 42.

  • ctl (struct) –

    Optional keyword, an instance of an svarControl structure for zero restrictions and advanced settings. An instance is initialized by calling svarControlCreate() and the following members can be set:

    adv.zero_restr

    Nx3 matrix, zero restrictions on impulse responses. Each row specifies one restriction with columns:

    1

    Variable index (1 to m) – the responding variable.

    2

    Shock index (1 to m) – the structural shock.

    3

    Horizon (0 = impact, 1 = one step ahead, etc.).

    Zero restrictions are satisfied exactly by construction using the ARW2018 null-space algorithm. When zero_restr is non-empty, the algorithm is automatically set to ARW2018. Default = {} (no zero restrictions).

    adv.narrative_restr

    Nx6 matrix, narrative restrictions on the historical decomposition. Each row specifies one restriction with columns:

    1

    Type: 1 = shock_sign, 2 = shock_dominance, 3 = decomposition_sign.

    2

    Variable index (1 to m).

    3

    Shock index (1 to m).

    4

    Date 1: observation index (1-indexed), or start of range.

    5

    Date 2: end observation (0 if unused).

    6

    Sign: 1 for positive, -1 for negative.

    When narrative_restr is non-empty, the v3 narrative engine is used automatically. Default = {} (no narrative restrictions).

    adv.algorithm

    Scalar, algorithm selection. Default = 0 (auto-detect).

    0

    Auto: uses RRW2010 for pure sign, ARW2018 if zero_restr is non-empty, v3 narrative engine if narrative_restr is non-empty.

    1

    Accept-reject (RRW2010). Efficient for pure sign restrictions. Cannot handle zero restrictions.

    2

    ARW2018 null-space construction. Required for zero restrictions. Also works for pure sign restrictions.

    adv.max_tries

    Scalar, maximum rotation attempts per posterior draw. Default = 10000.

    adv.seed

    Scalar, RNG seed for reproducibility. Default = 42.

    adv.quiet

    Scalar, set to 1 to suppress printed output. Default = 0.

  • quiet (scalar) – Optional keyword, set to 1 to suppress printed output. Default = 0.

Returns:

sir (struct) –

An instance of an svarPosteriorResult structure containing:

sir.irf_median

Array of (n_ahead+1) mxm matrices, posterior median impulse responses. sir.irf_median[h+1][i, j] is the median response of variable i to shock j at horizon h.

sir.irf_bands

Array of credibleBand structures. Default length 2 (68% and 90%). Access via sir.irf_bands[1].level, sir.irf_bands[1].lower, sir.irf_bands[1].upper. Each .lower and .upper is an array of (n_ahead+1) mxm matrices.

sir.cirf_median

Array of (n_ahead+1) mxm matrices, posterior median cumulative IRF.

sir.cirf_bands

Array of credibleBand structures. Default length 2 (68% and 90%). Access via sir.cirf_bands[1].level, sir.cirf_bands[1].lower, sir.cirf_bands[1].upper. Each .lower and .upper is an array of (n_ahead+1) mxm matrices.

sir.fevd_median

Array of (n_ahead+1) mxm matrices, posterior median FEVD. Each row sums to 1.0.

sir.fevd_bands

Array of credibleBand structures. Default length 2 (68% and 90%). Access via sir.fevd_bands[1].level, sir.fevd_bands[1].lower, sir.fevd_bands[1].upper. Each .lower and .upper is an array of (n_ahead+1) mxm matrices.

sir.n_attempted

Scalar, total posterior draws attempted.

sir.n_accepted

Scalar, draws that yielded a valid rotation.

sir.accept_rate

Scalar, acceptance rate (n_accepted / n_attempted).

sir.n_ahead

Scalar, number of horizons.

sir.m

Scalar, number of variables.

sir.var_names

Mx1 string array, variable names.

Examples#

Basic Monetary Policy SVAR#

new;
library timeseries;

fname = getGAUSSHome("pkgs/timeseries/examples/data/us_macro_quarterly.csv");
y = loadd(fname, "gdp_growth + cpi_inflation + fed_funds");

// Estimate SV-BVAR
result = bvarSvFit(y, p=4, n_draws=10000, n_burn=5000, quiet=1);

// Sign restrictions for monetary policy shock
// [variable, shock, horizon, sign]
// variable and shock: 1-indexed (GAUSS convention)
// horizon: 0 = impact, 1 = one step ahead, etc.
// sign: 1 = positive, -1 = negative
sign_restr = { 3 3 0  1,       // FFR up on impact
               1 3 0 -1,       // GDP down on impact
               2 3 0 -1 };     // CPI down on impact

sir = svarIrfCompute(result, sign_restr);

print "Acceptance rate:" sir.accept_rate;

Sign + Zero Restrictions#

Combine sign restrictions with zero (exclusion) restrictions. The algorithm automatically switches to ARW2018 when zero restrictions are present:

new;
library timeseries;

fname = getGAUSSHome("pkgs/timeseries/examples/data/us_macro_quarterly.csv");
y = loadd(fname, "gdp_growth + cpi_inflation + fed_funds");

result = bvarSvFit(y, quiet=1);

// Sign restrictions
sign_restr = { 3 3 0  1,       // FFR up at impact
               1 3 0 -1 };     // GDP down at impact

// Zero restrictions: monetary shock has no
// contemporaneous effect on CPI
struct svarControl adv;
adv = svarControlCreate();
adv.zero_restr = { 2 3 0 };    // [variable, shock, horizon]

sir = svarIrfCompute(result, sign_restr, n_ahead=20, ctl=adv);

With Narrative Restrictions#

Add narrative restrictions to sharpen identification. The algorithm automatically dispatches to the v3 narrative engine:

new;
library timeseries;

fname = getGAUSSHome("pkgs/timeseries/examples/data/us_macro_quarterly.csv");
y = loadd(fname, "gdp_growth + cpi_inflation + fed_funds");

result = bvarSvFit(y, quiet=1);

// Sign restrictions
sign_restr = { 3 3 0  1,
               1 3 0 -1,
               2 3 0 -1 };

// Narrative restriction: Volcker disinflation
// Monetary shock (shock 3) was positive in 1980:Q4 (obs 84)
narr_restr = { 1 3 3 84 0 1 };
//  type=1 (shock_sign), var=3, shock=3,
//  date1=84, date2=0, sign=+1

sir = svarIrfCompute(result, sign_restr, narr_restr=narr_restr);

Oil Market SVAR with Narrative Restrictions#

new;
library timeseries;

fname = getGAUSSHome("pkgs/timeseries/examples/data/oil_market.csv");
y = loadd(fname, "oil_production + real_activity + real_oil_price");

// Estimate SV-BVAR
result = bvarSvFit(y, p=12, n_draws=10000, n_burn=5000, quiet=1);

// Sign restrictions: oil supply shock
sign_restr = { 1 1 0 -1,       // Production falls
               3 1 0  1 };      // Oil price rises

// Narrative restrictions:
// 1990:M8 (obs 200): supply shock was negative (Gulf War)
// 2008:M7 (obs 415): demand shock dominated oil price
narr_restr = { 1 1 1 200 0 -1,    // shock_sign: supply shock negative
               2 3 2 415 0  1 };   // shock_dominance: demand shock
                                   //   dominated oil price

sir = svarIrfCompute(result, sign_restr, narr_restr=narr_restr);

print "Acceptance rate:" sir.accept_rate;

Accessing Results and Plotting#

new;
library timeseries;

// ... (estimate and identify as above) ...

// Median response of GDP to monetary shock at h=5
print sir.irf_median[6, 1, 3];

// 68% band
print sir.irf_bands[1].lower[6, 1, 3] "to" sir.irf_bands[1].upper[6, 1, 3];

// Cumulative response (for differenced VARs)
print "Cumulative GDP response to monetary shock at h=20:";
print sir.cirf_median[21, 1, 3];

// FEVD: GDP variance from monetary shock at h=20
print "GDP variance share from monetary shock:";
print sir.fevd_median[21, 1, 3];

// Plot using irfPlotData
df = irfPlotData(sir, 3, 1);    // Monetary shock -> GDP
plotXY(df[., "horizon"], df[., "median"]~df[., "bands_1_lower"]~df[., "bands_1_upper"]);

Remarks#

Sign restriction format: Each row of sign_restr is {variable, shock, horizon, sign} where indices are 1-based (GAUSS convention). Multiple restrictions are stacked as rows:

sign_restr = { 3 3 0  1,
               1 3 0 -1,
               2 3 0 -1 };

Algorithm auto-dispatch: The function automatically selects the appropriate backend algorithm:

  • Pure sign restrictions: RRW2010 accept-reject (fast, Haar-uniform draws).

  • Sign + zero restrictions: ARW2018 null-space construction (exact zeros by construction).

  • Narrative restrictions present: v3 narrative engine (ADRR2018 importance-weighted accept-reject).

Override with ctl.algorithm: 0 = auto (default), 1 = accept-reject, 2 = ARW2018.

Acceptance rate: The acceptance rate (sir.accept_rate) indicates what fraction of posterior draws yielded a valid rotation. Rates below 10% suggest the restrictions may be too tight, contradictory, or implausible for the data.

SV-BVAR draws: The time-T covariance \(\Sigma_T\) is reconstructed from U and \(h_T\) for each draw, giving identification at the current volatility state rather than a time-averaged covariance.

Sign vs zero vs narrative restrictions:

  • Sign restrictions constrain the direction of impulse responses (positive or negative). They are set-identifying: many rotations satisfy the same signs, producing wide credible bands.

  • Zero restrictions constrain specific impulse responses to be exactly zero at a given horizon. They tighten identification and are enforced by algebraic construction, not accept-reject.

  • Narrative restrictions constrain the historical decomposition at specific dates, using known historical events to discipline identification. They are the most informative and produce the tightest bands.

Narrative restriction types:

  • Type 1 (shock_sign): The most basic narrative restriction. It constrains the sign of a specific structural shock at a known date. Example: the monetary policy shock was contractionary in 1979:Q4.

  • Type 2 (shock_dominance): Constrains a specific shock to be the single largest contributor to the forecast error of a given variable at the specified date. Stronger than shock_sign.

  • Type 3 (decomposition_sign): Constrains the sign of the historical decomposition contribution of a specific shock to a given variable. Useful when the event is known to have moved a variable in a particular direction.

Observation indexing: The date1 and date2 columns use 1-based observation indices matching the estimation sample. For quarterly data starting in 1960:Q1, observation 84 corresponds to 1980:Q4.

Model#

For each posterior draw \((B^{(s)}, \Sigma^{(s)})\), the function searches for a sign-satisfying rotation \(Q^{(s)}\) and computes:

  • IRF: \(\Theta_h^{(s)} = J (F^{(s)})^h J' P^{(s)} Q^{(s)}\)

  • Cumulative IRF: \(C_h^{(s)} = \sum_{\ell=0}^{h} \Theta_\ell^{(s)}\)

  • FEVD: Variance share from each shock, with posterior uncertainty

The resulting bands integrate over both parameter uncertainty (different draws) and set identification uncertainty (different valid rotations within each draw).

Algorithm#

  1. For each of n_draws posterior draws \((B^{(s)}, \Sigma^{(s)})\):

    1. Form \(L^{(s)} = \text{chol}(\Sigma^{(s)})'\).

    2. Draw random rotations \(Q\) until one satisfies all sign restrictions (accept-reject), or construct \(Q\) in the null space of zero restrictions (ARW2018).

    3. If narrative restrictions are present, apply importance-weighted accept-reject (ADRR2018).

    4. Compute IRF, cumulative IRF, and FEVD under the accepted rotation.

  2. Compute pointwise quantiles across accepted draws (median, 68%, 90% bands).

Complexity: \(O(n\_accepted \cdot h \cdot m^2 p^2 + n\_total\_tries \cdot m^3)\).

Troubleshooting#

Very low acceptance rate (< 5%): Too many restrictions for this model. Options:

  • Remove restrictions at longer horizons (keep impact only).

  • Remove restrictions on variables weakly related to the shock.

  • Use a wider credible level to see if the posterior spans both signs.

Bands are very wide: Sign restrictions are set-identifying (not point-identifying). Wide bands reflect genuine identification uncertainty. Consider adding zero or narrative restrictions to tighten identification.

Cumulative IRF is needed for differenced data: If your VAR is estimated on growth rates, the cumulative IRF gives the level response. Use sir.cirf_median instead of sir.irf_median.

Verification#

Sign-restricted posterior IRFs cross-validated against ECB BEAR bear.irfres() output and the Rubio-Ramirez, Waggoner & Zha (2010) analytical examples. Narrative restrictions verified against Antolin-Diaz & Rubio-Ramirez (2018) replication files.

References#

  • Antolin-Diaz, J. and J.F. Rubio-Ramirez (2018). “Narrative sign restrictions for SVARs.” American Economic Review, 108(10), 2802-2829.

  • Arias, J.E., J.F. Rubio-Ramirez, and D.F. Waggoner (2018). “Inference based on structural vector autoregressions identified with sign and zero restrictions: Theory and applications.” Econometrica, 86(2), 685-720.

  • Fry, R. and A. Pagan (2011). “Sign restrictions in structural vector autoregressions: A critical review.” Journal of Economic Literature, 49(4), 938-960.

  • Rubio-Ramirez, J.F., D.F. Waggoner, and T. Zha (2010). “Structural vector autoregressions: Theory of identification and algorithms for inference.” Review of Economic Studies, 77(2), 665-696.

Library#

timeseries

Source#

var.src