hansen_threshold#

cultivars.diagnostics.nonlinearity.hansen_threshold(endog, *, order, delay=None, trim=_DEFAULT_TRIM, n_grid=_DEFAULT_GRID, replications=_HANSEN_REPLICATIONS, seed=None)[source]#

Hansen’s (1996) sup-F test of a SETAR against its linear restriction.

At every candidate threshold \(c\) on the trimmed quantile grid of \(y_{t-d}\) the two-regime regression

\[y_t = \phi_1^\top w_t\, \mathbb{1}\{y_{t-d} \le c\} + \phi_2^\top w_t\, \mathbb{1}\{y_{t-d} > c\} + e_t\]

is fitted and the \(F\) statistic for \(\phi_1 = \phi_2\) computed; the sup over the grid is the statistic and its maximizer the threshold estimate. Because \(c\) is unidentified under the null the sup has no tabulated law, and the p-value comes from replications draws in which the response is replaced by standard normal noise with the regressors and splits held fixed, Hansen’s fixed-regressor bootstrap, which reproduces the null distribution of the sup conditional on the design. Leaving delay as None searches \(d = 1, \ldots, p\) jointly, and the simulated sup ranges over the same delays so the search is paid for in the p-value. Homoskedastic errors are assumed; on 100 observations at order 1 the size is 5.5%, on 250 it is 3.5%.

Parameters:
  • endog (ArrayLike) – The series, (T,).

  • order (int) – Autoregressive order \(p\) per regime, at least 1.

  • delay (int | None) – Delay \(d\) of the threshold variable; None searches 1 .. order.

  • trim (float) – Fraction of the sorted threshold variable excluded at each end of the grid, in (0, 0.5); 0.15 by default.

  • n_grid (int) – Candidate thresholds per delay, at least 1; 300 by default.

  • replications (int) – Simulated sup statistics behind the p-value, at least 200; 1000 by default.

  • seed (int | Generator | None) – Seed or generator for the simulation.

Return type:

LinearityTest

Returns:

The LinearityTest named "Hansen sup-F" with threshold, the selected delay, and simulated critical_values set, and df=None.

Raises:
  • SpecificationError – If the order, delay, trim, grid, or replication count is unusable or the series is too short.

  • NumericalError – If a value is not finite or no admissible split exists.

Note

The threshold estimate is the least-squares one and is super-consistent under the alternative, but the record carries no interval for it; fit the SETAR for inference on the threshold. Under conditional heteroskedasticity the fixed-regressor draws should be scaled by the residuals, which is not done here, so read a rejection on ARCH residuals with that in mind.

See also

  • tsay() – the threshold test without a simulation and without a threshold estimate.

  • sup_wald() – the same sup-F construction over time rather than over a threshold variable.

  • SETAR – the model a rejection licenses.

References

Hansen, B. E. (1996). Inference when a nuisance parameter is not identified under the null hypothesis. Econometrica, 64(2), 413-430.

Hansen, B. E. (1997). Inference in TAR models. Studies in Nonlinear Dynamics & Econometrics, 2(1), 1-14.

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.

Example

A two-regime SETAR with threshold zero is rejected and the threshold located near zero; pinning the wrong delay loses the rejection:

>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> y = np.zeros(300)
>>> for t in range(1, 300):
...     slope = 0.8 if y[t - 1] <= 0.0 else -0.5
...     y[t] = slope * y[t - 1] + rng.standard_normal()
>>> verdict = hansen_threshold(y, order=1, replications=500, seed=0)
>>> verdict.reject(), bool(abs(verdict.threshold) < 0.5), verdict.delay
(True, True, 1)
>>> hansen_threshold(y, order=2, delay=2, replications=500, seed=0).reject()
False