cultivars.univariate#
Univariate models: one series, its mean, its variance, and its components.
Every model here takes one observed series and answers one of three
questions about it. What drives its conditional mean: a linear
autoregression (autoregression), the
Box-Jenkins family with differencing, seasonality and regressors
(box_jenkins), long memory through a
fractional difference (fractional_integration),
a regime that switches on an observed variable, abruptly
(threshold) or smoothly
(smooth_transition), a regime that switches
on a latent Markov chain (regime_switching),
or a learned nonlinear function of the lags
(mean_function). What drives its
conditional variance: a deterministic recursion on past shocks
(conditional_variance) or a latent process
with its own innovation (stochastic_volatility).
Or what it is made of: a trend, a cycle, a seasonal and an irregular,
each with a likelihood and a band
(unobserved_components).
The models share one shape. A model object holds the specification and
nothing else; fit (or sample, for the Bayesian estimators)
returns an immutable record that carries the estimates, the fit
statistics and the aligned per-observation series, and that record is
the only thing a consumer ever reads. Every record renders the same
way (print, a notebook cell, summary().to_pandas()), exposes its
series the same way (to_pandas, to_polars), ranks against other
records fitted on the same sample with compare and
information_criteria, and – where the model has a state-space
reading – emits it as a state_space system that can
filter data it was not estimated on. Refusals are typed: a test whose
null distribution does not exist for the model raises rather than
returning a number, and a comparison across different effective samples
raises rather than ranking incomparable likelihoods.
Names are imported from the leaf module, never from here –
from cultivars.univariate.box_jenkins import ARIMA – so an import
path names the family, the specification and the class. This package
exposes only the modules.
Layout. The public classes are thin: each validates its specification
on a model base in cultivars._internals and assembles its public
record from a packed fit, while the objectives, solvers, simulators,
system builders and the shared result mixins live in _internals and
the numerical primitives in _core. Diagnostics to run before a fit
are in diagnostics; the forecast evaluation that reads
these records is in forecast; the vector counterparts
of the mean models are in multivariate.
Example
A linear and a threshold autoregression on one sample, ranked by BIC through the shared comparison surface:
>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> y = np.zeros(400)
>>> for t in range(1, 400):
... phi = 0.6 if y[t - 1] <= 0.0 else -0.4
... y[t] = phi * y[t - 1] + rng.standard_normal()
>>> linear = autoregression.AR(y, order=1).fit()
>>> hard = threshold.SETAR(y, order=1, delay=1).fit()
>>> table = linear.compare(hard, criterion="bic")
>>> [row[0] for row in table.rows]
['SETAR(1, d=1)', 'AR(1)']
>>> list(hard.to_pandas().columns)
['observed', 'fitted', 'resid', 'threshold_variable', 'regime_weight']
Modules#
Autoregressive model AR(p) -- the public specification and result. |
|
ARMA / ARIMA / SARIMA / SARIMAX -- one engine behind four public fronts. |
|
Conditional-variance models: GARCH, GJR, EGARCH, and FIGARCH. |
|
ARFIMA(p, d, q) -- fractionally integrated ARMA with long memory. |
|
Learned conditional means: AR-NN and TAR-NN. |
|
Markov-switching autoregression: the latent-regime counterpart to SETAR. |
|
Smooth-transition autoregressions: LSTAR and ESTAR. |
|
Stochastic volatility: variance as a latent state, not a function of the past. |
|
Threshold autoregressions: SETAR and TAR. |
|
Structural time series: decomposition with a likelihood. |