UnobservedComponentsResult#

class cultivars.univariate.unobserved_components.UnobservedComponentsResult(*, endog, trend, has_cycle, seasonal_period, sigma2_irregular, sigma2_level, sigma2_slope, cycle_rho, cycle_freq, sigma2_cycle, sigma2_seasonal, llf, nobs, n_params, _smoothed_state, _smoothed_state_cov, _slices)[source]

Bases: _SummaryMixin, _SeriesMixin, _ComparisonMixin

A fitted structural decomposition: components, variances and bands.

The observed series is the sum of unobserved components, each with its own dynamics and its own innovation,

\[y_t = \mu_t + \psi_t + \gamma_t + \varepsilon_t, \qquad \varepsilon_t \sim N(0, \sigma^2_\varepsilon),\]

where the trend \(\mu_t\) is a local level \(\mu_{t+1} = \mu_t + \eta_t\), a local linear trend \(\mu_{t+1} = \mu_t + \beta_t + \eta_t\), \(\beta_{t+1} = \beta_t + \zeta_t\), or the smooth trend that sets \(\eta_t \equiv 0\) so the level is an integrated random walk; the cycle is the damped rotation

\[\begin{split}\begin{pmatrix} \psi_{t+1} \\ \psi^*_{t+1} \end{pmatrix} = \rho \begin{pmatrix} \cos\lambda_c & \sin\lambda_c \\ -\sin\lambda_c & \cos\lambda_c \end{pmatrix} \begin{pmatrix} \psi_t \\ \psi^*_t \end{pmatrix} + \begin{pmatrix} \kappa_t \\ \kappa^*_t \end{pmatrix}, \qquad 0 < \rho < 1,\end{split}\]

with period \(2\pi / \lambda_c\); and the seasonal is the trigonometric form, one such rotation without damping at each harmonic \(\lambda_j = 2\pi j / s\), \(j = 1, \ldots, \lfloor s/2 \rfloor\), every harmonic sharing one innovation variance \(\sigma^2_\omega\). Everything is estimated by exact maximum likelihood through the Kalman filter, and every component path reported here is the full-sample smoothed estimate \(E[\cdot \mid y_1, \ldots, y_n]\) with its smoothed standard deviation, so the bands widen at both ends of the sample – the behaviour an ad-hoc filter hides.

The record is immutable; it carries the smoothed state and its covariance privately and rebuilds the system matrices on demand, so the component properties, state_space, forecast and simulate all read the same fitted variances. Information criteria, the summary and the likelihood-ratio test come from the mixins.

Note

The likelihood is exact Gaussian under an approximate-diffuse initialization: the nonstationary states (level, slope, seasonal) start with variance 1e6 and the cycle starts at its stationary covariance. llf is therefore comparable across specifications on the same sample – the ranking the information_criteria express – but differs from an exact-diffuse likelihood by a constant that depends on the number of diffuse states, so it should not be compared with likelihoods from software that uses the exact-diffuse initialization. The cycle frequency is estimated on (0.05, pi - 0.05), so the cycle period lies between about two and about 126 observations; a slower swing is absorbed by the trend. n_params counts the variances and the two cycle shape parameters – 2 for a local level, 3 for a local linear trend, 2 for a smooth trend, plus 3 for the cycle and 1 for the seasonal.

Variables:
  • endog – The observed series, shape (n,).

  • trend – The trend specification ("level", "lltrend" or "smooth").

  • has_cycle – Whether a damped stochastic cycle was estimated.

  • seasonal_period – The trigonometric seasonal period, or None.

  • sigma2_irregular – The irregular (observation noise) variance \(\sigma^2_\varepsilon\).

  • sigma2_level – The level innovation variance \(\sigma^2_\eta\), or None for the smooth trend, whose level has no innovation of its own.

  • sigma2_slope – The slope innovation variance \(\sigma^2_\zeta\), or None for the local level.

  • cycle_rho – The cycle damping \(\rho\), or None.

  • cycle_freq – The cycle frequency \(\lambda_c\) in radians per observation, or None.

  • sigma2_cycle – The cycle innovation variance \(\sigma^2_\kappa\), or None.

  • sigma2_seasonal – The seasonal innovation variance \(\sigma^2_\omega\), or None.

  • llf – The exact Gaussian log-likelihood at the optimum.

  • nobs – The number of observations.

  • n_params – The number of free parameters the likelihood was maximized over.

See also

References

Harvey, A. C. (1989). Forecasting, Structural Time Series Models and the Kalman Filter. Cambridge University Press, chs. 2 and 4.

Durbin, J., & Koopman, S. J. (2012). Time Series Analysis by State Space Methods (2nd ed.). Oxford University Press, ch. 3.

Example

A local level recovered from a noisy random walk, then a level plus a stochastic cycle whose period is read off the fit:

>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> n = 300
>>> level = np.cumsum(0.1 * rng.standard_normal(n))
>>> y = level + 0.5 * rng.standard_normal(n)
>>> res = UnobservedComponents(y, trend="level").fit()
>>> res.trend, res.has_cycle, res.seasonal_period, res.nobs, res.n_params
('level', False, None, 300, 2.0)
>>> bool(abs(res.sigma2_irregular - 0.25) < 0.1), bool(res.sigma2_level < 0.05)
(True, True)
>>> bool(np.mean((res.level - level) ** 2) < np.mean((y - level) ** 2))
True
>>> rng = np.random.default_rng(3)
>>> n = 300
>>> rho, freq = 0.95, 2 * np.pi / 20
>>> rotation = rho * np.array([[np.cos(freq), np.sin(freq)], [-np.sin(freq), np.cos(freq)]])
>>> cycle = np.zeros((n, 2))
>>> for t in range(1, n):
...     cycle[t] = rotation @ cycle[t - 1] + 0.3 * rng.standard_normal(2)
>>> walk = np.cumsum(0.05 * rng.standard_normal(n))
>>> y = walk + cycle[:, 0] + 0.3 * rng.standard_normal(n)
>>> res = UnobservedComponents(y, cycle=True).fit()
>>> bool(abs(res.cycle_period - 20) < 2), bool(abs(res.cycle_rho - 0.95) < 0.05)
(True, True)
>>> bool(np.corrcoef(res.cycle, cycle[:, 0])[0, 1] > 0.9)
True

Private attributes#

_smoothed_state

The smoothed state path, shape (n, m).

_smoothed_state_cov

The smoothed state covariances, shape (n, m, m).

_slices

Component name to state-index range.

_params

The parameter record, rebuilt for the system builder.

Private methods#

_comparison_label()

Specification label used when this result appears in a ranking.

_component(name)

One component's smoothed path, or a refusal naming what exists.

_component_std(name)

One component's smoothed standard deviation path.

_from_fit(fit, model)

Assemble the public result from a raw fit and its specification.

_series()

Aligned per-observation output: the decomposition itself.

_summary_table()

Structured summary rendered by every display path.