Skip to main content

QFADF - Quantile Fourier ADF Unit Root Test

Python Version License: MIT

A Python implementation of the Quantile Fourier ADF unit root test proposed by Li & Zheng (2018), which is robust to both non-Gaussian conditions and smooth structural changes.

Reference

Li, H., & Zheng, C. (2018). Unit root quantile autoregression testing with smooth structural changes. Finance Research Letters, 25, 83-89.

DOI: 10.1016/j.frl.2017.10.008

Features

  • Quantile Fourier ADF Test (qr_fourier_adf): Unit root test at a specified quantile with Fourier approximation for structural changes
  • Bootstrap Critical Values (qr_fourier_adf_bootstrap): Bootstrap procedure for finite-sample critical values
  • QKS and QCM Statistics (qks_qcm_statistics): Quantile Kolmogorov-Smirnov and Cramér-von Mises tests over a range of quantiles
  • Optimal Frequency Selection (estimate_optimal_k): Data-driven selection of Fourier frequency
  • Pre-computed Critical Values: Based on extensive Monte Carlo simulations
  • Publication-ready Output: LaTeX tables and formatted results

Installation

From PyPI (when available)

pip install qfadf

From Source

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

Dependencies

  • Python >= 3.8
  • NumPy >= 1.20.0
  • Pandas >= 1.3.0
  • SciPy >= 1.7.0
  • Matplotlib >= 3.4.0 (optional, for plotting)

Quick Start

Basic Unit Root Test

import numpy as np
from qfadf import qr_fourier_adf

# Generate a random walk (unit root process)
np.random.seed(42)
y = np.cumsum(np.random.randn(200))

# Perform test at median (tau=0.5)
results = qr_fourier_adf(y, model=1, tau=0.5, k=3, pmax=8)

# Output:
# ======================================================================
#          QUANTILE FOURIER ADF UNIT ROOT TEST
#          Li & Zheng (2018, Finance Research Letters)
# ======================================================================
#   Model:                Constant
#   Fourier frequency k:  3
#   Lags (pmax):          8
#   Sample size:          191
# ----------------------------------------------------------------------
#   Test Results:
# ----------------------------------------------------------------------
#   Quantile (τ):         0.500
#   ρ(τ):                 0.998xxx
#   t_f(τ) statistic:     -1.xxxx
# ----------------------------------------------------------------------

Bootstrap Critical Values

from qfadf import qr_fourier_adf_bootstrap

# Bootstrap for critical values (recommended for inference)
boot_results = qr_fourier_adf_bootstrap(
    y, 
    model=1, 
    tau=0.5, 
    n_boot=1000,
    random_state=42
)

# Access results
print(f"Test statistic: {boot_results['tn']:.4f}")
print(f"Bootstrap p-value: {boot_results['p_value']:.4f}")
print(f"Critical values (1%, 5%, 10%): {boot_results['cv']}")
print(f"Reject H0 at 5%: {boot_results['reject_5pct']}")

Multiple Quantiles Analysis

from qfadf import qr_fourier_adf, qks_qcm_statistics, multiple_quantile_results_table

# Test at multiple quantiles
tau_values = [0.1, 0.25, 0.5, 0.75, 0.9]
results_list = []

for tau in tau_values:
    result = qr_fourier_adf(y, model=1, tau=tau, print_results=False)
    results_list.append(result)

# Create comparison table
comparison_df = multiple_quantile_results_table(results_list)
print(comparison_df)

# QKS and QCM statistics
qks_qcm = qks_qcm_statistics(y, model=1, tau_range=(0.1, 0.9))
print(f"QKS_f: {qks_qcm['QKS_f']:.4f}")
print(f"QCM_f: {qks_qcm['QCM_f']:.4f}")

Optimal Fourier Frequency

from qfadf import estimate_optimal_k

# Estimate optimal k using residual sum of squares criterion
k_opt = estimate_optimal_k(y, model=1, tau=0.5, k_max=5)
print(f"Optimal Fourier frequency: k = {k_opt}")

Model Specifications

Model 1: Constant Only

$$y_t = \phi \tilde{y}_{t-1} + \alpha_0 + \alpha_k \sin(2\pi kt/T) + \beta_k \cos(2\pi kt/T) + \mu_t$$

Model 2: Constant and Trend

$$y_t = \phi \tilde{y}_{t-1} + \alpha_0 + \alpha_k \sin(2\pi kt/T) + \beta_k \cos(2\pi kt/T) + \gamma t + \mu_t$$

Test Statistics

t_f(τ) Statistic

The quantile t-ratio test statistic at quantile τ:

$$t_f(\tau) = \frac{\hat{f}(F^{-1}(\tau))}{\sqrt{\tau(1-\tau)}} (Y'{-1} M_x Y{-1})^{1/2} (\hat{\phi} - 1)$$

QKS_f Statistic

$$QKS_f = \sup_{\tau \in \mathcal{T}} |t_f(\tau)|$$

QCM_f Statistic

$$QCM_f = \int_{\tau \in \mathcal{T}} t_f(\tau)^2 d\tau$$

API Reference

Main Functions

Function Description
qr_fourier_adf() Main test function for single quantile
qr_fourier_adf_bootstrap() Bootstrap procedure for critical values
qks_qcm_statistics() QKS and QCM tests over quantile range
estimate_optimal_k() Optimal Fourier frequency selection

Critical Values

Function Description
get_critical_values() Get pre-computed critical values
simulate_critical_values() Monte Carlo simulation for critical values
print_critical_value_table() Print formatted critical value table

Utilities

Function Description
prepare_data() Data preprocessing
adf_lag_selection() Automatic lag selection
format_results_latex() Export results as LaTeX table
plot_quantile_results() Visualization of results

Parameters

Parameter Default Description
y - Time series data (1D array)
model 1 1: constant, 2: constant + trend
tau 0.5 Quantile level (0 < τ < 1)
pmax 8 Maximum lag order for Δy
k 3 Fourier frequency (1 ≤ k ≤ 5)
n_boot 1000 Number of bootstrap replications

Output

The test returns a dictionary with:

  • tn: Test statistic t_f(τ)
  • rho_tau: Estimated AR coefficient ρ(τ)
  • tau: Quantile level
  • model: Model specification
  • k: Fourier frequency
  • n: Effective sample size
  • cv: Critical values (if bootstrap)
  • p_value: Bootstrap p-value (if bootstrap)
  • reject_*pct: Decision at various significance levels

Citation

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

@article{li2018unit,
  title={Unit root quantile autoregression testing with smooth structural changes},
  author={Li, Haiqi and Zheng, Chaowen},
  journal={Finance Research Letters},
  volume={25},
  pages={83--89},
  year={2018},
  publisher={Elsevier},
  doi={10.1016/j.frl.2017.10.008}
}

Author

Dr Merwan Roudane

License

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

  • Original GAUSS code by Saban Nazlioglu (TSPDLIB)
  • statsmodels - Standard ADF tests
  • arch - Unit root tests with various specifications

Changelog

Version 1.0.0 (2025)

  • Initial release
  • Implementation of QR-Fourier-ADF test
  • Bootstrap critical values
  • QKS and QCM statistics
  • Pre-computed critical value tables
  • Comprehensive documentation

Metadata

Release files for qfadf 1.0.0

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

Source distribution (sdist)

Source distribution for qfadf 1.0.0
File Size Uploaded Provenance
qfadf-1.0.0.tar.gz 28.6 kB Without provenance Details

Built distribution (wheel)

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

Total release size: 54.2 kB

Release files / qfadf-1.0.0.tar.gz

Download URL qfadf-1.0.0.tar.gz
Size 28.6 kB
Tags Source
SHA-256 checksum
How to use checksums
9905f70b67890179a6bbcf45a166d5e7af517df1bbb47e67a913a82f712717dd
BLAKE2b-256 checksum
How to use checksums
0b100b84ab92cb5c547fc9e38f08654830c65df8207cd3d93b60a0525f238f29
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.7

Release files / qfadf-1.0.0-py3-none-any.whl

Download URL qfadf-1.0.0-py3-none-any.whl
Size 25.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4429a1cd9a6adc3bb9a3cfbcc79b979b5eb9e0eef0bf65741cf2801febb6787e
BLAKE2b-256 checksum
How to use checksums
f324e8bf2771d7dec4cc74bedb0019d1a5d48055b09ad608b23f9ccb6ee086b1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.7

Security for qfadf 1.0.0

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.0 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