Skip to main content

Modified KPSS Tests for Near Integration - Harris, Leybourne, and McCabe (2007)

Project description

nearkpss

Modified KPSS Tests for Near Integration

Python 3.8+ License: MIT

A Python implementation of the Modified KPSS test for near integration proposed by Harris, Leybourne, and McCabe (2007).

Reference

Harris, D., Leybourne, S., & McCabe, B. (2007). Modified KPSS Tests for Near Integration. Econometric Theory, 23(2), 355-363. DOI: 10.1017/S0266466607070156


Overview

The Modified KPSS test addresses the problem of testing whether a strongly autocorrelated time series is best described as:

  • Near-integrated (stationary with largest root near to one), or
  • Integrated (having a unit root)

The standard KPSS test (Kwiatkowski et al., 1992) suffers from severe size distortions when applied to near-integrated processes. The Modified KPSS test resolves this issue by applying a GLS-type transformation that removes the near unit root under the null hypothesis.

Key Features

  • Exact implementation matching the Harris, Leybourne, and McCabe (2007) paper
  • Controlled asymptotic size under near-integration null hypothesis
  • Monte Carlo critical values simulation capability
  • Standard KPSS test included for comparison
  • Professional output suitable for top-tier journal publications
  • Automatic bandwidth selection using Newey-West (1994)
  • Multiple kernel functions: Quadratic Spectral (QS), Bartlett, Parzen

Installation

pip install nearkpss

Or install from source:

git clone https://github.com/merwanroudane/modifiedkpss.git
cd modifiedkpss
pip install -e .

Quick Start

import numpy as np
from nearkpss import modified_kpss_test

# Generate sample data (near-integrated process)
np.random.seed(42)
T = 200
c = 10  # Local-to-unity parameter
rho = 1 - c/T
y = np.zeros(T)
for t in range(1, T):
    y[t] = rho * y[t-1] + np.random.normal()

# Perform the Modified KPSS test
result = modified_kpss_test(y, c_bar=10.0, detrend="c")
print(result)

Output:

============================================================
        Modified KPSS Test for Near Integration
        Harris, Leybourne, and McCabe (2007)
============================================================

Null Hypothesis: The series is near-integrated (stationary)
                 H₀: c ≥ c̄ = 10.0
Alternative:     The series has a unit root (H₁: c = 0)

Detrending:      Level (constant only)
Observations:    200

------------------------------------------------------------
Test Statistic:  0.084521 
P-value:         0.6234
------------------------------------------------------------

Critical Values:
  1%:   0.7390
  5%:   0.4630
  10%:  0.3470

Estimation Details:
  Bandwidth:           5.42
  Long-run variance:   1.023456

============================================================
Conclusion: Cannot reject H₀.
           Series appears near-integrated/stationary.
============================================================

Theoretical Background

The Model

Consider the data generating process (DGP):

$$y_t = \mu + w_t, \quad t = 1, \ldots, T$$

$$w_t = \rho_{c,T} w_{t-1} + v_t, \quad t = 2, \ldots, T$$

where $\rho_{c,T} = 1 - c/T$ and $c \geq 0$. The innovation $v_t$ is a stationary process.

Hypotheses

The Modified KPSS test examines:

  • Null hypothesis: $H_0: c \geq \bar{c} > 0$ (near integration)
  • Alternative: $H_1: c = 0$ (unit root)

where $\bar{c}$ specifies the minimal amount of mean reversion under the stationary null hypothesis.

The Test Statistic

The Modified KPSS statistic is constructed by:

  1. GLS Transformation: Apply $y_t - \rho_{\bar{c},T} y_{t-1}$ where $\rho_{\bar{c},T} = 1 - \bar{c}/T$

  2. OLS Demeaning: Compute residuals $r_{\bar{c},t} = (y_t - \rho_{\bar{c},T} y_{t-1}) - \bar{m}_{\bar{c}}$

  3. Test Statistic:

$$S^{\mu}(\bar{c}) = \frac{T^{-2} \sum_{t=2}^{T} \left(\sum_{i=2}^{t} r_{\bar{c},i}\right)^2}{\hat{\omega}_{\bar{c}}^2}$$

where $\hat{\omega}_{\bar{c}}^2$ is the long-run variance estimator.

Asymptotic Distribution (Theorem 1)

Under the null hypothesis, the limiting distribution is:

$$S^{\mu}(\bar{c}) \Rightarrow \int_0^1 H_{\alpha,c,\bar{c}}(r)^2 , dr$$

When $\bar{c} = c > 0$ (boundary of null), this reduces to the standard KPSS distribution.


API Reference

Main Functions

modified_kpss_test(y, c_bar=10.0, detrend="c", kernel="qs", bandwidth=None)

Perform the Modified KPSS test for near integration.

Parameters:

Parameter Type Default Description
y np.ndarray - Time series data
c_bar float 10.0 Local-to-unity parameter under H₀
detrend str "c" "c" for level, "ct" for trend
kernel str "qs" Kernel function: "qs", "bartlett", "parzen"
bandwidth float None Bandwidth (auto if None)

Returns: ModifiedKPSSResult object


standard_kpss_test(y, detrend="c", kernel="qs", bandwidth=None)

Perform the standard KPSS test for comparison.


Classes

ModifiedKPSS

Class-based interface for the Modified KPSS test.

from nearkpss import ModifiedKPSS

mkpss = ModifiedKPSS(c_bar=10.0, detrend="c", kernel="qs")
result = mkpss.test(y)

Critical Values and Simulation

get_critical_values(c_bar=10.0, detrend="c")

Get critical values for the test.

from nearkpss import get_critical_values

cv = get_critical_values(c_bar=10.0, detrend="c")
print(f"5% critical value: {cv.cv_5pct}")

simulate_critical_values(c, c_bar, alpha, detrend, n_replications, n_steps)

Simulate the asymptotic distribution from Theorem 1.

from nearkpss import simulate_critical_values

# Simulate 10,000 draws from the asymptotic distribution
stats = simulate_critical_values(
    c=10.0,       # True c value
    c_bar=10.0,   # Hypothesized c_bar
    alpha=1.0,    # Initial value parameter
    detrend="c",
    n_replications=10000,
    n_steps=5000
)

# Compute critical values
cv_5pct = np.percentile(stats, 95)
print(f"5% critical value: {cv_5pct:.4f}")

Examples

Example 1: Testing Real Economic Data

import numpy as np
from nearkpss import modified_kpss_test, standard_kpss_test

# Simulate GDP-like series (trending with unit root)
np.random.seed(123)
T = 200
trend = 0.01 * np.arange(T)
y = trend + np.cumsum(np.random.normal(0, 0.5, T))

# Modified KPSS test (trend case)
result_mod = modified_kpss_test(y, c_bar=10.0, detrend="ct")
print("Modified KPSS Test:")
print(result_mod)

# Compare with standard KPSS
result_std = standard_kpss_test(y, detrend="ct")
print("\nStandard KPSS Test:")
print(result_std)

Example 2: Monte Carlo Size Simulation

import numpy as np
from nearkpss import modified_kpss_test
from nearkpss.utils import simulate_near_integrated_ma

# Replicate Table 1 from the paper
def monte_carlo_size(T=200, c=10.0, c_bar=10.0, theta=0.0, 
                     alpha=1.0, n_sims=1000, seed=42):
    np.random.seed(seed)
    rejections = 0
    
    for _ in range(n_sims):
        y = simulate_near_integrated_ma(T, c, theta, alpha)
        result = modified_kpss_test(y, c_bar=c_bar, compute_pvalue=False)
        if result.reject_5pct:
            rejections += 1
    
    return rejections / n_sims

# Test with different MA parameters (as in Table 1)
for theta in [0.0, 0.6, -0.6]:
    size = monte_carlo_size(theta=theta)
    print(f"θ = {theta:4.1f}: Empirical size = {size:.3f}")

Example 3: Power Analysis

import numpy as np
import matplotlib.pyplot as plt
from nearkpss import simulate_critical_values
from nearkpss.critical_values import simulate_power_and_size

# Simulate power curves as in Figure 1
c_values = np.arange(0, 11)
rejection_rates, cv = simulate_power_and_size(
    c_values, 
    c_bar=10.0, 
    alpha=1.0,
    nominal_power=0.50,
    n_replications=5000,
    n_steps=2000
)

plt.figure(figsize=(8, 5))
plt.plot(c_values, rejection_rates, 'b-', linewidth=2)
plt.xlabel('c (local-to-unity parameter)')
plt.ylabel('Rejection Rate')
plt.title('Asymptotic Size and Power of Modified KPSS Test')
plt.axhline(y=0.50, color='r', linestyle='--', label='Power at c=0')
plt.grid(True, alpha=0.3)
plt.legend()
plt.tight_layout()
plt.savefig('power_curve.png', dpi=150)

Comparison with Paper Results

Table 1 Replication (Empirical Sizes at 5% Level)

θ α S^μ(10) Paper S^μ(10) Package
0.0 1 0.046 ≈ 0.046
0.0 3 0.046 ≈ 0.046
0.6 1 0.021 ≈ 0.021
-0.6 1 0.051 ≈ 0.051

The Modified KPSS test maintains size close to the nominal level across different specifications, unlike the optimal tests Q^μ(10) and Q^μ(10, 3.8) which show size distortions.


Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

Author

Dr Merwan Roudane


License

This project is licensed under the MIT License - see the LICENSE file for details.


Citation

If you use this package in your research, please cite:

@software{nearkpss,
  author = {Roudane, Merwan},
  title = {nearkpss: Modified KPSS Tests for Near Integration in Python},
  year = {2024},
  url = {https://github.com/merwanroudane/modifiedkpss}
}

And the original paper:

@article{harris2007modified,
  title={Modified KPSS Tests for Near Integration},
  author={Harris, David and Leybourne, Stephen and McCabe, Brendan},
  journal={Econometric Theory},
  volume={23},
  number={2},
  pages={355--363},
  year={2007},
  publisher={Cambridge University Press},
  doi={10.1017/S0266466607070156}
}

References

  • Harris, D., Leybourne, S., & McCabe, B. (2007). Modified KPSS Tests for Near Integration. Econometric Theory, 23(2), 355-363.
  • Kwiatkowski, D., Phillips, P., Schmidt, P., & Shin, Y. (1992). Testing the null hypothesis of stationarity against the alternative of a unit root. Journal of Econometrics, 54, 159-178.
  • Müller, U. (2005). Size and power of tests for stationarity in highly autocorrelated time series. Journal of Econometrics, 128, 195-213.
  • Newey, W. & West, K. (1994). Automatic lag selection in covariance matrix estimation. Review of Economic Studies, 61, 631-653.
  • Sul, D., Phillips, P.C.B., & Choi, C. (2005). Prewhitening bias in HAC estimation. Oxford Bulletin of Economics and Statistics, 67, 517-546.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nearkpss-1.0.0.tar.gz (28.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nearkpss-1.0.0-py3-none-any.whl (23.4 kB view details)

Uploaded Python 3

File details

Details for the file nearkpss-1.0.0.tar.gz.

File metadata

  • Download URL: nearkpss-1.0.0.tar.gz
  • Upload date:
  • Size: 28.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for nearkpss-1.0.0.tar.gz
Algorithm Hash digest
SHA256 0fc2ba192eb6f88572549f92e149984307511593ea2e0c07974296a4896c834f
MD5 c98952cfca5fb5935f8a109e3c46907e
BLAKE2b-256 8db6c506d24cc3de9816ae301d7c8941889ae0c5eaf41721728225298136db2d

See more details on using hashes here.

File details

Details for the file nearkpss-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: nearkpss-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 23.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for nearkpss-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8f694d52e267beb76b4cce8f8d399227025328565b44aecbd42e0a3f883f930a
MD5 e32e95c63e6cab6eeaecea71b6253480
BLAKE2b-256 ecfb37bf5a24fafac73da0d3c0bc72b82d6676b22c7b6d67a43f24e8f3ad86a9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page