KPSS

This function applies the Kwiatkowski-Phillips-Schmidt-Shin (KPSS) test for stationarity.

Unlike the ADF test, the KPSS null hypothesis is stationarity (around a level or trend), and the alternative is a unit root.

The output includes the KPSS statistic, p-value, selected lag truncation, and reference critical values.

Excel Usage

=KPSS(x, kpss_regression, nlags, store)
  • x (list[list], required): Time-series observations as a 2D range.
  • kpss_regression (str, optional, default: “c”): Null hypothesis type, c for level-stationary or ct for trend-stationary.
  • nlags (str, optional, default: “auto”): Lag selection mode (auto or legacy) or an integer provided as text.
  • store (bool, optional, default: false): Return result storage object in addition to scalar outputs.

Returns (list[list]): 2D key-value table summarizing KPSS statistics and critical values.

Example 1: KPSS with automatic lag selection and level stationarity null

Inputs:

x kpss_regression nlags store
1 1.1 1.05 1.08 1.03 1.09 1.04 1.1 1.06 1.11 c auto false

Excel formula:

=KPSS({1,1.1,1.05,1.08,1.03,1.09,1.04,1.1,1.06,1.11}, "c", "auto", FALSE)

Expected output:

Result
kpss_stat 0.5
p_value 0.0416667
lags 9
critical_10% 0.347
critical_5% 0.463
critical_2.5% 0.574
critical_1% 0.739
Example 2: KPSS with legacy lag rule and trend stationarity null

Inputs:

x kpss_regression nlags store
2 2.2 2.35 2.5 2.65 2.8 2.95 3.1 3.25 3.4 ct legacy false

Excel formula:

=KPSS({2,2.2,2.35,2.5,2.65,2.8,2.95,3.1,3.25,3.4}, "ct", "legacy", FALSE)

Expected output:

Result
kpss_stat 0.358798
p_value 0.01
lags 7
critical_10% 0.119
critical_5% 0.146
critical_2.5% 0.176
critical_1% 0.216
Example 3: KPSS with manually provided lag count

Inputs:

x kpss_regression nlags store
3 3.1 3 3.15 3.05 3.2 3.1 3.25 3.15 3.3 c 2 false

Excel formula:

=KPSS({3,3.1,3,3.15,3.05,3.2,3.1,3.25,3.15,3.3}, "c", 2, FALSE)

Expected output:

Result
kpss_stat 0.440047
p_value 0.0598935
lags 2
critical_10% 0.347
critical_5% 0.463
critical_2.5% 0.574
critical_1% 0.739
Example 4: KPSS on low-variance stationary-looking series

Inputs:

x kpss_regression nlags store
5 5.02 4.99 5.01 5 5.03 4.98 5.01 5 5.02 c auto false

Excel formula:

=KPSS({5,5.02,4.99,5.01,5,5.03,4.98,5.01,5,5.02}, "c", "auto", FALSE)

Expected output:

Result
kpss_stat 0.326271
p_value 0.1
lags 6
critical_10% 0.347
critical_5% 0.463
critical_2.5% 0.574
critical_1% 0.739

Python Code

import numpy as np
from statsmodels.tsa.stattools import kpss as sm_kpss

def kpss(x, kpss_regression='c', nlags='auto', store=False):
    """
    Run the KPSS stationarity test under level or trend null hypotheses.

    See: https://www.statsmodels.org/stable/generated/statsmodels.tsa.stattools.kpss.html

    This example function is provided as-is without any representation of accuracy.

    Args:
        x (list[list]): Time-series observations as a 2D range.
        kpss_regression (str, optional): Null hypothesis type, c for level-stationary or ct for trend-stationary. Valid options: Constant, Constant+Trend. Default is 'c'.
        nlags (str, optional): Lag selection mode (auto or legacy) or an integer provided as text. Valid options: Auto, Legacy. Default is 'auto'.
        store (bool, optional): Return result storage object in addition to scalar outputs. Default is False.

    Returns:
        list[list]: 2D key-value table summarizing KPSS statistics and critical values.
    """
    try:
        def to1d(values):
            if isinstance(values, list):
                if all(isinstance(row, list) for row in values):
                    raw = [item for row in values for item in row]
                else:
                    raw = values
            else:
                raw = [values]

            out = []
            for item in raw:
                try:
                    out.append(float(item))
                except (TypeError, ValueError):
                    continue
            return out

        if kpss_regression not in ("c", "ct"):
            return "Error: regression must be 'c' or 'ct'"

        if nlags in ("auto", "legacy"):
            nlags_arg = nlags
        else:
            try:
                parsed = int(float(nlags))
            except (TypeError, ValueError):
                return "Error: nlags must be 'auto', 'legacy', or an integer"
            if parsed < 0:
                return "Error: nlags integer must be nonnegative"
            nlags_arg = parsed

        series = to1d(x)
        if len(series) < 4:
            return "Error: x must contain at least four numeric values"

        result = sm_kpss(
            np.asarray(series, dtype=float),
            regression=kpss_regression,
            nlags=nlags_arg,
            store=store,
        )

        kpss_stat = float(result[0])
        p_value = float(result[1])
        used_lags = int(result[2])
        crit_values = result[3]

        rows = [
            ["kpss_stat", kpss_stat],
            ["p_value", p_value],
            ["lags", used_lags],
        ]

        if isinstance(crit_values, dict):
            for key in ("10%", "5%", "2.5%", "1%"):
                if key in crit_values:
                    rows.append([f"critical_{key}", float(crit_values[key])])

        return rows
    except Exception as e:
        return f"Error: {str(e)}"

Online Calculator

Time-series observations as a 2D range.
Null hypothesis type, c for level-stationary or ct for trend-stationary.
Lag selection mode (auto or legacy) or an integer provided as text.
Return result storage object in addition to scalar outputs.