Skip to content

Shock decompositions

hetlearn.decompose splits the path of a variable, as a deviation from its RE steady state, into the contributions of each shock (or group of shocks), the initial conditions and, under learning, the moving perceived means.

D = hetlearn.decompose(res)                      % a result struct, default variables {'pinfobs', 'dy'}
D = hetlearn.decompose(id, vars, range, opts)    % a saved scenario id
Input Meaning
res or id A result of hetlearn.run, or a scenario id with results in results/<id>/
vars cellstr of variables; default {'pinfobs', 'dy'}
range Reporting dates, a vector or [start, end]; default every computed date
opts.groups struct of shock groups; each group is one summed component, shocks in no group stay single
opts.method 'auto' (default: 'iris' for mode 'rational', else 'tv'), 'iris', 'tv'
opts.model A preloaded struct('spec', spec, 'm', m, 'info', info) for the run's options
opts.save Write the CSV (default true)
opts.results_dir Parent folder of <id>/ (default results/)
opts.file CSV path (default results/<id>/decomposition.csv)
opts.quiet No progress line (default false)

Methods

'iris' (RE runs). IRIS contributions of the RE model, from the first date with initial conditions.

'tv' (learning runs). A time-varying linear decomposition with the model in force each quarter: the RE model where the history is the RE-smoothed one, the parameters recorded by the inversion over an inverted history, and over the forecast the beliefs and model shares in force (after the projection facility). Each shock's component is its propagation through the models in force, so slope beliefs and shares act inside every shock component. The extra component beliefs_constants is the intercept channel: the moving perceived means and their propagation.

The decomposition is additive: the components sum to the total. D.check reports the additivity error and how well the matrices rebuild the run's paths (recon_maxerr).

Example: Application 6

groups = struct('demand', {{'eb', 'eg', 'eqs'}}, 'monetary', {{'em'}}, 'supply', {{'ea'}}, ...
    'price_markup', {{'epinf'}}, 'wage_markup', {{'ew'}});
D = hetlearn.decompose('a6_inv_learn', {'pinfobs', 'dy'}, [qq(1966, 1), qq(2026, 2)], ...
    struct('groups', groups));
D.check                                          % additivity_maxerr, recon_maxerr, ...

run_applications('decompose') runs this for a6_smooth_re, a6_smooth_learn and a6_inv_learn (about 15 seconds; their results must exist).

The CSV results/<id>/decomposition.csv has the columns scenario, date, variable, component, value_model, value_report and label (with total rows); value_report is in report units (inflation annualised).

T = readtable(fullfile('results', 'a6_inv_learn', 'decomposition.csv'));
k = strcmp(T.variable, 'pinfobs') & strcmp(T.date, '2022Q2');
T(k, {'component', 'value_report'})

Restrictions

  • Results of history.mode = 'kalman' cannot be decomposed (hetlearn:options:unsupported).
  • Without the inversion, the history of a learning run is the RE history, so the learning decomposition equals the RE one before the origin (the project checks this to 1e-14).

In the project

Average contribution to inflation over 2021Q1-2023Q4 (pp, annualised; total 1.72 pp): price mark-up shocks 3.42 under the RE smoother and 6.24 in the history backed out with the learning model; the intercept channel adds 0.30 under learning. Full table: Application 6.