Skip to content

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.

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 realised 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.

cfg = a1_learn();                         % history.mode = 're_smoother' (default)

'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 exogenised, the shocks endogenised, 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 SW07). In quarters where every observable is missing (SW07, 2020Q1-Q3) there is nothing to exogenise, 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}\); realised values and PLM regressors 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, over 1966Q1-2026Q2:

RE(t-1), a6_kalman_re Learning, a6_kalman_learn
One-step RMSE, inflation (% q/q) 0.371 0.309
Log likelihood −2182.12 −1839.75

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. Combine it with beliefs.init.method = 'user' to impose 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'