CPR: Cointegrating Polynomial Regressions
A Python library for residual-based cointegration and non-cointegration tests for cointegrating polynomial regressions (CPRs).
This package implements the econometric methods developed in:
Wagner, M. (2023). Residual-based cointegration and non-cointegration tests for cointegrating polynomial regressions. Empirical Economics, 65, 1-31. https://doi.org/10.1007/s00181-022-02332-3
Features
- FM-OLS Estimation: Fully Modified OLS estimator for cointegrating polynomial regressions following Wagner & Hong (2016)
- CT Test: KPSS-Shin type test with null hypothesis of cointegration
- PU Test: Phillips-Ouliaris type test with null hypothesis of no cointegration
- Long-run Variance Estimation: Multiple kernel functions (Bartlett, Parzen, Quadratic Spectral, etc.) with automatic bandwidth selection (Andrews 1991, Newey-West 1994, Andrews-Monahan 1992)
- Critical Values: Pre-computed critical values for up to 4 integrated regressors and power 4
- Publication-Ready Output: Formatted output suitable for academic publications
Installation
pip install cpr-econometrics
Or install from source:
git clone https://github.com/merwanroudane/cpr-econometrics.git
cd cpr
pip install -e .
Quick Start
Basic Example: Environmental Kuznets Curve
import numpy as np
from cpr import fm_cpr, ct_test, pu_test, CPRTestSummary
# Generate sample data (simulating EKC relationship)
np.random.seed(42)
T = 150 # Typical sample size for annual macro data
# GDP per capita (I(1) process)
gdp = np.cumsum(np.random.randn(T) * 0.1) + 10
# Generate AR(1) errors (serially correlated as in real economic data)
errors = np.zeros(T)
for t in range(1, T):
errors[t] = 0.5 * errors[t-1] + np.random.randn() * 0.3
# Emissions with quadratic relationship (inverted U-shape EKC)
emissions = 2.0 + 0.5 * gdp - 0.02 * gdp**2 + errors
# Create deterministic components (intercept and trend)
deter = np.column_stack([np.ones(T), np.arange(1, T + 1)])
# FM-OLS estimation
result = fm_cpr(
y=emissions,
x=gdp.reshape(-1, 1),
orders=2, # Quadratic specification
deter=deter,
kern='ba', # Bartlett kernel
band='NW' # Newey-West bandwidth
)
print("FM-OLS Coefficients for polynomial terms:", result.beta_fm)
print("t-statistics:", result.t_beta)
# CT Test (H0: Cointegration)
ct_result = ct_test(
u_plus=result.u_plus,
omega=result.Omega_udotv,
d=1, # intercept and trend
m=1, # 1 integrated regressor
p=2 # quadratic specification
)
print(ct_result)
# PU Test (H0: No Cointegration)
pu_result = pu_test(
y=emissions,
x=gdp.reshape(-1, 1),
d=1,
m=1,
orders=2
)
print(pu_result)
# Combined Summary
summary = CPRTestSummary(ct_result, pu_result)
print(summary)
Expected Results:
- CT statistic: ~0.03-0.10 (should be < 0.106 for cointegration at 5%)
- PU statistic: ~50-150 (should be > 52.95 for cointegration at 5%)
API Reference
FM-OLS Estimation
from cpr import fm_cpr
result = fm_cpr(
y, # Dependent variable (T,)
x, # Integrated regressors (T, m)
orders, # Polynomial orders (int or list)
w=None, # Stationary regressors (optional)
deter=None, # Deterministic terms (optional)
kern='ba', # Kernel: 'tr', 'ba', 'pa', 'bo', 'da', 'qs'
band='NW', # Bandwidth: 'And91', 'NW', 'AM92', or numeric
deme=0 # Demeaning: 0 or 1
)
# Results include:
# - result.beta_fm: FM-OLS coefficients for polynomial terms
# - result.t_beta: t-statistics
# - result.u_plus: FM-OLS residuals
# - result.Omega_udotv: Conditional long-run variance
CT Test (Cointegration Test)
from cpr import ct_test
ct_result = ct_test(
u_plus, # FM-OLS residuals
omega, # Long-run variance estimate
d, # Deterministics: -1, 0, or 1
m, # Number of integrated regressors (1-4)
p # Highest power (1-4)
)
# Interpretation:
# - Reject H0 (cointegration) if statistic > critical value
# - Low statistic → evidence FOR cointegration
PU Test (Non-Cointegration Test)
from cpr import pu_test
pu_result = pu_test(
y, # Dependent variable
x, # Integrated regressors
d, # Deterministics: -1, 0, or 1
m, # Number of integrated regressors
orders, # Polynomial orders
kern='ba', # Kernel function
band='NW' # Bandwidth
)
# Interpretation:
# - Reject H0 (no cointegration) if statistic > critical value
# - High statistic → evidence FOR cointegration
Deterministic Specifications
d |
Description | Model |
|---|---|---|
| -1 | No deterministics | y = β₁x + β₂x² + ... + u |
| 0 | Intercept only | y = c + β₁x + β₂x² + ... + u |
| 1 | Intercept and trend | y = c + δt + β₁x + β₂x² + ... + u |
Kernel Functions
| Code | Kernel | Use Case |
|---|---|---|
'tr' |
Truncated | Not recommended |
'ba' |
Bartlett | Standard choice (default) |
'pa' |
Parzen | Alternative to Bartlett |
'bo' |
Bohman | Smooth kernel |
'da' |
Daniell | Spectral analysis |
'qs' |
Quadratic Spectral | Optimal for some purposes |
Bandwidth Selection
| Code | Method | Reference |
|---|---|---|
'NW' |
Newey-West (1994) | Default, data-driven |
'And91' |
Andrews (1991) | AR(1)-based |
'AM92' |
Andrews-Monahan (1992) | VAR prewhitening |
| Numeric | Fixed bandwidth | User-specified |
Decision Rule for EKC Analysis
Following Wagner (2023):
| CT Test | PU Test | Interpretation |
|---|---|---|
| Fail to reject | Reject | Evidence FOR cointegration |
| Reject | Fail to reject | Evidence AGAINST cointegration |
| Reject | Reject | Conflicting evidence |
| Fail to reject | Fail to reject | Conflicting evidence |
Critical Values
Critical values are embedded in the package for:
m = 1, 2, 3, 4integrated regressorsp = 1, 2, 3, 4polynomial powersd = -1, 0, 1deterministic specifications- Significance levels: 1%, 2.5%, 5%, 10%
from cpr import get_ct_critical_value, get_pu_critical_value
# Get specific critical value
cv_ct = get_ct_critical_value(d=1, m=1, p=2, alpha=0.05)
cv_pu = get_pu_critical_value(d=1, m=1, p=2, alpha=0.05)
Applications
This package is suitable for:
- Environmental Kuznets Curve (EKC) analysis
- Material Kuznets Curve (MKC) studies
- Intensity-of-use analysis
- Exchange rate target-zone models
- Any nonlinear cointegrating relationship involving powers of I(1) variables
Requirements
- Python ≥ 3.8
- NumPy ≥ 1.20.0
- SciPy ≥ 1.7.0
- pandas ≥ 1.3.0
- statsmodels ≥ 0.13.0
Citation
If you use this package in your research, please cite:
@article{wagner2023residual,
title={Residual-based cointegration and non-cointegration tests for cointegrating polynomial regressions},
author={Wagner, Martin},
journal={Empirical Economics},
volume={65},
pages={1--31},
year={2023},
publisher={Springer},
doi={10.1007/s00181-022-02332-3}
}
License
MIT License - see LICENSE for details.
Author
Dr Merwan Roudane
Email: merwanroudane920@gmail.com
GitHub: https://github.com/merwanroudane/cpr
Acknowledgments
This implementation is based on the MATLAB code accompanying Wagner (2023) and follows the econometric methodology developed in Wagner & Hong (2016).
Metadata
Release files for cpr-econometrics 0.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| cpr_econometrics-0.0.2.tar.gz | 39.7 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cpr_econometrics-0.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 76.3 kB
Release files / cpr_econometrics-0.0.2.tar.gz
| Download URL | cpr_econometrics-0.0.2.tar.gz |
|---|---|
| Size | 39.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9df3c35cd169ab8c5543d2fe575121f400af41b6de8aff43b7e1df39f905996b
|
|
BLAKE2b-256 checksum How to use checksums |
78bff95f6972771ef98cf07dc34ac0bb19662c19f9787fb9c17e6842d753c9b1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|
Release files / cpr_econometrics-0.0.2-py3-none-any.whl
| Download URL | cpr_econometrics-0.0.2-py3-none-any.whl |
|---|---|
| Size | 36.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
37b7e614f84353b7fcc81f255a693f8c51f5e7c111d3349dcc8b10c1e1d30329
|
|
BLAKE2b-256 checksum How to use checksums |
6f1bc7733850c50deb83e3272aa1c17a4ddaf77cd6772be2fbe92c7692383355
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|
Security for cpr-econometrics 0.0.2
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.