Skip to main content

GLS-based unit root tests for bounded time series

Project description

BoundedTest: GLS-based Unit Root Tests for Bounded Processes

Python Version License

A Python implementation of unit root tests for bounded time series based on Carrion-i-Silvestre and Gadea (2013).

Overview

boundedtest provides comprehensive tools for testing unit roots in time series that are constrained within bounds. The package implements:

  • GLS-detrending with bound-specific non-centrality parameter κ̅(c,c̄)
  • OLS-detrending for comparison
  • M-type test statistics: MZα, MSB, and MZt
  • Parametric and non-parametric long-run variance estimation
  • Critical values tailored to different bound configurations

Reference

This package implements the methodology from:

Carrion-i-Silvestre, J.L. and Gadea, M.D. (2013). "GLS-based unit root tests for bounded processes." Economics Letters, 120(2), 184-187.

Installation

pip install boundedtest

Or install from source:

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

Quick Start

import numpy as np
from boundedtest import bounded_unit_root_test

# Generate bounded data
np.random.seed(42)
data = np.cumsum(np.random.randn(200))
data = np.clip(data, -10, 10)  # Apply bounds

# Test for unit root with GLS-BOUNDS method (recommended)
result = bounded_unit_root_test(
    data=data,
    bounds=(-10, 10),
    statistic='mz_alpha',
    detrending='gls_bounds',
    lrv_method='np'
)

print(result)

Main Features

1. Detrending Methods

  • 'ols': Standard OLS detrending
  • 'gls_ers': GLS detrending with standard κ = -7 (Elliott et al., 1996)
  • 'gls_bounds': GLS detrending with bound-specific κ̅(c,c̄) (recommended)

2. Test Statistics

  • MZα: Modified Phillips-Perron statistic
  • MSB: Modified Sargan-Bhargava statistic
  • MZt: Modified t-statistic

3. LRV Estimation

  • Non-parametric ('np'): Newey-West with automatic bandwidth selection
  • Parametric ('ar'): AR-based with MAIC lag selection (Ng & Perron, 2001)

Examples

Example 1: Basic Usage

import numpy as np
from boundedtest import bounded_unit_root_test

# Generate data
np.random.seed(123)
T = 200
data = np.cumsum(np.random.randn(T))
bounds = (-5, 5)
data = np.clip(data, bounds[0], bounds[1])

# Run test
result = bounded_unit_root_test(
    data=data,
    bounds=bounds,
    detrending='gls_bounds'
)

print(result)
print(f"\nReject H0 at 5%: {result.reject_5pct}")

Example 2: Compare All Test Statistics

results = bounded_unit_root_test(
    data=data,
    bounds=bounds,
    statistic='all',  # Compute all statistics
    detrending='gls_bounds'
)

# Results is a dictionary
for stat_name, result in results.items():
    print(f"\n{stat_name}:")
    print(f"  Statistic: {result.statistic:.4f}")
    print(f"  Critical (5%): {result.critical_values['5%']:.4f}")
    print(f"  Reject H0: {result.reject_5pct}")

Example 3: Compare Detrending Methods

methods = ['ols', 'gls_ers', 'gls_bounds']

for method in methods:
    result = bounded_unit_root_test(
        data=data,
        bounds=bounds,
        statistic='mz_alpha',
        detrending=method
    )
    print(f"\n{method.upper()}:")
    print(f"  MZα = {result.statistic:.4f}")
    print(f"  Reject H0 = {result.reject_5pct}")

Example 4: With Pandas DataFrame

import pandas as pd

# Create DataFrame
df = pd.DataFrame({
    'date': pd.date_range('2020-01-01', periods=200, freq='D'),
    'series': data
})

# Test using the series
result = bounded_unit_root_test(
    data=df['series'],
    bounds=bounds,
    detrending='gls_bounds'
)

Example 5: Unemployment Rate (0-100% bounded)

# Unemployment rate bounded between 0 and 100
unemployment = np.random.uniform(3, 10, size=100)  # Example data
unemployment += np.cumsum(np.random.randn(100)) * 0.2

result = bounded_unit_root_test(
    data=unemployment,
    bounds=(0, 100),
    detrending='gls_bounds'
)

Understanding Results

The output includes:

  • Test Statistic Value: The computed test statistic
  • Critical Values: At 1%, 5%, and 10% significance levels
  • Rejection Decision: Whether to reject the unit root null hypothesis
  • Bounds Information: Original bounds and estimated c-parameters
  • Non-centrality Parameter (κ̅): Used in GLS detrending
  • LRV Estimate: Estimated long-run variance

Interpretation

  • MZα and MZt: Left-tail tests. Reject H₀ if statistic < critical value.
  • MSB: Right-tail test. Reject H₀ if statistic > critical value.
  • H₀: Series has a unit root (is I(1))
  • H₁: Series is stationary (is I(0))

Advanced Usage

Generating Bounded Processes

from boundedtest.regulated_ou import generate_bounded_ar1

# Generate bounded AR(1) process
data = generate_bounded_ar1(
    T=200,
    bounds=(-5, 5),
    rho=1.0,  # Unit root
    sigma=1.0,
    burnin=100,
    seed=42
)

Custom Critical Values via Simulation

from boundedtest.regulated_ou import compute_critical_values

# Compute critical values for specific bounds
cv = compute_critical_values(
    c_lower=-0.5,
    c_upper=0.5,
    kappa=0,
    n_sim=10000,
    alpha=0.05
)

print(cv)

Accessing Individual Components

from boundedtest import (
    ols_detrend,
    gls_detrend,
    compute_mz_alpha,
    estimate_lrv_np,
    get_kappa
)

# Manual detrending
y_tilde, _, _ = ols_detrend(data)

# Compute LRV
from boundedtest.statistics import compute_ar1_residuals
residuals = compute_ar1_residuals(y_tilde)
s2 = estimate_lrv_np(residuals)

# Compute statistic
mz_alpha = compute_mz_alpha(y_tilde, s2)

API Reference

Main Function

bounded_unit_root_test(
    data,           # array-like: Time series data
    bounds,         # tuple: (lower_bound, upper_bound)
    statistic='mz_alpha',  # str: Test statistic to compute
    detrending='gls_bounds',  # str: Detrending method
    lrv_method='np',  # str: LRV estimation method
    deterministics='constant'  # str: Deterministic components
) -> BoundedTestResult

Monte Carlo Simulations

The package includes utilities for Monte Carlo experiments:

from boundedtest.regulated_ou import simulate_bounded_process

# Simulate under H0
data_h0 = simulate_bounded_process(
    T=200,
    b_lower=-5,
    b_upper=5,
    alpha=1.0,  # Unit root
    sigma=1.0
)

# Simulate under H1  
data_h1 = simulate_bounded_process(
    T=200,
    b_lower=-5,
    b_upper=5,
    alpha=0.95,  # Stationary
    sigma=1.0
)

Requirements

  • Python >= 3.8
  • NumPy >= 1.20.0
  • SciPy >= 1.7.0
  • Pandas >= 1.3.0
  • Statsmodels >= 0.13.0

Citation

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

@article{carrion2013gls,
  title={GLS-based unit root tests for bounded processes},
  author={Carrion-i-Silvestre, Josep Llu{\'\i}s and Gadea, Mar{\'\i}a Dolores},
  journal={Economics Letters},
  volume={120},
  number={2},
  pages={184--187},
  year={2013},
  publisher={Elsevier}
}

License

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

Author

Merwan Roudane
Email: merwanroudane920@gmail.com
GitHub: @merwanroudane

Contributing

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

Acknowledgments

This implementation is based on the methodology developed by Josep Lluís Carrion-i-Silvestre and María Dolores Gadea. The original MATLAB code and methodological guidance were instrumental in developing this Python package.

See Also

  • Original paper: Economics Letters (2013)
  • Elliott, Rothenberg & Stock (1996): "Efficient Tests for an Autoregressive Unit Root"
  • Ng & Perron (2001): "Lag Length Selection and the Construction of Unit Root Tests"
  • Cavaliere (2005): "Limited Time Series with a Unit Root"

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

boundedtest-1.0.0.tar.gz (28.7 kB view details)

Uploaded Source

Built Distribution

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

boundedtest-1.0.0-py3-none-any.whl (24.9 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for boundedtest-1.0.0.tar.gz
Algorithm Hash digest
SHA256 89d74cb4bd95057f2cc84ca8b6006b5d884f144f2afab546fbcd80b45297d770
MD5 1a68f8d3cf479e9fee430d8c5935445c
BLAKE2b-256 45851b7d5f71069eda9a965a25cb19d893ea77645f758730c636d50dd6749728

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for boundedtest-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2110ac6292ca630cd3d89d01b99c6f4e961c4c8a9defd61ff0f47f8b856a3ce4
MD5 613ddcdfa4c5112181dc3c559658803b
BLAKE2b-256 0cfb3beb07103633711fb7feb575d4297717d41061772e65d73d4ba2d90684ec

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