zivot_andrews#

cultivars.diagnostics.unit_roots.zivot_andrews(endog, *, model='c', lags=None, max_lags=None, trimming=0.15)[source]#

Zivot-Andrews test of a unit root against a one-time break at an unknown date.

Perron (1989) showed that a stationary series with a broken trend looks like a unit root to the Dickey-Fuller test, and Zivot and Andrews made the break date endogenous. For every candidate date \(T_b\) inside the trimmed window the regression

\[\Delta y_t = \mu + \beta t + \theta\, DU_t(T_b) + \gamma\, DT_t(T_b) + \alpha\, y_{t-1} + \sum_{j = 1}^{p} \phi_j\, \Delta y_{t-j} + e_t\]

is run with the break dummies of the chosen model, \(DU\) a level shift and \(DT\) a slope change from \(T_b\) on; the statistic is the smallest \(t\) on \(y_{t-1}\) over the window, and the date that produces it is the estimated break. The null is a unit root without a break, so a rejection says “stationary around a broken trend”, not “broken unit root”. Critical values are the authors’ asymptotic ones for the minimized statistic, well to the left of the plain Dickey-Fuller values because the minimum over dates is taken; pvalue is None.

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

  • model (str) – "c" for a break in the intercept, "t" in the trend slope, "ct" in both.

  • lags (int | None) – Fixed augmentation, at least 0, or None to select once by the t-statistic rule on the no-break regression.

  • max_lags (int | None) – Largest augmentation under selection; default Schwert’s rule.

  • trimming (float) – Fraction of the sample excluded at each end, in (0, 0.5).

Return type:

UnitRootTest

Returns:

The UnitRootTest named "Zivot-Andrews" with break_index set and trend="ct", since the regression always carries a constant and a trend.

Raises:

Note

break_index is the arg-min of the statistic and is reported whether or not the null is rejected; under the null it is not an estimate of anything. The augmentation is selected once on the no-break regression and held fixed across dates, which is the authors’ procedure and keeps the search over dates comparable. The test has one break; for several, or for a break under the null as well, see the structural-break module.

See also

  • adf() – the test without a break, which this one nests.

  • sup_wald() – the break test on a stationary regression.

  • bai_perron() – several breaks.

References

Zivot, E., & Andrews, D. W. K. (1992). Further evidence on the great crash, the oil-price shock, and the unit-root hypothesis. Journal of Business & Economic Statistics, 10(3), 251-270.

Perron, P. (1989). The great crash, the oil price shock, and the unit root hypothesis. Econometrica, 57(6), 1361-1401.

Example

A trend-stationary series with a level shift at 150 looks like a unit root to ADF and is rejected here, with the break dated:

>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> t = np.arange(300)
>>> y = 0.05 * t + 5.0 * (t >= 150) + rng.standard_normal(300)
>>> test = zivot_andrews(y)
>>> test.reject(), test.break_index, test.trend
(True, 150, 'ct')
>>> adf(y, trend="ct").reject()
False