Skip to main content

Outlier-Robust Cointegration Analysis based on Franses & Lucas (1998)

Project description

robcointeg

Outlier-Robust Cointegration Analysis

Python Version License: MIT

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:

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

  2. Outlier Detection: Observation weights that identify which data points may be driving the cointegration results.

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

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. 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

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

robcointeg-0.0.2.tar.gz (44.7 kB view details)

Uploaded Source

Built Distribution

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

robcointeg-0.0.2-py3-none-any.whl (41.1 kB view details)

Uploaded Python 3

File details

Details for the file robcointeg-0.0.2.tar.gz.

File metadata

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

File hashes

Hashes for robcointeg-0.0.2.tar.gz
Algorithm Hash digest
SHA256 aeff0c9965f94c25b8939432f634198337627b9394c6d2b0a8dabe76b056339e
MD5 e7d65ba70200c438358529047ab56879
BLAKE2b-256 a5c0dc5c69c71f855e634fa74e5351f66b46d6248446df78f9f6de3bec5f2064

See more details on using hashes here.

File details

Details for the file robcointeg-0.0.2-py3-none-any.whl.

File metadata

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

File hashes

Hashes for robcointeg-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 2add44f01044b782b335f8f58d7af89312a78bc237393556a678a43df5404105
MD5 6b0e63eb49d30471f9c8e9dccac712e6
BLAKE2b-256 371dba96e6000b417df085f7ec375ee0fa8a0d3cd4c25402641ec7436392f310

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