7. Entropic tilting
A survey, a nowcast, or a policymaker’s judgment says something your model cannot see. You do not want to re-estimate the model, and you certainly do not want to re-specify it. You want the forecast to respect that information and to change as little as possible otherwise.
That is entropic tilting. It takes the model’s forecast density and reweights its paths so the density satisfies your views, choosing the weights that move the density least in the Kullback–Leibler sense. The model is not touched. Only the weight on each simulated path changes.
out = rise.scenario.tilt(m, {"PAI", 4, "mean", 0.5});
Here is what it reports for a view that inflation four periods out sits half a standard deviation above the model’s own forecast, on a 2000-path, 8-period density of a small New Keynesian model (the worked example in the RISE cookbook):
Entropic tilt
----------------------------------------------------------
paths 2000 over 8 periods
moment rows (one tilt) 1
largest miss 6.500e-13
divergence from the base 0.1264
effective sample 77.9% of the paths
----------------------------------------------------------
7.1. The target vocabulary
Each view is one row of four: {variable, horizons, moment, value}.
mean the average of the variable at each horizon given
std its spread, holding the mean where the density puts it
var the same, given as a variance
pathmean one number: the average across the horizons given
terminal the value at the last horizon given
cov co-movement of a pair: {["PAI","Y"], 1:4, "cov", z}
targets = {
"PAI", 4, "mean", 0.5 % one horizon
"Y", 1:4, "mean", [0.2 0.1 0.0 -0.1] % a path
"PAI", 8, "std", 1.2 % a risk view
};
A std or var view also pins the mean at that horizon — where you put it
with a mean row, or where the density already had it. Otherwise the spread
could be met by sliding the centre, which is not what you asked for.
7.2. One tilt, never several
An ensemble of paths is a joint distribution over the whole horizon, not one density per period. So views on several horizons, or several variables, are several rows of one moment vector, solved once, giving one weight per path.
Tilting one period at a time would give each period its own weighting of the
same paths, and the resulting “density” would not be a density of anything.
tilt does not let you do that: every row you give joins the same tilt.
7.3. Reading the diagnostics
divergence from the base is what the tilt cost: the Kullback–Leibler divergence of the tilted density from the one the model produced. It is the number to compare across views.
effective sample is the fraction of the paths still carrying weight,
1 / (N * sum(w.^2)). A tilt carried by a handful of draws is noise wearing a
distribution’s clothes.
largest miss is how far the achieved moments sit from your targets.
What these show in practice, on one density:
view divergence ESS
inflation +0.5 sd at h4 0.1264 77.9%
output +0.3 sd over h1-h4 0.0716 86.7%
inflation spread x1.5 at h6 0.2049 38.6%
inflation up, output held 0.3719 39.5%
Three lessons are in that table.
A path of modest views can be cheaper than one bold point view. The four output views move together, so the density meets them without much reweighting.
Spread costs more than location. Widening the band means leaning on the tails, and the tails are thinly populated.
A view that disagrees with the model’s structure is expensive, and the divergence tells you so. In this density supply shocks dominate, so higher inflation comes with lower output — pushing inflation up alone drags output from +0.04 to −0.78. Holding output where it was while inflation rises asks for demand-driven inflation the density rarely produces, and costs three times the point view.
That last one is worth taking seriously. When a tilt is expensive, the model is telling you that your view and its mechanism disagree. Tilting will still deliver the numbers — but the next question is whether the model is missing something, which is a different rung of the ladder.
7.4. What it refuses
The solver underneath returns weights that sum to one and look well formed even
when a view is out of reach. Handed a target of 50 against an ensemble spanning
roughly [-3, +3], it put every bit of the weight on a single path and
achieved +3.2, with no indication. tilt checks, and refuses:
tiltDidNotHitTargets a view the ensemble cannot reach
effectiveSampleTooSmall the view collapses the sample below MinESS
noTargets no views given
unknownVariable a name the density does not carry
horizonOutOfRange a horizon beyond the density
targetCountMismatch values do not match horizons
unknownMoment not one of the six moments above
badTargetShape a row that is not four entries
covNeedsTwo a cov view with one variable
All carry the prefix RISE:scenario:.
7.5. Options
Nsim paths to simulate when source is a model (default 2000)
Horizon periods to simulate (default 12)
MinESS refuse below this effective-sample fraction (default 0.05)
Tolerance how closely targets must be met (default 1e-6)
Seed random seed for the simulated density
Print show the report (default true)
source may also be an ensemble already in hand, a struct of
varname -> [T x N]. Use that to tilt the same draws several ways and
compare their costs, as in the table above.
7.6. Fan charts from the result
The weights plug straight into weighted quantiles:
q = utils.entropic_tilting.weighted_quantile(draws, [0.05 0.5 0.95], out.Weights);
7.7. References
Krüger, Clark and Ravazzolo (2017), “Using entropic tilting to combine BVAR forecasts with external nowcasts”, Journal of Business & Economic Statistics 35(3), 470–485.
Robertson, Tallman and Whiteman (2005), “Forecasting using relative entropy”, Journal of Money, Credit and Banking 37(3), 383–401.
7.8. See also
Scenario plausibility — the next rung: forcing a path through the shocks, and pricing what that does to the model