Phillips-Perron Test
Calculate the Phillips-Perron (PP) test for a unit root, per asset.
Phillips-Perron tests the same null hypothesis as the Augmented Dickey-Fuller test (a unit root), but corrects for heteroskedasticity and serial correlation in the errors nonparametrically via a Newey-West long-run variance estimate, rather than by adding lagged-difference terms to the regression as ADF does. PP and ADF should broadly agree on the same series since they test the same null with different correction methods.
The formula is as follows:
\[\text{Yₜ} = \alpha + \rho \cdot \text{Yₜ₋₁} + \text{uₜ} \;\text{fitted by OLS on the}\; \text{column} \;\text{level} (\text{Adj Close by default}),\;\; \text{with regression="c" (the default); "ct" adds a trend beta*t}\] \[t_{\rho} = (\text{rhô} - 1) / \operatorname{SE}(\text{rhô}),\;\; \text{γ₀} = \text{Σûₜ} ^{2} / n \;\text{and}\; s ^{2} = \text{Σûₜ} ^{2} / (n - k),\;\; \text{with k the number of coefficients}\] \[\lambda ^{2} = \text{γ₀} + 2 \cdot \operatorname{Σ}(j = 1..l) (1 - j / (l + 1)) \cdot \text{γⱼ},\;\; \text{with}\; \text{γⱼ} = (1 / n) \cdot \operatorname{Σ}(t = j + 1..n) \text{ûₜ} \cdot \text{ûₜ₋ⱼ} \;\text{and}\; l = \text{lags},\;\; \text{which defaults to int} (12 \cdot (n / 100) ^{1 / 4})\] \[Z_{t} = \sqrt{\text{γ₀} / \lambda ^{2}} \cdot t_{\rho} - (\lambda ^{2} - \text{γ₀}) / (2 \cdot \lambda \cdot s) \cdot n \cdot \operatorname{SE}(\text{rhô})\]- The unit root is rejected at 5% when Z_t is below the MacKinnon (1996) asymptotic critical value (-2.86 for “c”, -3.41 for “ct”); no p-value is reported
For more information about the method, see the following paper:
- Phillips, P.C.B., & Perron, P. (1988). “Testing for a Unit Root in Time Series Regression.” Biometrika, 75(2), 335-346.
Also known as: PP test, Z_t test.
Phillips-Perron Test in Python or via the MCP
Install the Finance Toolkit with:
pip install financetoolkit -U
Then call get_phillips_perron_test as shown below.
from financetoolkit import Toolkit
toolkit = Toolkit(
["GCUSD", "SIUSD"],
api_key="FINANCIAL_MODELING_PREP_KEY",
start_date="2021-01-01",
end_date="2025-12-31",
)
toolkit.econometrics.get_phillips_perron_test()
Or, after setting up the Finance Toolkit MCP, ask:
Did the prices of gold and silver have a unit root from 2021 to 2025, according to the Phillips-Perron test?
Which returns:
| GCUSD | SIUSD | |
|---|---|---|
| Phillips-Perron Statistic | 3.39009 | 4.5285 |
| P-Value | 1 | 1 |
| Lags Used | 23 | 23 |
| Observations | 1300 | 1300 |
| Critical Value 1% | -3.43539 | -3.43539 |
| Critical Value 5% | -2.86377 | -2.86377 |
| Critical Value 10% | -2.56796 | -2.56796 |
| Reject Unit Root (5%) | 0 | 0 |
Using Your Own Data
get_phillips_perron_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_phillips_perron_test()
Parameters
get_phillips_perron_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" |
regression | str | Which deterministic term to include, one of “c” (constant) or “ct” (constant and trend). Defaults to “c”. Note “n” (no constant) is not supported, see econometrics.unitroot_model.get_phillips_perron_test for why. | "ct" |
lags | int | The truncation lag for the Newey-West long-run variance estimate. Defaults to None, meaning the Schwert (1989) rule ceil(12 * (n / 100) ** 0.25), capped for short samples as the ADF lag search is. | 8 |
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 |