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.1.tar.gz (43.4 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.1-py3-none-any.whl (39.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: robcointeg-0.0.1.tar.gz
  • Upload date:
  • Size: 43.4 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.1.tar.gz
Algorithm Hash digest
SHA256 8881f72a643e3862f09f16cfacc9ac49b8df0b9805afb131d906c0d8bfc1c16c
MD5 793090802b784a14c5d42c87043f2b69
BLAKE2b-256 aca648cf88767f62ec6fd7a914fd1ef1bb2a6a1547907522a6ea882ed9871b96

See more details on using hashes here.

File details

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

File metadata

  • Download URL: robcointeg-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 39.7 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 78fa8b1aaa60ffb87b2614c703e27983ce2fbbd16fbbf9360f7e66e64917dbdf
MD5 0a18cdfdb587013e580a72f6be70f0b7
BLAKE2b-256 f5c866f3609d7b9a5d214f418dfc3bf0c70fbffc41aa52a97421c2dce15a2764

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