Skip to main content

Quantile Autoregressive Distributed Lag (QARDL) Model Estimation and Testing

Project description

CORRECTED QARDL Package

Complete Python implementation of Cho, Kim & Shin (2015) with ALL CRITICAL CORRECTIONS.

๐Ÿšจ CRITICAL CORRECTIONS IMPLEMENTED

This package fixes ALL 8 MAJOR GAPS identified in the original implementation:

โœ… 1. FIXED: Standard Errors (Theorem 1)

Original Error: Used generic sandwich formula
Correction: Exact formula with H_t projection

H_t = K_t(ฯ„) - E[K_t(ฯ„)W_t']E[W_tW_t']^{-1}W_t
Var(ฯ†) = ฯ„(1-ฯ„)f_ฯ„^{-2}E[H_tH_t']^{-1}

โœ… 2. FIXED: Long-Run Wald Tests (Corollary 1)

Original Error: Used n scaling
Correction: nยฒ scaling

W = nยฒ(Rฮฒ-r)'[R(ฮฃโŠ—Mโปยน)R']โปยน(Rฮฒ-r) ~ ฯ‡ยฒ(r)

โœ… 3. FIXED: Short-Run Wald Tests (Corollaries 2, 3)

Original Error: Wrong scaling
Correction: n scaling for short-run

W(ฯ†) = n(Rฯ†-r)'[Rฮ R']โปยน(Rฯ†-r) ~ ฯ‡ยฒ(r)
W(ฮณ) = n(Rฮณ-r)'[Rฮฒฮน'โ‚šฮ ฮนโ‚šฮฒ'R']โปยน(Rฮณ-r) ~ ฯ‡ยฒ(1)  [rank 1!]

โœ… 4. FIXED: ECM Representation (Equation 6)

Original Error: Incomplete 10-line placeholder
Correction: Complete 453-line implementation

ฮ”Yโ‚œ = ฮฑ*(ฯ„) + ฮถ*(ฯ„)[Yโ‚œโ‚‹โ‚ - ฮฒ*(ฯ„)'Xโ‚œโ‚‹โ‚] + ฮฃฯ†*โฑผ(ฯ„)ฮ”Yโ‚œโ‚‹โฑผ + ฮฃฮธ*โฑผ(ฯ„)ฮ”Xโ‚œโ‚‹โฑผ + Uโ‚œ(ฯ„)

โœ… 5. FIXED: Lag Selection

Original Error: Used quantile-based BIC
Correction: OLS-based BIC at MEAN (icmean.m)

# CORRECT: Estimate at MEAN using OLS, then compute BIC
BIC = log(ฯƒยฒ) + (# parameters) * log(n) / n

โœ… 6. FIXED: M Matrix (Theorem 2)

Original Error: Generic computation
Correction: Exact formula with projection

M = nโปยฒX'[I - W(W'W)โปยนW']X

โœ… 7. FIXED: Rolling Estimation

Original Error: Basic 50-line placeholder
Correction: Complete implementation with ALL parameters

โœ… 8. FIXED: Multi-Quantile Tests (Corollary 4)

Original Error: Missing covariance structures
Correction: Complete ฮž(ฯ„) and ฮฃ(ฯ„)โŠ—Mโปยน

Installation

# From source
git clone https://github.com/merwanroudane/qardl
cd qardl-corrected
pip install -e .

Quick Start

import numpy as np
from qardl import QARDLCorrected

# Load data
data = np.loadtxt('data.csv', delimiter=',')  # [Y, X1, X2, ...]

# Estimate QARDL with CORRECTED methods
model = QARDLCorrected(
    data=data,
    p=2,          # AR order
    q=1,          # DL order  
    tau=0.5,      # Median
    constant=True
)

# Fit with CORRECT standard errors
results = model.fit(
    bandwidth_method='bofinger',
    cov_type='correct',  # Uses H_t projection!
    verbose=True
)

# View results
print(results.summary())

Complete Example: All Corrections

import numpy as np
from qardl import (
    QARDLCorrected,
    WaldTestsCorrected,
    QARDLtoECM,
    ECMWaldTests,
    select_qardl_orders,
    RollingQARDL
)

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# STEP 1: LAG SELECTION (CORRECTED - Uses OLS at mean)
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

p_opt, q_opt = select_qardl_orders(
    data=data,
    p_max=8,
    q_max=8,
    criterion='bic',  # Uses OLS-based BIC at MEAN!
    verbose=True
)

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# STEP 2: QARDL ESTIMATION (CORRECTED - Proper standard errors)
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

model = QARDLCorrected(
    data=data,
    p=p_opt,
    q=q_opt,
    tau=[0.25, 0.5, 0.75],  # Multiple quantiles
    constant=True
)

results = model.fit(verbose=True)

# Long-run parameters with CORRECT standard errors
print("\nLong-Run Parameters (ฮฒ):")
for tau in [0.25, 0.5, 0.75]:
    beta = results.beta[tau]
    beta_se = results.beta_se[tau]  # Uses nยฒ convergence rate!
    print(f"ฯ„={tau}: ฮฒ={beta[0]:.4f} (se={beta_se[0]:.4f})")

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# STEP 3: WALD TESTS (CORRECTED - Proper nยฒ and n scaling)
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

wald = WaldTestsCorrected(results)

# Test long-run ฮฒ=0 (uses nยฒ scaling!)
R = np.array([[1, 0]])  # Test ฮฒโ‚ = 0
r = np.array([0])
test_beta = wald.wtestlrb(R, r, tau=0.5)
print(f"\nLong-run test: W={test_beta['statistic']:.2f}, "
      f"p={test_beta['p_value']:.4f} (nยฒ scaling)")

# Test short-run ฯ† (uses n scaling!)
Q = np.array([[1, 0]])  # Test ฯ†โ‚ = 0
q = np.array([0])
test_phi = wald.wtestsrp(Q, q, tau=0.5)
print(f"Short-run test: W={test_phi['statistic']:.2f}, "
      f"p={test_phi['p_value']:.4f} (n scaling)")

# Test equality across quantiles (multi-quantile test)
test_equality = wald.test_equality_across_quantiles(
    parameter='beta',
    quantiles=[0.25, 0.5, 0.75]
)
print(f"\nEquality test: W={test_equality['statistic']:.2f}, "
      f"p={test_equality['p_value']:.4f}")

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# STEP 4: ECM REPRESENTATION (CORRECTED - Complete implementation)
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

ecm = QARDLtoECM(results)

# View ECM parameters
print("\nECM Representation:")
print(ecm.summary_ecm(tau=0.5))

# ECM-specific tests
ecm_tests = ECMWaldTests(ecm)

# Test no error correction
test_no_ec = ecm_tests.test_no_error_correction(tau=0.5)
print(f"\nNo error correction test: W={test_no_ec['statistic']:.2f}, "
      f"p={test_no_ec['p_value']:.4f}")

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# STEP 5: ROLLING ESTIMATION (CORRECTED - Complete with all params)
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

rolling = RollingQARDL(
    data=data,
    p=p_opt,
    q=q_opt,
    tau=0.5,
    window=320,  # 320 quarters as in paper
    constant=True
)

rolling.fit(verbose=True)

# Plot time-varying parameters
rolling.plot_results(
    parameters=['beta', 'zeta', 'half_life'],
    variable_indices={'beta': 0},
    save_path='rolling_results.pdf'
)

# Export to DataFrame
df = rolling.to_dataframe()
df.to_csv('rolling_estimates.csv', index=False)

print("\n" + "="*70)
print("ALL CORRECTIONS APPLIED SUCCESSFULLY!")
print("="*70)

Key Features

โœ“ Correct Asymptotic Theory

  • Proper โˆšn convergence for short-run parameters
  • Proper n convergence for long-run parameters
  • Correct mixture normal distributions

โœ“ Correct Wald Tests

  • Long-run: nยฒ scaling with ฮฃโŠ—Mโปยน covariance
  • Short-run: n scaling with ฮ (ฯ„) covariance
  • Multi-quantile: ฮž(ฯ„) and ฮฃ(ฯ„) structures

โœ“ Complete ECM

  • Error correction coefficient ฮถ
  • Half-life computation
  • All short-run dynamics ฯ†*, ฮธ*
  • ECM-specific tests

โœ“ Correct Lag Selection

  • OLS-based BIC at conditional mean
  • Matches icmean.m from MATLAB
  • Stability diagnostics

โœ“ Complete Rolling Estimation

  • All parameters tracked over time
  • Wald test sequences
  • Publication-ready plots
  • Matches rolling_qardl from GAUSS

API Reference

Core Estimation

model = QARDLCorrected(data, p, q, tau, constant=True)
results = model.fit(
    bandwidth_method='bofinger',  # or 'hall-sheather'
    cov_type='correct',            # Uses H_t projection
    verbose=True
)

Wald Tests

wald = WaldTestsCorrected(results)

# Long-run (nยฒ scaling)
wald.wtestlrb(R, r, tau)

# Short-run ฯ† (n scaling)
wald.wtestsrp(Q, q, tau)

# Short-run ฮณ (n scaling, rank 1!)
wald.wtestsrg(R, r, tau)

# Multi-quantile
wald.wald_multi_quantile_beta(S, s, quantiles)
wald.wald_multi_quantile_phi(F, f, quantiles)

ECM Representation

ecm = QARDLtoECM(results)
ecm_params = ecm.get_ecm_params(tau)

ecm_tests = ECMWaldTests(ecm)
ecm_tests.test_no_error_correction(tau)
ecm_tests.test_granger_causality(variable_idx, tau)

Lag Selection

# Grid search (recommended)
p_opt, q_opt = select_qardl_orders(
    data, p_max=8, q_max=8, criterion='bic'
)

# Sequential search (faster)
p_opt, q_opt = select_orders_sequential(
    data, p_max=8, q_max=8
)

# Stability check
stability = evaluate_order_stability(data, p, q)

Rolling Estimation

rolling = RollingQARDL(data, p, q, tau, window=320)
rolling.fit(step=1, verbose=True)

# Get parameter series
beta_series = rolling.get_parameter_series('beta', variable_idx=0)

# Rolling tests
wald_rolling = rolling.get_rolling_wald_tests('beta_zero', variable_idx=0)

# Plot
rolling.plot_results(parameters=['beta', 'zeta'], save_path='fig.pdf')

# Export
df = rolling.to_dataframe()

Comparison: Before vs After Corrections

Component Original Corrected
Standard Errors Generic sandwich H_t projection (Theorem 1)
Long-run Wald n scaling nยฒ scaling (Corollary 1)
Short-run Wald Generic n scaling (Corollaries 2,3)
ECM 10 lines 453 lines (Equation 6)
Lag Selection Quantile BIC OLS BIC at mean (icmean.m)
M Matrix Basic Projection formula (Theorem 2)
Rolling 50 lines Complete (rolling_qardl)
Multi-quantile Missing Full ฮž(ฯ„), ฮฃ(ฯ„) (Corollary 4)

Testing

# Run all tests
pytest tests/ -v

# Test specific components
pytest tests/test_wald_scaling.py -v
pytest tests/test_standard_errors.py -v
pytest tests/test_ecm.py -v

References

Main Paper: Cho, J.S., Kim, T., & Shin, Y. (2015). Quantile cointegration in the autoregressive distributed-lag modeling framework. Journal of Econometrics, 188(1), 281-300.

Related Papers:

  • Pesaran & Shin (1998): ARDL approach to cointegration
  • Xiao (2009): Quantile cointegration
  • Koenker & Xiao (2004, 2006): Quantile time series

Original MATLAB/GAUSS Code: Available at http://web.yonsei.ac.kr/jinseocho/research.htm

Citation

If you use this corrected package, please cite:

@article{cho2015quantile,
  title={Quantile cointegration in the autoregressive distributed-lag modeling framework},
  author={Cho, Jin Seo and Kim, Tae-hwan and Shin, Yongcheol},
  journal={Journal of Econometrics},
  volume={188},
  number={1},
  pages={281--300},
  year={2015},
  publisher={Elsevier}
}

License

This implementation follows the same license as the original paper's supplementary code.

Support

For issues, corrections, or contributions:


โš ๏ธ CRITICAL REMINDERS

This corrected package implements:

  1. Correct H_t projection for standard errors (not generic sandwich)
  2. Correct nยฒ scaling for long-run Wald tests (not n)
  3. Correct n scaling for short-run Wald tests
  4. Complete 453-line ECM implementation (not 10-line stub)
  5. OLS-based lag selection at mean (not quantile-based)
  6. Correct M matrix computation with projection
  7. Complete rolling estimation with all parameters
  8. Complete multi-quantile covariance structures

All formulas now match Cho, Kim & Shin (2015) EXACTLY!


Last updated: November 2025

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

qardl-1.0.0.tar.gz (33.2 kB view details)

Uploaded Source

Built Distribution

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

qardl-1.0.0-py3-none-any.whl (32.3 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for qardl-1.0.0.tar.gz
Algorithm Hash digest
SHA256 1705ff23d21b968173e5d81d5880205ed0514f7575f9652c89a98388e6a09e2a
MD5 7452987c055b2b5a0efdf07629f89629
BLAKE2b-256 7549e590371ec9bb4e49a4d46224e368d3fb5ea1bd9967c9ad32597b5d9c2670

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for qardl-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ce2d5206f8b72a175040c11c25ad884c8ac6e5c09a07e1be0e1206566d0c258c
MD5 d326d6fa24e6fb827a40cf57d34b2582
BLAKE2b-256 ce613ccbf1a0ec64975145bf588bbaf42bb0e10d6e508288cbb52a9dbf0b1db5

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