Skip to main content

Quantilecoint

Python 3.8+ License: MIT Version

Quantile Cointegrating Regression - A Python implementation based on Xiao (2009) "Quantile cointegrating regression", Journal of Econometrics, 150, 248-260.

Author

Dr Merwan Roudane
Email: merwanroudane920@gmail.com
GitHub: https://github.com/merwanroudane/quantilecoint

Overview

This package implements quantile regression methods for cointegrated time series, including:

  • Quantile Cointegrating Regression: Estimate cointegrating relationships at different quantiles
  • Fully-Modified Quantile Regression: Bias-corrected estimator for endogenous regressors
  • Augmented Quantile Cointegrating Regression: Uses leads and lags to handle endogeneity
  • Wald Test: Test linear restrictions on cointegrating coefficients
  • Stability Test: Bootstrap-based test for constant vs. time-varying coefficients
  • CUSUM Cointegration Test: Robust test for the null of cointegration

Installation

pip install quantilecoint

Or install from source:

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

Complete Example: All Functions Demonstrated

import numpy as np
from quantilecoint import QuantileCointegration

# =============================================================================
# 1. GENERATE COINTEGRATED DATA
# =============================================================================
np.random.seed(42)
n = 200

# x_t is an I(1) process (random walk)
x = np.cumsum(np.random.randn(n))

# y_t is cointegrated with x_t: y = α + β*x + u
alpha_true = 2.0
beta_true = 1.5
y = alpha_true + beta_true * x + np.random.randn(n) * 0.5

print("=" * 70)
print("QUANTILECOINT LIBRARY - COMPLETE DEMONSTRATION")
print("Based on Xiao (2009) Journal of Econometrics")
print("=" * 70)

# =============================================================================
# 2. CREATE MODEL
# =============================================================================
model = QuantileCointegration(y, x, n_lags=4)
print(f"\nModel created with {n} observations, K=4 leads/lags")

# =============================================================================
# 3. FIT AT SINGLE QUANTILE (tau=0.5 for median)
# =============================================================================
print("\n" + "-" * 70)
print("3. SINGLE QUANTILE ESTIMATION (τ = 0.5)")
print("-" * 70)

results_single = model.fit(tau=0.5)
res = results_single[0.5]
print(f"   Intercept α(0.5): {res.alpha:.4f} (true: {alpha_true})")
print(f"   Slope β(0.5):     {res.beta[0]:.4f} (true: {beta_true})")

# =============================================================================
# 4. FIT AT MULTIPLE QUANTILES
# =============================================================================
print("\n" + "-" * 70)
print("4. MULTIPLE QUANTILE ESTIMATION")
print("-" * 70)

quantiles = [0.1, 0.25, 0.5, 0.75, 0.9]
results = model.fit(tau=quantiles)

print(f"{'τ':>8} {'α(τ)':>12} {'β(τ)':>12}")
print("-" * 35)
for tau in quantiles:
    res = results[tau]
    print(f"{tau:>8.2f} {res.alpha:>12.4f} {res.beta[0]:>12.4f}")

# =============================================================================
# 5. FULLY-MODIFIED QUANTILE REGRESSION (bias-corrected)
# =============================================================================
print("\n" + "-" * 70)
print("5. FULLY-MODIFIED QUANTILE REGRESSION (Theorem 2)")
print("-" * 70)

fm_result = model.fit_fully_modified(tau=0.5)
print(f"   β̂⁺(0.5):      {fm_result.beta[0]:.6f}")
print(f"   Std. Error:   {fm_result.std_errors[1]:.6f}")
print(f"   t-statistic:  {fm_result.tvalues[1]:.4f}")
print(f"   p-value:      {fm_result.pvalues[1]:.6f}")
ci = fm_result.conf_int()
print(f"   95% CI:       [{ci[1, 0]:.4f}, {ci[1, 1]:.4f}]")

# =============================================================================
# 6. WALD TEST FOR LINEAR RESTRICTIONS
# =============================================================================
print("\n" + "-" * 70)
print("6. WALD TEST (Theorem 3): H₀: β = 1.5")
print("-" * 70)

R = np.array([[0, 1]])  # Test the slope coefficient
r = np.array([1.5])     # Against value 1.5
wald_result = model.wald_test(R, r, tau=0.5)

print(f"   Wald statistic:  {wald_result.statistic:.4f}")
print(f"   Degrees of freedom: {wald_result.df}")
print(f"   P-value:         {wald_result.pvalue:.4f}")
if wald_result.pvalue > 0.05:
    print("   Conclusion: FAIL TO REJECT H₀ (β = 1.5)")
else:
    print("   Conclusion: REJECT H₀")

# =============================================================================
# 7. STABILITY TEST (constant vs. time-varying coefficients)
# =============================================================================
print("\n" + "-" * 70)
print("7. STABILITY TEST (Section 3.2): H₀: β(τ) = β (constant)")
print("-" * 70)

stability = model.test_stability(
    quantiles=np.arange(0.1, 0.91, 0.1),
    n_bootstrap=200  # Use more (e.g., 1000) for publication
)

print(f"   Test statistic sup|V̂ₙ(τ)|: {stability.statistic:.4f}")
print(f"   τ with max deviation:      {stability.tau_max:.2f}")
print(f"   Bootstrap p-value:         {stability.pvalue:.4f}")
print(f"   Critical values:")
print(f"      10%: {stability.critical_values['10%']:.4f}")
print(f"       5%: {stability.critical_values['5%']:.4f}")
print(f"       1%: {stability.critical_values['1%']:.4f}")
if stability.reject_at_05:
    print("   Conclusion: REJECT H₀ - Evidence of time-varying coefficients")
else:
    print("   Conclusion: FAIL TO REJECT H₀ - Coefficients appear constant")

# =============================================================================
# 8. CUSUM COINTEGRATION TEST
# =============================================================================
print("\n" + "-" * 70)
print("8. CUSUM COINTEGRATION TEST (Section 3.3): H₀: Cointegrated")
print("-" * 70)

coint_test = model.test_cointegration(tau=0.5, test_type='ks')

print(f"   CUSUM statistic: {coint_test.statistic:.4f}")
print(f"   Test type:       {coint_test.test_type.upper()}")
print(f"   P-value:         {coint_test.pvalue:.4f}")
if coint_test.reject_at_05:
    print("   Conclusion: REJECT H₀ - Evidence against cointegration")
else:
    print("   Conclusion: FAIL TO REJECT H₀ - Series appear cointegrated")

# =============================================================================
# 9. GET FORMATTED SUMMARY
# =============================================================================
print("\n" + "-" * 70)
print("9. PUBLICATION-READY SUMMARY OUTPUT")
print("-" * 70)

summary = results.summary()
print("\nText format (first 500 chars):")
print(summary.as_text()[:500] + "...")

# =============================================================================
# 10. LATEX OUTPUT FOR PAPERS
# =============================================================================
print("\n" + "-" * 70)
print("10. LATEX TABLE OUTPUT")
print("-" * 70)

latex = summary.as_latex()
print(latex[:400] + "...\n")

print("=" * 70)
print("ALL FUNCTIONS DEMONSTRATED SUCCESSFULLY!")
print("=" * 70)

Quick Reference

Basic Usage

from quantilecoint import QuantileCointegration

model = QuantileCointegration(y, x, n_lags=4)

# Fit at single quantile
results = model.fit(tau=0.5)

# Fit at multiple quantiles  
results = model.fit(tau=[0.1, 0.25, 0.5, 0.75, 0.9])

# Access coefficients
beta = results[0.5].beta
alpha = results[0.5].alpha

Fully-Modified Estimates (Bias-Corrected)

fm_result = model.fit_fully_modified(tau=0.5)
print(fm_result.summary())

Statistical Tests

# Test H₀: β = 1.0
wald = model.wald_test(R=np.array([[0, 1]]), r=np.array([1.0]), tau=0.5)

# Test for time-varying coefficients
stability = model.test_stability(n_bootstrap=1000)

# Test for cointegration
coint = model.test_cointegration(tau=0.5)

Output Formats

results = model.fit(tau=[0.1, 0.5, 0.9])
summary = results.summary()

# Plain text
print(summary.as_text())

# LaTeX (for papers)
print(summary.as_latex())

# HTML (for web)
print(summary.as_html())

API Reference

Classes

  • QuantileCointegration - Main model class
  • QuantileCointegrationResults - Results container

Methods

Method Description
fit(tau=, method=) Fit quantile regression at specified quantile(s)
fit_fully_modified(tau=) Fit bias-corrected estimator
wald_test(R, r, tau=) Test linear restrictions on β
test_stability(n_bootstrap=) Test for constant coefficients
test_cointegration(tau=) CUSUM test for cointegration

References

  • Xiao, Z. (2009). Quantile cointegrating regression. Journal of Econometrics, 150(2), 248-260.
  • Koenker, R., & Bassett, G. (1978). Regression quantiles. Econometrica, 46(1), 33-50.
  • Koenker, R., & Xiao, Z. (2006). Quantile autoregression. Journal of the American Statistical Association, 101(475), 980-990.

License

MIT License - see LICENSE file for details.

Citation

@software{roudane2026quantilecoint,
  author = {Roudane, Merwan},
  title = {quantilecoint: Quantile Cointegrating Regression in Python},
  year = {2026},
  version = {1.0.1},
  url = {https://github.com/merwanroudane/quantilecoint}
}

Metadata

Release files for quantilecoint 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for quantilecoint 1.0.1
File Size Uploaded Provenance
quantilecoint-1.0.1.tar.gz 38.4 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for quantilecoint 1.0.1
File Interpreter ABI Platform
quantilecoint-1.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 86.2 kB

Release files / quantilecoint-1.0.1.tar.gz

Download URL quantilecoint-1.0.1.tar.gz
Size 38.4 kB
Tags Source
SHA-256 checksum
How to use checksums
2fd947ad9178214b9fe90e862d378da87cdcd47c2bc1d72be3482904250ce062
BLAKE2b-256 checksum
How to use checksums
1dae2ab756b6d70329ab11736dc5f622cd78318e05aa34997e0e2c7f2f84fa1c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.7

Release files / quantilecoint-1.0.1-py3-none-any.whl

Download URL quantilecoint-1.0.1-py3-none-any.whl
Size 47.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
31bb8c4301865d7e1ddedd4647a73a5d32cfa792219e5ebac6cffc067b2df427
BLAKE2b-256 checksum
How to use checksums
3f349949d16ff0e704b56ff1b677961c38df51e65d0d2610d5d7a5f3076c7b15
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.7

Security for quantilecoint 1.0.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page