cultivars.diagnostics.unit_roots#

Unit-root and stationarity tests: the question every model in the package asks first.

A level VAR, a cointegrating system, and a differenced ARMA are answers to one question, whether the series carries a stochastic trend, and the tests here are how that question is put to the data. The difficulty is that under a unit root the least-squares \(t\) ratio on the level does not converge to a normal but to a functional of Brownian motion,

\[t_{\gamma} \;\xrightarrow{d}\; \frac{\int_0^1 W(r)\, dW(r)}{\bigl(\int_0^1 W(r)^2\, dr\bigr)^{1/2}},\]

whose quantiles depend on the deterministic terms and sit far to the left of the normal’s, and that the alternative of interest, a root just inside the circle, is where every test in the family has least power. The tests come in two families. The Dickey-Fuller line puts the unit root under the null: adf() with its augmentation chosen on a common sample, phillips_perron() with a kernel correction instead of augmentation, dfgls() on a GLS-detrended series (Elliott, Rothenberg & Stock 1996), which recovers most of the power the OLS detrending loses near the null, and ng_perron(), whose \(M\) statistics keep size under a large negative moving-average root that inflates the others. kpss() puts stationarity under the null instead, so that a series both families fail to reject is one the sample cannot classify, which the record says rather than hides. zivot_andrews() allows one break at an unknown date, because a broken trend is the classic way a stationary series is mistaken for a unit root (Perron 1989). long_run_variance() is the kernel estimator the corrected tests divide by, exposed on its own.

Two commitments shape the surface. First, the two nulls share one record. A UnitRootTest carries lower_tail so that reject reads correctly whichever null the test put up, and a table of an ADF and a KPSS on the same series reads side by side without the reader translating tails. Second, a p-value is reported only where one exists. The Dickey-Fuller law has MacKinnon’s response surface and the KPSS table is dense enough to interpolate, and those tests carry p-values; DF-GLS, Ng-Perron, and Zivot-Andrews are known through asymptotic critical values at three levels and carry pvalue=None, so their reject reads the table and refuses a level it does not have, rather than interpolating a number that would look more precise than it is.

Every trend argument takes "n" (nothing), "c" (constant) or "ct" (constant and linear trend); KPSS, DF-GLS and Ng-Perron admit only the last two, and Zivot-Andrews always carries both and takes a model for the break instead. The trend must include every deterministic term the alternative would need, since a trending series tested against a constant alone has no power.

Layout. UnitRootTest is the record, a TabulatedTest with the trend, lags, method, and break fields; the seven functions are the producers. The numerics live in _core: _dickey_fuller_regression runs the augmented regression and _resolve_dickey_fuller_lags chooses the augmentation by AIC, BIC, the t-statistic rule, or the modified AIC on a common sample, with _schwert_max_lags as the ceiling; _mackinnon_pvalue and _mackinnon_critical_values are the response surface; _gls_detrend is the Elliott-Rothenberg-Stock detrending with the local-to-unity constants in _GLS_DETREND_C; _phillips_perron, _kpss_statistic, and _ng_perron_statistics compute their statistics, _long_run_variance and _newey_west_bandwidth the kernel estimate beneath the first two; _zivot_andrews runs the search over dates; and the KPSS, DF-GLS, Ng-Perron, and Zivot-Andrews tables are the module’s named constants, read through _critical_value_table.

References

Dickey, D. A., & Fuller, W. A. (1979). Distribution of the estimators for autoregressive time series with a unit root. Journal of the American Statistical Association, 74(366), 427-431.

Said, S. E., & Dickey, D. A. (1984). Testing for unit roots in autoregressive-moving average models of unknown order. Biometrika, 71(3), 599-607.

Phillips, P. C. B., & Perron, P. (1988). Testing for a unit root in time series regression. Biometrika, 75(2), 335-346.

Kwiatkowski, D., Phillips, P. C. B., Schmidt, P., & Shin, Y. (1992). Testing the null hypothesis of stationarity against the alternative of a unit root. Journal of Econometrics, 54(1-3), 159-178.

Elliott, G., Rothenberg, T. J., & Stock, J. H. (1996). Efficient tests for an autoregressive unit root. Econometrica, 64(4), 813-836.

Ng, S., & Perron, P. (2001). Lag length selection and the construction of unit root tests with good size and power. Econometrica, 69(6), 1519-1554.

Perron, P., & Qu, Z. (2007). A simple modification to improve the finite sample properties of Ng and Perron’s unit root tests. Economics Letters, 94(1), 12-19.

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.

MacKinnon, J. G. (1994). Approximate asymptotic distribution functions for unit-root and cointegration tests. Journal of Business & Economic Statistics, 12(2), 167-176.

MacKinnon, J. G. (1996). Numerical distribution functions for unit root and cointegration tests. Journal of Applied Econometrics, 11(6), 601-618.

Stock, J. H. (1994). Unit roots, structural breaks and trends. In Handbook of Econometrics, Volume 4 (pp. 2739-2841). North-Holland.

Example

The two families agree on a random walk and on white noise, from opposite tails; a test known only through its table carries no p-value and reads the table:

>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> walk = np.cumsum(rng.standard_normal(300))
>>> adf(walk).reject(), kpss(walk).reject()
(False, True)
>>> noise = rng.standard_normal(300)
>>> adf(noise).reject(), kpss(noise).reject()
(True, False)
>>> dfgls(walk).pvalue, dfgls(walk).reject(alpha=0.05)
(None, False)

Classes#

UnitRootTest

Verdict of a unit-root or stationarity test.

Functions#

adf(endog, *[, trend, lags, max_lags, method])

Augmented Dickey-Fuller test of a unit root.

dfgls(endog, *[, trend, lags, max_lags, method])

Elliott-Rothenberg-Stock DF-GLS test of a unit root.

kpss(endog, *[, trend, kernel, bandwidth])

KPSS test with stationarity under the null.

long_run_variance(endog, *[, kernel, bandwidth])

Kernel estimate of a series' long-run variance about its mean.

ng_perron(endog, *[, trend, lags, max_lags, ...])

Ng-Perron \(M\) tests of a unit root on a GLS-detrended series.

phillips_perron(endog, *[, trend, kernel, ...])

Phillips-Perron \(Z_t\) test of a unit root.

zivot_andrews(endog, *[, model, lags, ...])

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