Skip to main content

Asymmetric Causality Testing - Implementation of Hatemi-J (2012) test

Project description

asymcaus

PyPI version Python Version License: MIT

Asymmetric Causality Testing in Python

A Python implementation of the asymmetric causality test developed by Hatemi-J (2012). This package allows testing for Granger-causal relationships between positive and negative components of time series variables separately.

📚 Background

Traditional Granger causality tests assume that the causal impact of positive shocks is the same as negative shocks in absolute terms. However, economic agents often react differently to positive versus negative news. The asymmetric causality test addresses this limitation by decomposing variables into cumulative positive and negative changes and testing causality between these components separately.

🎯 Features

  • Asymmetric Causality Testing: Test causal relationships between positive and negative components
  • Bootstrap Critical Values: Leverage-adjusted bootstrap for robust inference under non-normality and ARCH effects
  • Multiple Information Criteria: AIC, AICC, BIC/SBC, HQC, and Hatemi-J Criterion (HJC)
  • Toda-Yamamoto Procedure: Handle integrated variables without pre-testing for cointegration
  • Comprehensive Diagnostics: Multivariate normality tests, ARCH tests, and autocorrelation tests
  • Unit Root Tests: ADF, KPSS, and Phillips-Perron tests

📦 Installation

pip install asymcaus

For development installation with all dependencies:

pip install asymcaus[full]

🚀 Quick Start

Basic Usage

import numpy as np
from asymcaus import asymmetric_causality_test

# Generate sample data (two I(1) series)
np.random.seed(42)
T = 500
z = np.cumsum(np.random.randn(T))  # Cause variable
y = np.cumsum(np.random.randn(T))  # Effect variable

# Test if positive shocks in Z cause positive shocks in Y
result = asymmetric_causality_test(
    y=y, 
    z=z, 
    component='positive',
    n_bootstrap=1000
)

# View results
print(result.summary())

Full Analysis (All Components)

from asymcaus import full_asymmetric_causality_analysis, print_full_analysis

# Test all combinations
results = full_asymmetric_causality_analysis(
    y=y, 
    z=z,
    var_names=('Oil Price', 'Stock Index'),
    n_bootstrap=1000
)

# Print comprehensive summary
print(print_full_analysis(results))

With Unit Root Pre-testing

from asymcaus import determine_integration_order, asymmetric_causality_test

# Determine integration order
int_order_y, _ = determine_integration_order(y)
int_order_z, _ = determine_integration_order(z)
int_order = max(int_order_y, int_order_z)

print(f"Integration order: {int_order}")

# Use Toda-Yamamoto procedure
result = asymmetric_causality_test(
    y=y,
    z=z,
    component='positive',
    integration_order=int_order,  # Add extra lags
    criterion='hjc'
)

Diagnostic Tests

from asymcaus import run_all_diagnostics, print_diagnostics_summary

# After running causality test, check residual diagnostics
# (Assumes you have residuals from VAR estimation)
residuals = np.random.randn(100, 2)  # Example residuals

diagnostics = run_all_diagnostics(residuals)
print(print_diagnostics_summary(diagnostics))

📖 API Reference

Main Functions

asymmetric_causality_test(y, z, component='positive', ...)

Perform the Hatemi-J (2012) asymmetric causality test.

Parameters:

  • y (array): Dependent variable (effect)
  • z (array): Independent variable (cause)
  • component (str): Type of component to test
    • 'positive': Test Z+ → Y+
    • 'negative': Test Z- → Y-
    • 'positive_to_negative': Test Z+ → Y-
    • 'negative_to_positive': Test Z- → Y+
    • 'original': Test without decomposition
  • criterion (str): Information criterion ('aic', 'bic', 'hqc', 'hjc')
  • max_lag (int): Maximum lag order (default: 8)
  • integration_order (int): Order of integration for Toda-Yamamoto (default: 0)
  • n_bootstrap (int): Number of bootstrap replications (default: 1000)
  • log_transform (bool): Apply log transformation (default: False)
  • var_names (tuple): Names for variables
  • random_state (int): Random seed for reproducibility

Returns: AsymmetricCausalityResult object

full_asymmetric_causality_analysis(y, z, ...)

Run asymmetric causality tests for all component combinations.

cumulative_components(y, log_transform=False)

Calculate cumulative positive and negative components.

Unit Root Tests

  • adf_test(y, trend='c') - Augmented Dickey-Fuller test
  • kpss_test(y, trend='c') - KPSS stationarity test
  • pp_test(y, trend='c') - Phillips-Perron test
  • determine_integration_order(y) - Automatic integration order detection

Diagnostic Tests

  • doornik_hansen_test(residuals) - Multivariate normality test
  • multivariate_arch_test(residuals) - ARCH effects test
  • ljung_box_test(residuals) - Autocorrelation test
  • run_all_diagnostics(residuals) - Run all diagnostics

📊 Example: Oil Prices and Stock Markets

Replicating the UAE market analysis from Hatemi-J (2012):

import numpy as np
from asymcaus import (
    asymmetric_causality_test,
    full_asymmetric_causality_analysis,
    print_full_analysis,
    determine_integration_order
)

# Load your data (oil prices and stock index)
# oil_price = ...
# stock_index = ...

# Example with simulated data
np.random.seed(2012)
T = 488

# Simulated I(1) processes
oil_price = np.cumsum(np.random.randn(T) * 0.02) + 4.5
stock_index = np.cumsum(np.random.randn(T) * 0.015) + 5.0

# Determine integration order
int_order, _ = determine_integration_order(oil_price)
print(f"Oil price integration order: {int_order}")

# Full asymmetric causality analysis
results = full_asymmetric_causality_analysis(
    y=stock_index,
    z=oil_price,
    var_names=('Oil', 'Stock'),
    integration_order=1,
    n_bootstrap=1000,
    criterion='hjc'
)

print(print_full_analysis(results))

📝 Interpretation of Results

The test evaluates the null hypothesis:

H₀: Variable Z does not Granger-cause variable Y

For asymmetric components:

  • Positive components (Z+ → Y+): Do positive shocks in Z cause positive shocks in Y?
  • Negative components (Z- → Y-): Do negative shocks in Z cause negative shocks in Y?
  • Cross effects (Z+ → Y-, Z- → Y+): Do shocks of one sign cause opposite effects?

Decision Rule:

  • If Wald statistic > Bootstrap critical value → Reject H₀ (causality exists)
  • Bootstrap critical values are preferred over χ² critical values when data exhibits non-normality or ARCH effects

🔬 Methodology

Cumulative Sum Decomposition

For a time series y_t, positive and negative shocks are defined as:

ε⁺_t = max(Δy_t, 0)
ε⁻_t = min(Δy_t, 0)

Cumulative sums:

y⁺_t = Σᵢ₌₁ᵗ ε⁺ᵢ
y⁻_t = Σᵢ₌₁ᵗ ε⁻ᵢ

Bootstrap with Leverage Adjustment

The bootstrap procedure:

  1. Estimate restricted VAR model (under H₀)
  2. Calculate leverage-adjusted residuals
  3. Generate bootstrap samples
  4. Compute bootstrap Wald statistics
  5. Derive critical values from bootstrap distribution

Information Criteria

The Hatemi-J Criterion (HJC) is the average of SBC and HQC:

HJC = (SBC + HQC) / 2

📚 References

  • Hatemi-J, A. (2012). Asymmetric Causality Tests with an Application. Empirical Economics, 43(1), 447-456.
  • Granger, C.W.J. & Yoon, G. (2002). Hidden Cointegration. Working Paper, UC San Diego.
  • Toda, H.Y. & Yamamoto, T. (1995). Statistical Inference in Vector Autoregressions with Possibly Integrated Processes. Journal of Econometrics, 66, 225-250.
  • Hacker, R.S. & Hatemi-J, A. (2006). Tests for Causality between Integrated Variables Using Asymptotic and Bootstrap Distributions. Applied Economics, 38(13), 1489-1500.

🤝 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

📄 License

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

👤 Author

Dr. Merwan Roudane

🙏 Acknowledgments

  • Original GAUSS code by Prof. Abdulnasser Hatemi-J and Prof. Scott Hacker
  • Based on the methodology in Hatemi-J (2012), Empirical Economics

📈 Citation

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

@software{roudane2024asymcaus,
  author = {Roudane, Merwan},
  title = {asymcaus: Asymmetric Causality Testing in Python},
  year = {2024},
  url = {https://github.com/merwanroudane/asymcaus}
}

@article{hatemi2012asymmetric,
  title={Asymmetric causality tests with an application},
  author={Hatemi-J, Abdulnasser},
  journal={Empirical Economics},
  volume={43},
  number={1},
  pages={447--456},
  year={2012},
  publisher={Springer}
}

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

asymcaus-2.0.0.tar.gz (31.8 kB view details)

Uploaded Source

Built Distribution

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

asymcaus-2.0.0-py3-none-any.whl (23.5 kB view details)

Uploaded Python 3

File details

Details for the file asymcaus-2.0.0.tar.gz.

File metadata

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

File hashes

Hashes for asymcaus-2.0.0.tar.gz
Algorithm Hash digest
SHA256 2107d851de6d85f16fdb181bc629e517b971800277ec178c34e0eb85081a406a
MD5 f8b94c7be3e3173407ef0f826b883073
BLAKE2b-256 189175a85cdac6af5b2d1bb858b1a962301035ec7f506de016295103ef109719

See more details on using hashes here.

File details

Details for the file asymcaus-2.0.0-py3-none-any.whl.

File metadata

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

File hashes

Hashes for asymcaus-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d7b79dca29cb151b037b7abf293dceb2fbaef9930a2e78535afb6e80c3f8cd50
MD5 5335bff6dcdc45ca3be6ae6dc8767497
BLAKE2b-256 350292386288024bae44e45299a0a12f45d9dea7c7ca31bbad9c803a9e23b98b

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