Stationarity (ADF & KPSS)
Stationarity (ADF & KPSS Tests)
Definition
Core Statement
A time series is Stationary if its statistical properties (mean, variance, autocorrelation) do not change over time. Stationarity is a prerequisite for many time series models like ARIMA Models.
Purpose
- Determine if a time series can be modeled with standard techniques.
- Decide if differencing or other transformations are needed.
When to Use
Test for Stationarity When...
- Preparing data for ARIMA, VAR, or Granger Causality.
- Visual inspection of the series shows a trend or changing variance.
Theoretical Background
Types of Non-Stationarity
| Type | Description | Solution |
|---|---|---|
| Trend | Mean changes over time. | Differencing ( |
| Changing Variance | Volatility changes over time. | Log transform; GARCH models. |
| Seasonality | Periodic patterns. | Seasonal differencing. |
The Tests
| Test | Null Hypothesis ( |
Interpretation |
|---|---|---|
| ADF (Augmented Dickey-Fuller) | Series has a unit root (Non-Stationary). | Reject if p < 0.05: Series is stationary. |
| KPSS | Series is stationary. | Reject if p < 0.05: Series is non-stationary. |
Use Both Tests Together
| ADF Result | KPSS Result | Conclusion |
|---|---|---|
| Reject (Stationary) | Fail to Reject (Stationary) | Stationary. |
| Fail to Reject | Reject (Non-Stationary) | Non-Stationary. Difference needed. |
| Conflict | Conflict | Trend-stationary or need more investigation. |
Worked Example: Is the Trend Real?
Problem
You have a stock price series
- ADF p-value: 0.65
- KPSS p-value: 0.01
Question: Is the series stationary? Should you difference it?
Analysis:
-
ADF Test (
: Non-Stationary): . Fail to reject . - Evidence suggests Non-Stationary.
-
KPSS Test (
: Stationary): . Reject . - Evidence suggests Non-Stationary.
-
Conclusion:
- Both tests agree. The series has a Unit Root.
- Action: Apply First Difference (
).
-
Re-Test (After Differencing):
- New ADF
. New KPSS . - Now it is stationary.
- New ADF
Assumptions
Limitations
Pitfalls
- Trend Stationarity vs Difference Stationarity: ADF assumes a stochastic trend suitable for differencing. If the trend is deterministic (e.g., a straight line
), differencing introduces overdifferencing artifacts. - Structural Breaks: A sudden crash (like 2008 financial crisis) is often interpreted by ADF as non-stationarity. Using standard ADF here is wrong; use Zivot-Andrews Test instead.
- Seasonality: A strong seasonal cycle can look like non-stationarity. Remove seasonality before testing.
Python Implementation
from statsmodels.tsa.stattools import adfuller, kpss
# ADF Test
adf_result = adfuller(series, autolag='AIC')
print(f"ADF Statistic: {adf_result[0]:.4f}")
print(f"ADF p-value: {adf_result[1]:.4f}")
# KPSS Test
kpss_result = kpss(series, regression='c')
print(f"KPSS Statistic: {kpss_result[0]:.4f}")
print(f"KPSS p-value: {kpss_result[1]:.4f}")
# Interpretation
if adf_result[1] < 0.05 and kpss_result[1] > 0.05:
print("Series is STATIONARY.")
elif adf_result[1] > 0.05 and kpss_result[1] < 0.05:
print("Series is NON-STATIONARY. Apply differencing.")
R Implementation
library(tseries)
# ADF Test
adf.test(series)
# KPSS Test
kpss.test(series, null = "Level")
# Interpretation:
# ADF p < 0.05 AND KPSS p > 0.05 -> Stationary.
Interpretation Guide
| Test | p-value | Meaning |
|---|---|---|
| Test | p-value | Meaning |
| ------ | --------- | --------- |
| ADF | 0.02 | Reject |
| ADF | 0.35 | Fail to reject: Unit Root (Non-Stationary). |
| KPSS | 0.10 | Fail to reject: Stationary. |
| KPSS | 0.01 | Reject: Non-Stationary. |
| Conflicting | ADF > 0.05 & KPSS < 0.05 | Non-Stationary. Difference it. |
| Conflicting | ADF < 0.05 & KPSS > 0.05 | Stationary. Use as is. |
Related Concepts
- ARIMA Models - Requires stationarity.
- Differencing - Transformation to achieve stationarity.
- GARCH Models - For non-constant variance.