robcointeg
Outlier-Robust Cointegration Analysis
A Python implementation of outlier-robust cointegration testing based on the methodology of Franses & Lucas (1998).
Author: Dr Merwan Roudane
Email: merwanroudane920@gmail.com
GitHub: https://github.com/merwanroudane/robcointeg
Overview
Standard unit-root and cointegration tests are sensitive to atypical events such as outliers and structural breaks. This package implements the outlier-robust cointegration test proposed by Franses & Lucas (1998), which provides:
-
Robust Cointegration Testing: A pseudolikelihood ratio (PLR) test based on the Student-t distribution that is less sensitive to outliers than the standard Gaussian-based Johansen test.
-
Outlier Detection: Observation weights that identify which data points may be driving the cointegration results.
-
Diagnostic Tools: Methods for comparing robust and non-robust test results to signal when standard cointegration results might be influenced by aberrant observations.
Installation
From PyPI (when published)
pip install robcointeg
From Source
git clone https://github.com/merwanroudane/robcointeg.git
cd robcointeg
pip install -e .
With Plotting Support
pip install robcointeg[plotting]
Full Installation (all optional dependencies)
pip install robcointeg[full]
Quick Start
Basic Usage
import numpy as np
from robcointeg import RobustVAR, compare_tests, diagnostic_report
# Generate sample data
np.random.seed(42)
T = 100
y = np.cumsum(np.random.randn(T, 2), axis=0)
# Add an outlier
y[50, 0] += 5
# Fit robust VAR model
model = RobustVAR(p=2, nu=5)
model.fit(y)
# View results
print(model.summary())
print(f"Observation weights: {model.weights}")
Cointegration Testing
from robcointeg import plr_test, johansen_trace_test
# Robust test (Student-t based)
robust_result = plr_test(y, p=2, nu=5, r=0)
print(f"Robust PLR statistic: {robust_result.test_statistic:.2f}")
print(f"Reject at 5%: {robust_result.reject[0.05]}")
# Standard Johansen test for comparison
johansen_result = johansen_trace_test(y, p=2, r=0)
print(f"Johansen statistic: {johansen_result.test_statistic:.2f}")
Compare Robust and Non-Robust Tests
from robcointeg import compare_tests
comparison = compare_tests(y, p=2, nu=5)
print(comparison['summary'])
if comparison['conflict']:
print("⚠ Tests give different results!")
print(f"Gaussian rank: {comparison['gaussian_rank']}")
print(f"Robust rank: {comparison['robust_rank']}")
Full Diagnostic Report
from robcointeg import diagnostic_report
report = diagnostic_report(
y, p=2, nu=5,
variable_names=['Y1', 'Y2'],
significance_level=0.05
)
Methodology
This package implements the methodology from:
Franses, P.H. & Lucas, A. (1998). "Outlier Detection in Cointegration Analysis", Journal of Business & Economic Statistics, 16:4, 459-468.
Key Equations
1. VAR/VECM Model (Equation 1):
$$\Delta y_t = \alpha\beta' y_{t-1} + \Phi_1 \Delta y_{t-1} + \cdots + \Phi_{p-1} \Delta y_{t-p+1} + \mu + \varepsilon_t$$
2. Student-t Pseudolikelihood (Equation 2):
$$\mathcal{L}(\theta) = \prod_{t=1}^{T} \frac{\Gamma((\nu+k)/2)}{\Gamma(\nu/2)|\pi\nu V|^{1/2}} \left(1 + \frac{\varepsilon_t' V^{-1} \varepsilon_t}{\nu}\right)^{-(\nu+k)/2}$$
3. Pseudolikelihood Ratio Test (Equation 3):
$$\text{PLR} = 2 \ln\left(\frac{\mathcal{L}(\hat{\theta})}{\mathcal{L}(\tilde{\theta})}\right)$$
4. Observation Weights (Equation 8):
$$w_t = \left(\frac{\nu}{\nu + \varepsilon_t' V^{-1} \varepsilon_t}\right)^{1/2}$$
Interpretation of Weights
- Low weight ($w_t < 0.67$ for $\nu=5$, $k=2$): The observation does not correspond to the general pattern of the model and deserves closer inspection.
- Consecutive low weights may indicate additive outliers (AO).
- Low weights at the start and end of a period may indicate level shifts.
- Many consecutive low weights may indicate variance shifts.
API Reference
Core Classes
RobustVAR
from robcointeg import RobustVAR
model = RobustVAR(p=2, nu=5, with_constant=True)
model.fit(y)
# Attributes
model.weights # Observation weights
model.residuals # Model residuals
model.log_likelihood # Log pseudolikelihood
model.Pi # Long-run impact matrix
model.alpha # Loading matrix
model.beta # Cointegrating vectors
model.eigenvalues # Eigenvalues
RobustCointegrationTest
from robcointeg import sequential_plr_test
result = sequential_plr_test(y, p=2, nu=5)
# Attributes
result.test_results # List of test results for each rank
result.selected_rank # Determined cointegrating rank
result.weights # Observation weights
result.outlier_indices # Detected outlier indices
result.summary # Text summary
Main Functions
| Function | Description |
|---|---|
plr_test() |
Perform PLR test for a specific rank |
johansen_trace_test() |
Standard Johansen trace test |
compare_tests() |
Compare robust and non-robust tests |
compute_weights() |
Compute observation weights |
detect_outliers() |
Identify outlying observations |
diagnostic_report() |
Generate full diagnostic report |
Critical Values
The package includes critical values from Table 1 of Franses & Lucas (1998):
from robcointeg import get_critical_value, CriticalValueTable
# Get single critical value
cv = get_critical_value(k_minus_r=2, nu=5, significance_level=0.05)
# Access full table
table = CriticalValueTable(with_drift=True)
print(table.print_table())
Examples
Example 1: Finland/U.S. Real Exchange Rate
This replicates the empirical application from Section 3 of the paper:
import numpy as np
from robcointeg import compare_tests, plot_comparison_panel
# Load Finland/U.S. exchange rate data (hypothetical)
# y should contain: log(CPI_US), log(CPI_Finland), log(Exchange_Rate)
comparison = compare_tests(y, p=2, nu=5)
print(comparison['summary'])
# Visualize (requires matplotlib)
plot_comparison_panel(
y, comparison['weights'], comparison['outlier_indices'],
nu=5, k=3, title='Finland/U.S. Real Exchange Rate Analysis'
)
Example 2: Monte Carlo Simulation
from robcointeg import monte_carlo_critical_values
# Simulate critical values
cv = monte_carlo_critical_values(
k_minus_r=2, nu=5, n_sim=10000, T=100, with_drift=True
)
print(f"95% critical value: {cv[0.95]:.2f}")
Citation
If you use this package in your research, please cite the original paper:
@article{franses1998outlier,
title={Outlier Detection in Cointegration Analysis},
author={Franses, Philip Hans and Lucas, Andr{\'e}},
journal={Journal of Business \& Economic Statistics},
volume={16},
number={4},
pages={459--468},
year={1998},
publisher={Taylor \& Francis}
}
And this software:
@software{robcointeg,
author = {Roudane, Merwan},
title = {robcointeg: Outlier-Robust Cointegration Analysis in Python},
year = {2025},
url = {https://github.com/merwanroudane/robcointeg}
}
References
- Franses, P.H. & Lucas, A. (1998). "Outlier Detection in Cointegration Analysis", Journal of Business & Economic Statistics, 16:4, 459-468.
- Johansen, S. (1988). "Statistical Analysis of Cointegration Vectors", Journal of Economic Dynamics and Control, 12, 231-254.
- Johansen, S. (1991). "Estimation and Hypothesis Testing of Cointegration Vectors in Gaussian Vector Autoregressive Models", Econometrica, 59, 1551-1580.
- Lucas, A. (1997). "Cointegration Testing Using Pseudo Likelihood Ratio Tests", Econometric Theory, 13, 149-169.
- Lucas, A. (1998). "Inference on Cointegrating Ranks Using LR and LM Tests Based on Pseudo Likelihoods", Econometric Reviews, 17, 185-214.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Changelog
Version 0.0.1 (2025)
- Initial release
- Implementation of Franses & Lucas (1998) methodology
- Student-t pseudolikelihood ratio (PLR) test
- Observation weight computation
- Outlier detection
- Comparison with standard Johansen test
- Visualization tools
- Critical value tables from the original paper
Metadata
Release files for robcointeg 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 | |
|---|---|---|---|---|
| robcointeg-0.0.2.tar.gz | 44.7 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| robcointeg-0.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 85.8 kB
Release files / robcointeg-0.0.2.tar.gz
| Download URL | robcointeg-0.0.2.tar.gz |
|---|---|
| Size | 44.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
aeff0c9965f94c25b8939432f634198337627b9394c6d2b0a8dabe76b056339e
|
|
BLAKE2b-256 checksum How to use checksums |
a5c0dc5c69c71f855e634fa74e5351f66b46d6248446df78f9f6de3bec5f2064
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|
Release files / robcointeg-0.0.2-py3-none-any.whl
| Download URL | robcointeg-0.0.2-py3-none-any.whl |
|---|---|
| Size | 41.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2add44f01044b782b335f8f58d7af89312a78bc237393556a678a43df5404105
|
|
BLAKE2b-256 checksum How to use checksums |
371dba96e6000b417df085f7ec375ee0fa8a0d3cd4c25402641ec7436392f310
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|
Security for robcointeg 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.