Bootstrap tests for autocorrelation in regression models
Project description
boot_dw: Bootstrap Tests for Autocorrelation
A Python implementation of bootstrap-based tests for autocorrelation in regression models, based on:
Jeong, J. and Chung, S. (2001). "Bootstrap tests for autocorrelation". Computational Statistics & Data Analysis 38: 49-69.
Overview
The classical Durbin-Watson (DW) test for autocorrelation suffers from an important limitation: the test is inconclusive when the test statistic falls into the "indeterminate range" (dL, dU). This package implements bootstrap alternatives that eliminate this problem and provide superior finite-sample properties.
Implemented Tests
- Classical DW Test - Traditional Durbin-Watson test (with indeterminate range)
- BDW Test - Bootstrapped Durbin-Watson test (eliminates indeterminate range)
- B-ρ Test - Bootstrapped AR(1) coefficient test (percentile method)
- BCa-ρ Test - Bias-corrected accelerated ρ test (recommended, most powerful)
Installation
pip install boot_dw
Or install from source:
git clone https://github.com/merwanroudane/bootdw.git
cd bootdw
pip install -e .
Quick Start
import numpy as np
from boot_dw import autocorrelation_test
# Generate sample data
np.random.seed(42)
n = 50
X = np.random.randn(n, 2)
y = X @ np.array([2, -1]) + np.random.randn(n)
# Run BCa-ρ test (recommended)
result = autocorrelation_test(y, X, method='bca_rho', random_state=42)
print(result)
Output:
======================================================================
Bias-corrected accelerated ρ (BCa-ρ) test
======================================================================
H₀: ρ = 0 vs H₁: ρ > 0
Test statistic: -0.045123
P-value: 0.685000
Conclusion: Fail to reject H₀
Estimated ρ̂: -0.045123
DW statistic: 2.087456
95% BCa CI: (-0.312456, 0.198234)
Sample size: n = 50, k = 2
Bootstrap reps: B = 200
======================================================================
Features
Publication-Ready Output
The package provides publication-quality formatted output:
from boot_dw import bca_rho_test
result = bca_rho_test(y, X, n_bootstrap=200, random_state=42)
# Detailed summary
print(result.summary())
# LaTeX table for multiple tests
from boot_dw.utils import format_latex_table
results = {
'Classical DW': dw_test(y, X),
'BDW': bdw_test(y, X, random_state=42),
'BCa-ρ': bca_rho_test(y, X, random_state=42)
}
print(format_latex_table(results))
Monte Carlo Simulations
Replicate the simulations from Jeong & Chung (2001):
import numpy as np
from boot_dw import autocorrelation_test
# Simulation parameters
n = 50
k = 3
rho_values = np.arange(0, 1.0, 0.1)
n_simulations = 1000
n_bootstrap = 200
rejection_rates = []
for rho in rho_values:
rejections = 0
for _ in range(n_simulations):
# Generate data with AR(1) errors
X = np.random.randn(n, k)
u = np.zeros(n)
u[0] = np.random.randn()
for t in range(1, n):
u[t] = rho * u[t-1] + np.random.randn()
y = X @ np.ones(k) + u
# Test for autocorrelation
result = autocorrelation_test(y, X, method='bca_rho',
n_bootstrap=n_bootstrap, alpha=0.05)
if result.pvalue < 0.05:
rejections += 1
rejection_rates.append(rejections / n_simulations)
print(f"Empirical size (ρ=0): {rejection_rates[0]:.3f}")
print(f"Power at ρ=0.5: {rejection_rates[5]:.3f}")
API Reference
Main Test Function
autocorrelation_test(y, X, method='bca_rho', alternative='greater',
n_bootstrap=200, alpha=0.05, add_constant=True,
random_state=None)
Parameters:
y: Dependent variable (n,)X: Independent variables (n, k)method: Test method -'dw','bdw','b_rho', or'bca_rho'(recommended)alternative:'greater'(default),'less', or'two-sided'n_bootstrap: Number of bootstrap replications (default: 200)alpha: Significance level (default: 0.05)add_constant: Add intercept to regression (default: True)random_state: Random seed for reproducibility
Returns: TestResult object with attributes:
statistic: Test statistic valuepvalue: P-valuemethod: Test namealternative: Alternative hypothesisadditional_info: Dict with details (CI, critical values, etc.)
Individual Test Functions
from boot_dw import dw_test, bdw_test, b_rho_test, bca_rho_test
# Classical Durbin-Watson test
result_dw = dw_test(y, X)
# Bootstrapped Durbin-Watson test
result_bdw = bdw_test(y, X, n_bootstrap=200, random_state=42)
# Bootstrapped ρ test (percentile method)
result_brho = b_rho_test(y, X, n_bootstrap=200, random_state=42)
# BCa-ρ test (most powerful)
result_bca = bca_rho_test(y, X, n_bootstrap=200, random_state=42)
Core Functions
from boot_dw.core import durbin_watson, ols_regression, estimate_rho
# Calculate DW statistic
dw_stat = durbin_watson(residuals)
# OLS regression
beta, residuals, fitted = ols_regression(y, X, add_constant=True)
# Estimate AR(1) coefficient
rho_hat = estimate_rho(residuals)
Bootstrap Functions
from boot_dw.bootstrap import (
recursive_bootstrap_dw,
recursive_bootstrap_rho,
bca_confidence_interval
)
# Bootstrap DW distribution
dw_bootstrap = recursive_bootstrap_dw(y, X, residuals, rho_est, n_bootstrap=200)
# Bootstrap ρ distribution
rho_bootstrap = recursive_bootstrap_rho(y, X, residuals, rho_est, n_bootstrap=200)
# BCa confidence interval
lower, upper, z0, a0 = bca_confidence_interval(rho_bootstrap, rho_obs, y, X)
Theoretical Background
The Durbin-Watson Statistic
For regression model y = Xβ + u with AR(1) errors:
$$u_t = \rho u_{t-1} + e_t, \quad |ρ| < 1$$
The Durbin-Watson statistic is:
$$d = \frac{\sum_{t=2}^T (e_t - e_{t-1})^2}{\sum_{t=1}^T e_t^2} \approx 2(1 - \hat{\rho})$$
where:
- d ≈ 2: No autocorrelation (ρ ≈ 0)
- d < 2: Positive autocorrelation (ρ > 0)
- d > 2: Negative autocorrelation (ρ < 0)
Bootstrap Procedures
BDW Test (Bootstrapped Durbin-Watson)
- Estimate β̂, ρ̂ from original data
- Resample innovations ê with replacement
- Construct u* = e* (imposing H₀: ρ = 0)
- Create bootstrap data y* = Xβ̂ + u*
- Compute DW* and build empirical distribution F*_d
- Compare observed DW to F*_d for p-value
B-ρ Test (Bootstrapped ρ)
- Estimate β̂, ρ̂ and compute innovations
- Resample innovations ê with replacement
- Recursively construct u*t = ρ̂u*{t-1} + e*_t
- Estimate ρ* from bootstrap errors
- Build empirical distribution F*_ρ
- Test if 0 is in the confidence interval
BCa-ρ Test (Bias-Corrected Accelerated ρ)
- Perform B-ρ bootstrap
- Calculate bias correction: z₀ = Φ⁻¹(Ĝ(ρ̂))
- Calculate acceleration: a₀ from jackknife influence function
- Compute adjusted confidence interval
- Test if 0 is outside BCa interval
Performance (from Jeong & Chung 2001)
Monte Carlo results show:
-
Classical DW test:
- Has indeterminate range
- Poor size and power in small samples
-
BDW test:
- Eliminates indeterminate range
- Better power than classical DW and (a+bdU) approximation
-
B-ρ test:
- More powerful than BDW
- May have size distortions in small samples
-
BCa-ρ test (BEST):
- Most accurate empirical size
- Highest power, especially in small samples (n=10-50)
- Robust across different sample sizes
- Strongly recommended for practical applications
Examples
Example 1: Testing with Simulated AR(1) Data
import numpy as np
from boot_dw import autocorrelation_test
# Set parameters
np.random.seed(123)
n = 100
k = 3
rho_true = 0.6
# Generate regressors
X = np.random.randn(n, k)
beta_true = np.array([2.0, -1.5, 0.8])
# Generate AR(1) errors
u = np.zeros(n)
u[0] = np.random.randn()
for t in range(1, n):
u[t] = rho_true * u[t-1] + np.random.randn()
# Generate dependent variable
y = X @ beta_true + u
# Test for autocorrelation
result = autocorrelation_test(y, X, method='bca_rho', random_state=123)
print(result.summary())
Example 2: Comparing All Tests
import numpy as np
from boot_dw import dw_test, bdw_test, b_rho_test, bca_rho_test
from boot_dw.utils import format_latex_table
# Generate data
np.random.seed(42)
n = 50
X = np.random.randn(n, 2)
y = X @ np.array([2, -1]) + np.random.randn(n) * 0.5
# Run all tests
results = {
'Classical DW': dw_test(y, X),
'BDW': bdw_test(y, X, n_bootstrap=200, random_state=42),
'B-ρ (Percentile)': b_rho_test(y, X, n_bootstrap=200, random_state=42),
'BCa-ρ': bca_rho_test(y, X, n_bootstrap=200, random_state=42)
}
# Print comparison
for name, result in results.items():
print(f"\n{name}:")
if result.pvalue is not None:
print(f" Statistic: {result.statistic:.4f}")
print(f" P-value: {result.pvalue:.4f}")
else:
print(f" DW statistic: {result.statistic:.4f}")
print(f" P-value: Not available (use DW tables)")
# Generate LaTeX table
print("\nLaTeX Table:")
print(format_latex_table(results))
Example 3: Power Simulation Study
import numpy as np
import matplotlib.pyplot as plt
from boot_dw import autocorrelation_test
def simulate_power(n=50, k=3, rho_values=None, n_sim=100, n_bootstrap=200):
"""Simulate power function for BCa-ρ test."""
if rho_values is None:
rho_values = np.arange(0, 1.0, 0.1)
power = np.zeros(len(rho_values))
for i, rho in enumerate(rho_values):
rejections = 0
for _ in range(n_sim):
# Generate data
X = np.random.randn(n, k)
u = np.zeros(n)
u[0] = np.random.randn() / np.sqrt(1 - rho**2)
for t in range(1, n):
u[t] = rho * u[t-1] + np.random.randn()
y = X @ np.ones(k) + u
# Test
result = autocorrelation_test(y, X, method='bca_rho',
n_bootstrap=n_bootstrap, alpha=0.05)
if result.pvalue < 0.05:
rejections += 1
power[i] = rejections / n_sim
print(f"ρ = {rho:.1f}: power = {power[i]:.3f}")
return rho_values, power
# Run simulation
rho_vals, power_vals = simulate_power(n=50, k=3, n_sim=100, n_bootstrap=200)
# Plot
plt.figure(figsize=(10, 6))
plt.plot(rho_vals, power_vals, 'o-', linewidth=2, markersize=8)
plt.axhline(y=0.05, color='r', linestyle='--', label='Nominal size (5%)')
plt.xlabel('True ρ', fontsize=12)
plt.ylabel('Rejection Rate', fontsize=12)
plt.title('Power Function of BCa-ρ Test (n=50, k=3)', fontsize=14)
plt.grid(True, alpha=0.3)
plt.legend(fontsize=10)
plt.tight_layout()
plt.savefig('power_function.png', dpi=300)
plt.show()
Citation
If you use this package in your research, please cite both the package and the original paper:
Package:
@software{boot_dw2024,
author = {Roudane, Merwan},
title = {boot\_dw: Bootstrap Tests for Autocorrelation},
year = {2024},
url = {https://github.com/merwanroudane/bootdw},
version = {0.0.1}
}
Original paper:
@article{jeong2001bootstrap,
title={Bootstrap tests for autocorrelation},
author={Jeong, Jinook and Chung, Seoung},
journal={Computational Statistics \& Data Analysis},
volume={38},
number={1},
pages={49--69},
year={2001},
publisher={Elsevier}
}
References
-
Jeong, J. and Chung, S. (2001). "Bootstrap tests for autocorrelation". Computational Statistics & Data Analysis 38: 49-69.
-
Durbin, J. and Watson, G.S. (1950). "Testing for Serial Correlation in Least Squares Regression I". Biometrika 37: 409-428.
-
Durbin, J. and Watson, G.S. (1951). "Testing for Serial Correlation in Least Squares Regression II". Biometrika 38: 159-178.
-
Efron, B. (1987). "Better Bootstrap Confidence Intervals". Journal of the American Statistical Association 82: 171-200.
License
MIT License - see LICENSE file for details.
Author
Dr. Merwan Roudane
Email: merwanroudane920@gmail.com
GitHub: https://github.com/merwanroudane
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Acknowledgments
This implementation is based on the seminal work of Jeong & Chung (2001). Special thanks to the authors for their rigorous theoretical and empirical analysis of bootstrap methods for autocorrelation testing.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file boot_dw-0.0.1.tar.gz.
File metadata
- Download URL: boot_dw-0.0.1.tar.gz
- Upload date:
- Size: 33.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5bec36b79b1bc0bc287b580ce6940e4039c896e5d93e55a9abda408a33825c02
|
|
| MD5 |
ccd7d230a45c523ca5e091af9e2dc932
|
|
| BLAKE2b-256 |
a08a79ae84a788795f4749e081bb9b257b3b2f5d43fa137bf224bf34603fbbfc
|
File details
Details for the file boot_dw-0.0.1-py3-none-any.whl.
File metadata
- Download URL: boot_dw-0.0.1-py3-none-any.whl
- Upload date:
- Size: 21.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4438ad5ea1e9d88d84d2dd223710c3eb3ab17794277ec73794aa23e5df2f947c
|
|
| MD5 |
fffa936bcd0e366dd752b634d3e6703f
|
|
| BLAKE2b-256 |
6fe955f140028511723d9fe5a45eae9ae5754e618d42c7146a209d416a998dcf
|