DynamicNelsonSiegelResult.forecast#
- DynamicNelsonSiegelResult.forecast(steps)[source]#
Curve forecasts with honest standard errors.
Filters the estimation panel to the last factor state, then propagates mean and covariance through the fitted dynamics,
\[\hat f_{T+h} = \mu + \Phi\,(\hat f_{T+h-1} - \mu), \qquad P_{T+h} = \Phi P_{T+h-1} \Phi' + Q,\]and maps both through the loadings, adding the measurement variance to the yield-level spread.
- Parameters:
steps (
int) – Horizons ahead, at least 1.- Return type:
- Returns:
(mean, std)arrays of shape(steps, p)on the estimation maturities; the standard errors include factor uncertainty and measurement noise, but not parameter uncertainty.- Raises:
SpecificationError – If
stepsis not positive.
Example
>>> import numpy as np >>> from cultivars.engine._core._polynomials import _nelson_siegel_loadings >>> rng = np.random.default_rng(0) >>> taus = np.array([0.5, 2.0, 5.0, 10.0]) >>> basis = _nelson_siegel_loadings(taus, 0.6) >>> mu = np.array([5.0, -1.5, 0.5]) >>> f = np.tile(mu, (40, 1)) >>> for t in range(1, 40): ... f[t] = mu + 0.9 * (f[t - 1] - mu) + 0.2 * rng.standard_normal(3) >>> curves = f @ basis.T + 0.05 * rng.standard_normal((40, 4)) >>> res = DynamicNelsonSiegel(curves, taus, decay=0.6).fit() >>> mean, std = res.forecast(12) >>> mean.shape, std.shape, bool(np.all(std > 0.0)) ((12, 4), (12, 4), True) >>> bool(np.all(np.diff(std, axis=0) >= -1e-12)) True >>> bool(np.abs(mean[-1] - res.loadings @ res.mu).max() < 0.5) True >>> res.forecast(0) Traceback (most recent call last): cultivars.exceptions.SpecificationError: steps must be at least 1; got 0.