cultivars.univariate.autoregression#
Autoregressive model AR(p) – the public specification and result.
The model is
held under the package’s three-object discipline: AR is the
immutable specification, estimation belongs to the family base it
inherits, and ARResult is the frozen result the user actually
handles. Two estimators are reachable through method. "css"
conditions on the first \(p\) observations and solves the lagged
regression by ordinary least squares, so the likelihood is the
conditional one on \(n - p\) observations. "exact" maximizes
the exact Gaussian likelihood,
through the companion state-space embedding, with the search kept inside the stationary region by the partial-autocorrelation reparameterization of Monahan (1984): the optimizer moves in unconstrained \(\mathbb R^p\), each coordinate maps to a partial autocorrelation in \((-1, 1)\), and the Durbin-Levinson recursion turns those into coefficients whose companion roots lie inside the unit circle by construction. The two estimators differ in finite samples by the stationary density of the first \(p\) observations and converge as the sample grows.
Two commitments shape the surface. First, the effective sample is
reported, not hidden: nobs is \(n - p\) under CSS and \(n\)
under exact ML, so the information criteria are on different scales
across the two, and ARResult.compare() refuses to rank results
with differing nobs rather than silently order incomparable
numbers – to select an order, fit every candidate with "exact".
Second, the result carries what a downstream consumer needs and nothing
about how it was found: the series, the fitted and residual paths
aligned to it, the coefficients by display name, and the companion
matrix’s verdict on stationarity; simulate draws from the fitted
law with the deterministic terms handled as regressors inside the
recursion, and refuses a fit whose coefficients sum to one.
Layout. AR validates order, trend and method at
construction through validate_order and validate_choice against
the Trend and Method
aliases, and fit dispatches through _fit_family to _fit_css
or _fit_exact on the _AutoRegressionModel base in
_internals; the exact path builds an _AutoRegressionObjective
and hands it to _maximize_likelihood, with pacf_to_coeffs and
coeffs_to_pacf in _core doing the reparameterization. The
packed _AutoRegressionFit record is assembled into
ARResult by _from_fit, and _simulate_arma with the
_SIMULATION_BURN default backs simulate. The four mixins the
result composes – _SummaryMixin, _SeriesMixin,
_ComparisonMixin, _StationarityMixin – live in _internals
and are shared with every other univariate result. The
moving-average and integrated generalization is
box_jenkins; the long-memory one
fractional_integration.
References
Hamilton, J. D. (1994). Time Series Analysis, chapters 5 and 13. Princeton University Press.
Monahan, J. F. (1984). A note on enforcing stationarity in ARMA models. Biometrika, 71(2), 403-404.
Box, G. E. P., Jenkins, G. M., Reinsel, G. C., & Ljung, G. M. (2015). Time Series Analysis: Forecasting and Control, 5th ed. Wiley.
Example
Order selection the way the module intends it – every candidate fitted by exact ML so the criteria share a sample – picks the true order of a simulated AR(2):
>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> e = rng.standard_normal(600)
>>> z = np.zeros(600)
>>> for t in range(2, 600):
... z[t] = 0.5 * z[t - 1] - 0.3 * z[t - 2] + e[t]
>>> fits = {p: AR(z, order=p, method="exact").fit() for p in range(1, 5)}
>>> table = fits[1].compare(fits[2], fits[3], fits[4], criterion="bic")
>>> table.columns
('model', 'llf', 'k', 'BIC', 'dBIC')
>>> [row[0] for row in table.rows]
['AR(2)', 'AR(3)', 'AR(4)', 'AR(1)']
>>> bool(np.allclose(fits[2].ar_params, [0.5, -0.3], atol=0.05)), fits[2].is_stationary
(True, True)