History modes¶
Before the forecast starts, the agents learn over the history, from beliefs.init.date to
the forecast origin. Most model variables are not observed, so the toolbox needs estimates of
the past states. history.mode decides where they come from. RE stands for rational
expectations.
| Option | Values (default first) | Meaning |
|---|---|---|
history.learn |
true, false |
Learn over the history; false = the initial beliefs and shares apply at the origin |
history.mode |
're_smoother', 'inversion', 'kalman' |
The RE model's filter or smoother; the history backed out with the learning model; a time-varying Kalman filter of the learning model |
history.re_states |
'smoothed', 'filtered' |
're_smoother' only: two-sided smoother or one-sided filter (Timing). Project baseline: 'filtered' |
history.realtime |
false, true |
're_smoother' only: RE filter on data up to the origin only (Timing); ignored under 'inversion' and 'kalman' |
history.inversion.start |
[] |
First inversion quarter; [] = beliefs.init.date |
history.inversion.shocks |
{} |
Shocks backed out; {} = every transition shock |
history.kalman.init |
'stochastic', 'smoothed' |
'kalman' only: start from the asymptotic distribution of the first quarter's model, or at beliefs.init.date from the RE-smoothed state |
're_smoother': learn on the RE estimates (default)¶
The RE model is filtered and smoothed once over the whole sample (hetlearn.re_filter, cached
in models/<name>/generated/refilter_*.mat). Each history quarter, the RE agents' forecasts,
the learners' data and the realized values in the forecast errors are read from that output;
beliefs and shares are updated, and the model with the new beliefs is solved only to apply the
projection facility. The data are not re-explained by the learning model. This is the mode of
every application except 6.
'inversion': back out the history with the learning model¶
One quarter at a time, from history.inversion.start, the learning model in force that
quarter explains the data: the observables are exogenized, the shocks endogenized, and then
beliefs and shares are updated on the resulting states. The history is real time by
construction (quarter t uses data up to t). It needs at least as many shocks as observables.
function cfg = a6_inv_learn()
cfg = a6_smooth_learn(); % a1_learn with origin 2026Q2
cfg.id = 'a6_inv_learn';
cfg.history.mode = 'inversion';
cfg.history.re_states = 'smoothed'; % required: 'filtered' is an error with 'inversion'
cfg.compare_with = {'a6_smooth_learn'};
end
Options:
cfg.history.inversion.start = qq(1985, 1); % start later; the RE smoother before it
cfg.history.inversion.shocks = {'ea', 'eb', 'eg', 'eqs', 'em', 'epinf', 'ew'}; % SW07: all seven
Under the RE model the inversion equals the RE smoother (to 2e-13 for the Smets and Wouters
(2007) model, SW07). In quarters where every observable is missing (SW07, the COVID-19 quarters
2020Q1-2020Q3) there is nothing to exogenize, so from 2020 on the inverted RE history no longer
equals the smoother. The backed-out model parameters of each quarter are kept in the result,
and hetlearn.decompose uses them.
In the project, the inversion reproduces the seven SW07 observables over 1966Q1-2026Q2 to 4e-15, and the learners' share at the end of 2022Q2 is 0.811 against 0.591 on the filtered RE history (Application 6).
'kalman': a time-varying Kalman filter of the learning model¶
Each quarter, the model with the beliefs and shares from the end of the quarter before is solved, and the Kalman filter predicts and updates with that quarter's data (a quarter without data is a prediction only). The agents then learn from the filtered values in real time. This gives one-step prediction errors and a log likelihood of the learning model.
function cfg = a6_kalman_learn()
cfg = a6_smooth_learn();
cfg.id = 'a6_kalman_learn';
cfg.history.mode = 'kalman';
cfg.history.re_states = 'smoothed'; % required: 'filtered' is an error with 'kalman'
cfg.compare_with = {'a6_kalman_re'};
end
res = hetlearn.run(a6_kalman_learn(), 'save', false);
T = hetlearn.engine.kalman_history('rmse', res); % RMSE by observable and subsample, log likelihood
res.kalman % predictions, errors, F_t, l_t, filtered and predicted data
cfg = a6_kalman_learn(); cfg.id = 'a6_kalman_smoothed_start';
cfg.history.kalman.init = 'smoothed'; % start at beliefs.init.date from the RE-smoothed state
What the agents see in the Kalman history: a forecast made in t with data to t-1 uses the
prediction \(x_{t|t-1}\); a forecast with period-t data uses \(x_{t|t}\); realized values and
regressors of the perceived laws of motion are the filtered values as they were when each
quarter was filtered, not revised later. Before beliefs.init.date the model is the RE limit.
The forecast starts from the filtered state at the origin.
A saved run writes results/<id>/kalman_errors.csv: date, number of observables, the
log-likelihood contribution, and the error, prediction and variance of each observable.
In the project the learning model fits inflation better than the RE model one quarter ahead, with a higher likelihood (Application 6); the seven further expectation rules are compared the same way.
No learning over the history¶
cfg = a1_learn(); cfg.id = 'a1_nolearn';
cfg.history.learn = false; % initial beliefs and shares apply at the origin
With history.learn = false the beliefs at the origin are the initial beliefs (RE moments by
default), and the share is shares.init_n2. Combined with beliefs.init.method = 'user' it
imposes beliefs at the origin (Initial beliefs).
'inversion' and 'kalman' need history.learn = true.
Which mode to use¶
| Purpose | Mode |
|---|---|
| Forecasts and scenarios from a given origin, comparable to the RE forecast | 're_smoother' |
| A history consistent with the learning model, shocks for a decomposition under learning | 'inversion' |
| In-sample fit: one-step errors and a likelihood of the learning model | 'kalman' |