cultivars.univariate.threshold#
Threshold autoregressions: SETAR and TAR.
Two linear autoregressions selected by an indicator on an observed transition variable,
with \(z_t = y_t\) for the self-exciting SETAR and an
external series for TAR. The regime is a deterministic
function of something you can see – a lag of the series, or a variable
you supply – which is what separates this family from
regime_switching, where the regime is
latent and only its filtered probability is ever recovered. Here the
regime weight is computed, not inferred, so estimation is least squares
rather than EM and the results carry the transition variable itself as
an aligned series. Because the weight is an indicator, the sum of
squares is a step function of the threshold – piecewise constant,
nowhere differentiable in \(r\) – so no gradient method can find
its minimum, and the estimator is an exhaustive search,
over a grid \(\mathcal{G}_d\) of n_grid quantiles of the
transition variable with trim of each tail removed, regime-wise
least squares at every candidate, and – when the delay is left open –
every \(d\) in 1..order on one common effective sample so the
sums of squares are comparable across delays. The threshold estimate is
super-consistent (Chan, 1993), which is why the coefficients can be
read as ordinary least squares conditional on it.
Two commitments shape the surface. First, stationarity is reported per
regime, never as a single verdict. A two-regime autoregression has no
single companion polynomial, and regime-wise stationarity is sufficient
but not necessary for the process to be globally stationary: a model
with an explosive inner regime and a contracting outer one is well
behaved, since excursions are pulled back. The result exposes
lower_stability and upper_stability and refuses to collapse
them. Second, the likelihood-ratio test is blocked outright. Under
linearity the threshold and the delay do not appear in the likelihood,
so the chi-squared limit does not hold for any test that involves them
(the Davies problem); likelihood_ratio_test raises rather than hand
back a well-formed and wrong p-value, the criteria rank specifications
without testing them, and the tests that do respect the problem are
tsay() and the bootstrap
sup-F hansen_threshold().
Layout. SETAR and TAR differ only in the transition
variable and delegate to _ThresholdModel in _internals, which
validates order, delay and n_grid through validate_order,
trim through validate_open_interval and an external variable
through validate_aligned; its _fit_family lays out the
regressors with deterministic_columns and lag_matrix, runs the
grid with ols from _core on each split, and packs a
_ThresholdFit. SETARResult extends
_ObservedRegimeResult, which supplies the per-regime stability
verdicts, the refusal of the likelihood-ratio test, the aligned series
and simulate through _simulate_two_regime; the result aligns the
transition variable with trailing_lag from _core and emits its
mean as a NonlinearSSM through
NonlinearSSM._lag_stack_state_space. The smooth-weight counterpart
is smooth_transition, of which the hard
switch is the infinite-speed limit; the neural counterpart is
TARNN; the vector form is
cultivars.multivariate.regime_switching.
References
Tong, H. (1990). Non-linear Time Series: A Dynamical System Approach. Oxford University Press.
Tsay, R. S. (1989). Testing and modeling threshold autoregressive processes. Journal of the American Statistical Association, 84(405), 231-240.
Chan, K. S. (1993). Consistency and limiting distribution of the least squares estimator of a threshold autoregressive model. Annals of Statistics, 21(1), 520-533.
Hansen, B. E. (1997). Inference in TAR models. Studies in Nonlinear Dynamics and Econometrics, 2(1), 1-14.
Davies, R. B. (1987). Hypothesis testing when a nuisance parameter is present only under the alternative. Biometrika, 74(1), 33-43.
Example
A hard switch recovered by the grid, ranked on BIC against the linear fit, with the likelihood-ratio test refused as it should be:
>>> import numpy as np
>>> from cultivars.univariate.autoregression import AR
>>> 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()
>>> hard = SETAR(y, order=1, delay=1).fit()
>>> linear = AR(y, order=1).fit()
>>> bool(hard.information_criteria.bic < linear.information_criteria.bic - 20)
True
>>> hard.is_regimewise_stationary, bool(abs(hard.threshold) < 0.3)
(True, True)
>>> hard.likelihood_ratio_test(linear)
Traceback (most recent call last):
cultivars.exceptions.SpecificationError: ...
Classes#
Self-exciting threshold autoregression with two regimes. |
|
Threshold autoregression driven by an external transition variable. |
|
A fitted hard-threshold autoregression. |