DynamicNelsonSiegel#

class cultivars.multivariate.reduced_form.term_structure.DynamicNelsonSiegel(panel, maturities, *, decay=None)[source]#

One-step maximum-likelihood dynamic Nelson-Siegel estimation.

The Diebold-Rudebusch-Aruoba state space: level, slope and curvature follow diagonal autoregressions around their means with a full innovation covariance, curves observe them through the Nelson-Siegel loadings at the panel’s maturities with per-maturity measurement noise, and the decay \(\lambda\) is either estimated with everything else or held at a supplied value. The parameter vector – \(\log\lambda\) when free, the three means, the three tanh-bounded persistences, the six entries of a log-diagonal Cholesky factor and the \(p\) log measurement variances – is maximized from the Diebold-Li two-step estimate as the warm start, with the decay seeded where the curvature loading peaks at the median maturity.

Variables:
  • _panel – The validated (nobs, p) yield panel, nan where missing.

  • _maturities – The validated (p,) maturities.

  • _fixed_decay – The decay to hold fixed, or None to estimate it.

See also

References

Diebold, F. X., & Li, C. (2006). Forecasting the term structure of government bond yields. Journal of Econometrics, 130(2), 337-364.

Diebold, F. X., Rudebusch, G. D., & Aruoba, S. B. (2006). The macroeconomy and the yield curve: A dynamic latent factor approach. Journal of Econometrics, 131(1-2), 309-338.

Example

>>> import numpy as np
>>> from cultivars.engine._core._polynomials import _nelson_siegel_loadings
>>> rng = np.random.default_rng(0)
>>> taus = np.array([0.25, 1.0, 2.0, 5.0, 10.0])
>>> basis = _nelson_siegel_loadings(taus, 0.6)
>>> f = np.zeros((120, 3))
>>> mu = np.array([5.0, -1.5, 0.5])
>>> f[0] = mu
>>> for t in range(1, 120):
...     f[t] = mu + 0.9 * (f[t - 1] - mu) + 0.2 * rng.standard_normal(3)
>>> curves = f @ basis.T + 0.05 * rng.standard_normal((120, 5))
>>> res = DynamicNelsonSiegel(curves, taus, decay=0.6).fit()
>>> bool(np.corrcoef(res.level, f[:, 0])[0, 1] > 0.95)
True

Methods#

fit()

Maximize the exact likelihood from the two-step warm start.