Multiple Structural Breaks in Cointegrating Regressions: A Model Selection Approach
Project description
selectbreakcoint
Multiple Structural Breaks in Cointegrating Regressions: A Model Selection Approach
A Python implementation of the adaptive lasso methodology for detecting and estimating multiple structural breaks in cointegrating regressions, based on:
Schmidt, A. and Schweikert, K. (2021). "Multiple structural breaks in cointegrating regressions: A model selection approach." Studies in Nonlinear Dynamics & Econometrics.
Features
- Structural Break Detection: Detect multiple structural breaks in both intercept and slope coefficients of cointegrating regressions
- Adaptive Lasso Estimation: Oracle-efficient estimation using the adaptive lasso with proper treatment of non-stationary regressors
- Cointegration Testing: Residual-based tests for cointegration allowing for multiple structural breaks
- Flexible Model Specification:
- Known breakpoint candidates (Section 2.1)
- Diverging number of breakpoint candidates (Algorithm 1, Section 2.2)
- Complete Critical Values: Tables from Schmidt and Schweikert (2021) for statistical inference
- Comparison Methods: Gregory-Hansen and Hatemi-J tests for benchmarking
Installation
pip install selectbreakcoint
Or install from source:
git clone https://github.com/merwanroudane/selectbreakcoint.git
cd selectbreakcoint
pip install -e .
Quick Start
Detecting Structural Breaks
import numpy as np
from selectbreakcoint import AdaptiveLassoBreaks
# Generate cointegrated data with a structural break at t=100
np.random.seed(42)
T = 200
x = np.cumsum(np.random.randn(T)) # I(1) regressor
# y with break at t=100 (intercept: 2→4, slope: 2→4)
e = np.random.randn(T) * 0.5
y = np.where(
np.arange(T) < 100,
2 + 2 * x + e,
4 + 4 * x + e
)
# Estimate structural breaks
model = AdaptiveLassoBreaks(max_breaks=2, trim=0.05)
result = model.fit(x, y)
print(result)
Cointegration Testing with Structural Breaks
from selectbreakcoint import CointegrationTest
# Test for cointegration allowing up to 2 structural breaks
test = CointegrationTest(max_breaks=2, test_type='adf')
result = test.test(x, y)
print(result)
print(f"Cointegrated at 5%? {result.is_cointegrated}")
Using Known Breakpoint Candidates
# If you have prior information about potential break dates
model = AdaptiveLassoBreaks(max_breaks=3)
result = model.fit(x, y, known_breaks=[0.25, 0.5, 0.75])
print(f"Detected breaks at: {result.break_fractions}")
Methodology
Algorithm 1: Diverging Number of Breakpoint Candidates
The package implements the three-step procedure from Section 2.2:
- Initial Lasso: Apply plain lasso to the full model with all potential break points
- Adaptive Lasso: Use adaptive weights to distinguish active from inactive breaks
- Post-Lasso OLS: Final estimation with selected breaks
Algorithm 2: Cointegration Testing
The cointegration test (Section 2.3) follows:
- For each tuning parameter λ, estimate breaks using adaptive lasso
- Re-estimate using post-lasso OLS
- Test residuals using ADF or bias-corrected Z_t statistics
- Select model specification minimizing the test statistic (infimum test)
Critical Values
Critical values from Table 1 of Schmidt and Schweikert (2021) are included for:
- ADF-type test statistics
- Bias-corrected Z_t test statistics
- Maximum breaks: 1 to 6
- Sample sizes: 100, 200, 400, asymptotic
- Significance levels: 10%, 5%, 1%
API Reference
Main Classes
AdaptiveLassoBreaks
AdaptiveLassoBreaks(
max_breaks=1, # Maximum number of structural breaks
trim=0.05, # Lateral trimming parameter
min_obs=1, # Minimum observations per regime
n_lambda=100, # Number of lambda values in grid
gamma=1.0, # Exponent for adaptive lasso weights
penalty_type='bic_star', # 'bic' or 'bic_star' (modified BIC)
dynamic_lags=0 # Number of leads/lags for endogeneity correction
)
Methods:
fit(x, y, known_breaks=None): Estimate structural breakspredict(x_new): Predict y valuesget_residuals(): Get model residuals
CointegrationTest
CointegrationTest(
max_breaks=1, # Maximum number of structural breaks
trim=0.05, # Lateral trimming parameter
test_type='adf', # 'adf' or 'zt' (bias-corrected)
lag_selection='aic',# 'aic', 'bic', or 'fixed'
n_lambda=100, # Number of lambda values
dynamic_lags=0 # Leads/lags for endogeneity correction
)
Methods:
test(x, y): Perform cointegration testis_cointegrated(significance=0.05): Check cointegration statusget_breaks(): Get estimated break dates
Result Classes
BreakEstimationResult
Contains:
n_breaks: Number of detected breaksbreak_fractions: Break fractions τ ∈ (0, 1)break_dates: Break date indicesintercept_coefs,slope_coefs: Baseline coefficientsintercept_changes,slope_changes: Parameter changesregime_intercepts,regime_slopes: Regime-specific valuesresiduals: Model residualsbic: BIC value
CointegrationTestResult
Contains:
test_statistic: Test statistic valuecritical_values: Critical values at different significance levelsis_cointegrated: Boolean for 5% significancereject_null: Dict of rejection decisionsbreak_fractions,break_dates: Estimated breaks under alternative
Utility Functions
from selectbreakcoint import (
get_critical_values, # Retrieve critical values
construct_break_indicators, # Build indicator matrices
compute_bic, # Standard BIC
compute_modified_bic, # Modified BIC for diverging parameters
dynamic_augmentation, # Leads/lags for endogeneity correction
hausdorff_distance, # Performance metric for Monte Carlo
)
Examples
Example 1: PPP Analysis (Empirical Application)
import pandas as pd
from selectbreakcoint import AdaptiveLassoBreaks, CointegrationTest
# Load PPP data (nominal exchange rate and price ratio)
data = pd.read_csv('ppp_data.csv')
exchange_rate = data['ex'].values
price_ratio = data['p_us'] - data['p_uk'] # log price differential
# Test for cointegration with up to 6 breaks
test = CointegrationTest(max_breaks=6, dynamic_lags=2)
result = test.test(price_ratio.values, exchange_rate)
print(result)
print(f"\nBreak dates: {result.break_dates}")
Example 2: Monte Carlo Simulation
from selectbreakcoint import AdaptiveLassoBreaks
from selectbreakcoint.utils import hausdorff_distance, percentage_correct_estimation
def run_monte_carlo(n_reps=1000, T=200, true_breaks=[0.33, 0.67]):
pce_list = []
hd_list = []
for _ in range(n_reps):
# Generate DGP as in Equation (18)
x = np.cumsum(np.random.randn(T))
e = np.random.randn(T) * 2
# True coefficients: μ=2, β=2 with changes of 2 at each break
y = np.zeros(T)
bp1, bp2 = int(0.33*T), int(0.67*T)
y[:bp1] = 2 + 2*x[:bp1] + e[:bp1]
y[bp1:bp2] = 4 + 4*x[bp1:bp2] + e[bp1:bp2]
y[bp2:] = 6 + 6*x[bp2:] + e[bp2:]
# Estimate
model = AdaptiveLassoBreaks(max_breaks=4)
result = model.fit(x, y)
pce_list.append(1 if result.n_breaks == 2 else 0)
hd_list.append(hausdorff_distance(result.break_fractions, true_breaks))
print(f"PCE: {np.mean(pce_list)*100:.1f}%")
print(f"Mean Hausdorff distance: {np.mean(hd_list)*T:.2f}")
run_monte_carlo()
Comparison with R Implementation
This Python package is designed to be compatible with the original R code from Schmidt and Schweikert (2021). Key correspondences:
| R Function | Python Method |
|---|---|
lasso.est() |
AdaptiveLassoBreaks.fit() |
ur.df() |
adf_test() |
pp() |
phillips_perron_test() |
Dependencies
- NumPy >= 1.20.0
- SciPy >= 1.7.0
- scikit-learn >= 1.0.0
- pandas >= 1.3.0
- statsmodels >= 0.13.0
Citation
If you use this package in your research, please cite:
@article{schmidt2021multiple,
title={Multiple structural breaks in cointegrating regressions: A model selection approach},
author={Schmidt, Alexander and Schweikert, Karsten},
journal={Studies in Nonlinear Dynamics \& Econometrics},
year={2021},
publisher={De Gruyter}
}
Author
Dr. Merwan Roudane
License
MIT License - see LICENSE file for details.
References
- Schmidt, A. and Schweikert, K. (2021). Multiple structural breaks in cointegrating regressions: A model selection approach. Studies in Nonlinear Dynamics & Econometrics.
- Gregory, A.W. and Hansen, B.E. (1996). Residual-based tests for cointegration in models with regime shifts. Journal of Econometrics.
- Hatemi-J, A. (2008). Tests for cointegration with two unknown regime shifts. Empirical Economics.
- Zou, H. (2006). The adaptive lasso and its oracle properties. Journal of the American Statistical Association.
- Phillips, P.C.B. (1987). Time series regression with a unit root. Econometrica.
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 selectbreakcoint-1.0.0.tar.gz.
File metadata
- Download URL: selectbreakcoint-1.0.0.tar.gz
- Upload date:
- Size: 33.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
79ff2e391d10a96e90332e098253b854a0deefd9c0975372ecb3e431fbf62bf2
|
|
| MD5 |
80ed9c4f5f71261013d3757951d66a59
|
|
| BLAKE2b-256 |
dedd954abd12ab069a204f4824c2b9f939edd39770ddb07427a49e96ef2037bb
|
File details
Details for the file selectbreakcoint-1.0.0-py3-none-any.whl.
File metadata
- Download URL: selectbreakcoint-1.0.0-py3-none-any.whl
- Upload date:
- Size: 33.3 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 |
3e2f80e9679e23d9d8dd536e7741abe3c8d2a5cc3796419d089006cdef356391
|
|
| MD5 |
55238350446424fd389b4d192c0cc679
|
|
| BLAKE2b-256 |
fc3b86e854f7ab4059273d287c6527d9e9f516568bc02c65777467786263db28
|