Calculate the Kwiatkowski-Phillips-Schmidt-Shin (KPSS) test for stationarity, per asset.

KPSS is the natural complement to the Augmented Dickey-Fuller test: where the ADF null hypothesis is that the series HAS a unit root, the KPSS null hypothesis is that the series IS stationary, with a unit root as the alternative. Running both together is standard practice to triangulate a confident conclusion – ADF rejecting a unit root and KPSS failing to reject stationarity together give a confident stationarity conclusion, while the two tests disagreeing flags an ambiguous case.

The formula is as follows:

\[\text{Yₜ} = \alpha + \text{eₜ} \;\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}\] \[\text{Sₜ} = \operatorname{Σ}(i = 1..t) \text{êᵢ}\] \[\text{KPSS} = \operatorname{Σ}(t = 1..n) \text{Sₜ} ^{2} / (n ^{2} \cdot \lambda ^{2})\] \[\lambda ^{2} = (1 / n) \cdot \text{Σêₜ} ^{2} + (2 / n) \cdot \operatorname{Σ}(s = 1..l) (1 - s / (l + 1)) \cdot \operatorname{Σ}(t = s + 1..n) \text{êₜ} \cdot \text{êₜ₋ₛ},\;\; \text{with}\; l = \text{lags} \;\text{or},\;\; \text{by default},\;\; \text{the Hobijn},\;\; \text{Franses and Ooms (2004) automatic bandwidth}\]
  • The p-value is interpolated from the KPSS (1992) critical value table, so it is bounded between 0.01 and 0.10

For more information about the method, see the following paper:

  • 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.

Also known as: KPSS test, stationarity test.

KPSS Test in Python or via the MCP

Install the Finance Toolkit with:

pip install financetoolkit -U

Then call get_kpss_test as shown below.

from financetoolkit import Toolkit

toolkit = Toolkit(
    ["^GSPC", "^N225"],
    api_key="FINANCIAL_MODELING_PREP_KEY",
    start_date="2021-01-01",
    end_date="2025-12-31",
)

toolkit.econometrics.get_kpss_test()

Or, after setting up the Finance Toolkit MCP, ask:

Were the S&P 500 and the Nikkei 225 stationary from 2021 to 2025, according to the KPSS test?

Which returns:

  ^GSPC ^N225
KPSS Statistic 4.73448 4.79639
P-Value 0.01 0.01
Lags Used 21 21
Observations 1299 1298
Critical Value 1% 0.739 0.739
Critical Value 2.5% 0.574 0.574
Critical Value 5% 0.463 0.463
Critical Value 10% 0.347 0.347
Reject Stationarity (5%) 1 1

Using Your Own Data

get_kpss_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_kpss_test()

Parameters

get_kpss_test accepts the following parameters.

ParameterTypeDescriptionExample
periodstrThe data frequency (daily, weekly, monthly, quarterly, or yearly). Defaults to “daily”."weekly"
columnstrThe historical data column to test. Defaults to “Adj Close”."Return"
regressionstrWhich deterministic term to remove before testing, one of “c” (constant, level-stationarity) or “ct” (constant and trend, trend-stationarity). Defaults to “c”."ct"
lagsintThe truncation lag for the long-run variance estimate. Defaults to statsmodels’ automatic (Hobijn, Franses & Ooms, 2004) bandwidth selection.8
include_benchmarkboolWhether to include “Benchmark” among the assets tested. Defaults to False.True
roundingint | NoneThe number of decimals to round the results to. Defaults to None.2
Share