Zivot-Andrews Test
Calculate the Zivot-Andrews test for a unit root, per asset, allowing for a single structural break at an unknown (endogenously estimated) date.
The (A)DF/KPSS/PP tests above all assume the deterministic component of the series (its constant and/or trend) is stable throughout the sample. If a series instead has a single one-time break – e.g. a permanent level shift or a change in trend slope, such as a stock split, spin-off, or a structural shift in the business – the ordinary ADF test is biased towards not rejecting the unit root even for a genuinely (trend-)stationary series with a break. The Zivot-Andrews test corrects for this by adding a break dummy to the ADF regression and choosing, for each asset, the break date that is most favorable to the stationary alternative – which is why it needs its own (more negative) critical values rather than the ordinary ADF ones.
The formula is as follows:
\[\Delta \text{Yₜ} = \mu + \theta \cdot \text{DUₜ} + \beta \cdot t + \alpha \cdot \text{Yₜ₋₁} + \operatorname{Σ}(i = 1..p) \text{cᵢ} \cdot \Delta \text{Yₜ₋ᵢ} + \text{epsilonₜ},\;\; \text{with}\; \text{Yₜ} \;\text{the}\; \text{column} \;\text{level} (\text{Adj Close by default}) \text{and}\; \text{DUₜ} = 1 \;\text{after the break date}\; T_{B} \;\text{and}\; 0 \;\text{before it} (\text{regression} = \text{"c"},\; \text{the default})\] \[\text{regression="t" replaces theta*DUₜ by a trend break γ*DTₜ},\;\; \text{with}\; \text{DTₜ} = t - T_{B} \;\text{after the break and}\; 0 \;\text{before it},\;\; \text{and regression="ct" includes both}\] \[\text{ZA} = \text{min over}\; T_{B} \;\text{of}\; \text{alphâ} / \operatorname{SE}(\text{alphâ}),\;\; \text{searching every break date outside the first and last trim (15\% by default) of the sample}\] \[p = \text{the number of lags that minimises the AIC},\;\; \text{up to max\_lag (same default as get\_augmented\_dickey\_fuller)}\]For more information about the method, see the following papers:
- 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.
Also known as: ZA test, structural break unit root test.
Zivot-Andrews Test in Python or via the MCP
Install the Finance Toolkit with:
pip install financetoolkit -U
Then call get_zivot_andrews_test as shown below.
from financetoolkit import Toolkit
toolkit = Toolkit(
["CLUSD"],
api_key="FINANCIAL_MODELING_PREP_KEY",
start_date="2021-01-01",
end_date="2025-12-31",
)
toolkit.econometrics.get_zivot_andrews_test()
Or, after setting up the Finance Toolkit MCP, ask:
Did the price of WTI crude oil have a unit root from 2021 to 2025 once a single structural break is allowed for?
Which returns:
| CLUSD | |
|---|---|
| Zivot-Andrews Statistic | -4.1369 |
| P-Value | 0.271885 |
| Break Index | 243 |
| Observations | 1280 |
| Lags Used | 10 |
| Critical Value 1% | -5.27644 |
| Critical Value 5% | -4.81067 |
| Critical Value 10% | -4.56618 |
| Reject Unit Root (5%) | 0 |
Using Your Own Data
get_zivot_andrews_test runs on any data, not only prices: ratios, economic indicators, yield curves or your own dataset. Pass a DataFrame, a Series or a dictionary of them to Econometrics as data, with the dates in the rows or the columns, and set changes to how its changes are calculated: "percentage", "log", "difference" for rates and ratios, or None when the data are changes already. For example, for the monthly unemployment rates of the United States and Germany:
from financetoolkit import Economics, Econometrics
economics = Economics(start_date="2000-01-01")
unemployment = economics.get_unemployment_rate(
countries=["United States", "Germany"], period="monthly"
)
econometrics = Econometrics(data=unemployment, changes="difference")
econometrics.get_zivot_andrews_test()
Parameters
get_zivot_andrews_test accepts the following parameters.
| Parameter | Type | Description | Example |
|---|---|---|---|
period | str | The data frequency (daily, weekly, monthly, quarterly, or yearly). Defaults to “daily”. | "weekly" |
column | str | The historical data column to test. Defaults to “Adj Close”. | "Return" |
max_lag | int | The maximum number of lagged differences to consider when selecting the (single, reused) lag length. Defaults to the Schwert (1989) rule of thumb, capped at (n - 5) // 3 for short samples. | 12 |
regression | str | Which break to allow for, one of “c” (a break in the level/intercept), “t” (a break in the trend slope) or “ct” (both). Defaults to “c”. | "ct" |
trim | float | The fraction of observations excluded from the candidate break date search at the start and end of the sample. Must be in [0, 1/3). Defaults to 0.15. | 0.1 |
include_benchmark | bool | Whether to include “Benchmark” among the assets tested. Defaults to False. | True |
rounding | int | None | The number of decimals to round the results to. Defaults to None. | 2 |