cultivars.univariate.smooth_transition#
Smooth-transition autoregressions: LSTAR and ESTAR.
Two linear autoregressions blended by a weight that moves continuously with a lagged value of the series,
with the logistic transition
\(G(z) = \bigl(1 + \exp(-\gamma (z - c)/s)\bigr)^{-1}\) – monotone,
so the regimes are low and high – or the exponential transition
\(G(z) = 1 - \exp(-\gamma (z - c)^2 / s^2)\) – symmetric about
\(c\), so the regimes are near and far from it. \(s\) is the
standard deviation of the transition variable, so \(\gamma\) is a
speed per standard deviation and comparable across series; as
\(\gamma \to \infty\) the logistic weight becomes an indicator and
the model is the hard-switch threshold
model with two extra parameters. Conditional on \((\gamma, c)\) the
model is linear in \((\phi_L, \phi_U)\), so estimation concentrates
the regime blocks out by least squares and searches only the two
transition parameters,
by derivative-free multi-start, because the surface is flat in \(\gamma\) away from the data and multimodal in \(c\).
Two commitments shape the surface. First, the transition is reported on
a scale a reader can judge: gamma per standard deviation with the
scale retained, and a flag, is_effectively_abrupt, raised when the
fitted speed has driven the weight to an indicator and the likelihood is
flat in gamma – the smooth model has then said nothing a
SETAR would not, and the
summary says so. Second, nonlinearity is not tested here. Under
linearity the threshold, the delay and the speed drop out of the
likelihood, so a chi-squared likelihood ratio against the linear
autoregression has no limit distribution (the Davies problem); the
result’s likelihood_ratio_test refuses, the criteria rank
specifications without testing them, and the Terasvirta linearity test
is terasvirta().
Layout. LSTAR and ESTAR fix the transition family and
delegate to _SmoothTransitionModel in _internals, which
validates order and delay through validate_order and the
family through validate_choice against
Transition; _build_objective lays out the
regressors with deterministic_columns and lag_matrix, seeds the
threshold from the best hard split over interior quantiles, and hands
a _SmoothTransitionObjective – whose least_squares is ols
from _core on the weighted blocks – to _maximize_likelihood
under Nelder-Mead. The packed _SmoothTransitionFit is assembled by
STARResult._from_fit(); the result extends
_ObservedRegimeResult, which supplies the per-regime stability
verdicts, the refusal of the likelihood-ratio test and simulate
through _simulate_two_regime, and emits its mean as a
NonlinearSSM through
NonlinearSSM._lag_stack_state_space. The hard-switch counterpart is
threshold; the latent-regime counterpart is
regime_switching; the vector form is
cultivars.multivariate.regime_switching.
References
Terasvirta, T. (1994). Specification, estimation, and evaluation of smooth transition autoregressive models. Journal of the American Statistical Association, 89(425), 208-218.
van Dijk, D., Terasvirta, T., & Franses, P. H. (2002). Smooth transition autoregressive models: A survey of recent developments. Econometric Reviews, 21(1), 1-47.
Davies, R. B. (1987). Hypothesis testing when a nuisance parameter is present only under the alternative. Biometrika, 74(1), 33-43.
Example
A smooth switch fitted three ways; the smooth model wins on BIC, the hard switch is close, and the linear fit is not in the race:
>>> import numpy as np
>>> from cultivars.univariate.autoregression import AR
>>> from cultivars.univariate.threshold import SETAR
>>> rng = np.random.default_rng(0)
>>> y = np.zeros(800)
>>> for t in range(1, 800):
... w = 1.0 / (1.0 + np.exp(-10.0 * y[t - 1]))
... y[t] = (1 - w) * (0.5 + 0.6 * y[t - 1]) + w * (-0.5 - 0.6 * y[t - 1])
... y[t] += 0.3 * rng.standard_normal()
>>> smooth = LSTAR(y, order=1).fit()
>>> hard = SETAR(y, order=1).fit()
>>> linear = AR(y, order=1).fit()
>>> bic = [fit.information_criteria.bic for fit in (smooth, hard, linear)]
>>> bool(bic[0] < bic[1] < bic[2]), bool(bic[2] - bic[0] > 400)
(True, True)
>>> smooth.is_effectively_abrupt, bool(abs(smooth.threshold - hard.threshold) < 0.2)
(False, True)
Classes#
Exponential smooth-transition autoregression. |
|
Logistic smooth-transition autoregression. |
|
A fitted smooth-transition autoregression. |