"""
Example: Asymmetric Causality Analysis
======================================

This example demonstrates how to use the asymcaus package to perform
asymmetric causality testing following Hatemi-J (2012).

We replicate a simplified version of the analysis from the original paper,
examining the causal relationship between oil prices and stock market indices.
"""

import numpy as np

# Import from asymcaus
from asymcaus import (
    # Main test functions
    asymmetric_causality_test,
    full_asymmetric_causality_analysis,
    print_full_analysis,
    
    # Data transformation
    cumulative_components,
    
    # Unit root tests
    adf_test,
    determine_integration_order,
    
    # Diagnostics
    run_all_diagnostics,
    print_diagnostics_summary,
)


def main():
    """Main example demonstrating asymmetric causality testing."""
    
    print("=" * 70)
    print("      ASYMMETRIC CAUSALITY TEST - EXAMPLE APPLICATION")
    print("      Following Hatemi-J (2012), Empirical Economics")
    print("=" * 70)
    print()
    
    # =========================================================================
    # 1. Generate Sample Data
    # =========================================================================
    print("1. GENERATING SAMPLE DATA")
    print("-" * 70)
    
    np.random.seed(2012)  # For reproducibility
    T = 488  # Sample size similar to Hatemi-J (2012)
    
    # Simulate I(1) processes (random walks with drift)
    # Oil prices
    oil_innovations = np.random.randn(T) * 0.025
    oil_price = np.cumsum(oil_innovations) + 4.5  # Log oil price
    
    # Stock prices  
    stock_innovations = np.random.randn(T) * 0.020
    stock_price = np.cumsum(stock_innovations) + 5.0  # Log stock price
    
    print(f"Sample size: {T} observations")
    print(f"Oil price range: [{oil_price.min():.2f}, {oil_price.max():.2f}]")
    print(f"Stock price range: [{stock_price.min():.2f}, {stock_price.max():.2f}]")
    print()
    
    # =========================================================================
    # 2. Unit Root Tests
    # =========================================================================
    print("2. UNIT ROOT TESTS")
    print("-" * 70)
    
    # Test oil prices
    adf_oil = adf_test(oil_price, trend='c')
    print(f"Oil Price - ADF Statistic: {adf_oil.statistic:.4f}")
    print(f"  Critical values: 1%: {adf_oil.critical_values['1%']:.2f}, "
          f"5%: {adf_oil.critical_values['5%']:.2f}")
    print(f"  Conclusion: {adf_oil.conclusion}")
    print()
    
    # Test stock prices
    adf_stock = adf_test(stock_price, trend='c')
    print(f"Stock Price - ADF Statistic: {adf_stock.statistic:.4f}")
    print(f"  Critical values: 1%: {adf_stock.critical_values['1%']:.2f}, "
          f"5%: {adf_stock.critical_values['5%']:.2f}")
    print(f"  Conclusion: {adf_stock.conclusion}")
    print()
    
    # Determine integration order
    int_order_oil, _ = determine_integration_order(oil_price)
    int_order_stock, _ = determine_integration_order(stock_price)
    integration_order = max(int_order_oil, int_order_stock)
    
    print(f"Integration order (Oil): I({int_order_oil})")
    print(f"Integration order (Stock): I({int_order_stock})")
    print(f"Using integration order: {integration_order} for Toda-Yamamoto")
    print()
    
    # =========================================================================
    # 3. Cumulative Components
    # =========================================================================
    print("3. CUMULATIVE POSITIVE AND NEGATIVE COMPONENTS")
    print("-" * 70)
    
    # Calculate cumulative components for visualization
    data = np.column_stack([stock_price, oil_price])
    cum_pos, cum_neg = cumulative_components(data)
    
    print(f"Stock+ range: [{cum_pos[:, 0].min():.2f}, {cum_pos[:, 0].max():.2f}]")
    print(f"Stock- range: [{cum_neg[:, 0].min():.2f}, {cum_neg[:, 0].max():.2f}]")
    print(f"Oil+ range: [{cum_pos[:, 1].min():.2f}, {cum_pos[:, 1].max():.2f}]")
    print(f"Oil- range: [{cum_neg[:, 1].min():.2f}, {cum_neg[:, 1].max():.2f}]")
    print()
    
    # =========================================================================
    # 4. Standard (Non-Asymmetric) Causality Test
    # =========================================================================
    print("4. STANDARD CAUSALITY TEST (Original Variables)")
    print("-" * 70)
    
    result_standard = asymmetric_causality_test(
        y=stock_price,
        z=oil_price,
        component='original',
        criterion='hjc',
        max_lag=10,
        integration_order=integration_order,
        n_bootstrap=1000,
        var_names=('Oil', 'Stock'),
        random_state=42
    )
    
    print(f"H0: Oil does not Granger-cause Stock")
    print(f"Wald Statistic: {result_standard.wald_stat:.4f}")
    print(f"Optimal Lag: {result_standard.optimal_lag}")
    print(f"Bootstrap CVs (1%, 5%, 10%): {result_standard.bootstrap_cv}")
    print(f"Chi-squared p-value: {result_standard.p_value_chi2:.4f}")
    print(f"Reject at 5%: {'Yes' if result_standard.reject_null['5%'] else 'No'}")
    print()
    
    # =========================================================================
    # 5. Asymmetric Causality Tests
    # =========================================================================
    print("5. ASYMMETRIC CAUSALITY TESTS")
    print("-" * 70)
    
    # Test positive components (Oil+ => Stock+)
    print("\n--- Testing: Oil+ => Stock+ ---")
    result_pos = asymmetric_causality_test(
        y=stock_price,
        z=oil_price,
        component='positive',
        criterion='hjc',
        max_lag=10,
        integration_order=integration_order,
        n_bootstrap=1000,
        var_names=('Oil', 'Stock'),
        random_state=42
    )
    print(f"Wald Statistic: {result_pos.wald_stat:.4f}")
    print(f"Bootstrap CV (5%): {result_pos.bootstrap_cv[1]:.4f}")
    print(f"Reject at 5%: {'Yes' if result_pos.reject_null['5%'] else 'No'}")
    
    # Test negative components (Oil- => Stock-)
    print("\n--- Testing: Oil- => Stock- ---")
    result_neg = asymmetric_causality_test(
        y=stock_price,
        z=oil_price,
        component='negative',
        criterion='hjc',
        max_lag=10,
        integration_order=integration_order,
        n_bootstrap=1000,
        var_names=('Oil', 'Stock'),
        random_state=42
    )
    print(f"Wald Statistic: {result_neg.wald_stat:.4f}")
    print(f"Bootstrap CV (5%): {result_neg.bootstrap_cv[1]:.4f}")
    print(f"Reject at 5%: {'Yes' if result_neg.reject_null['5%'] else 'No'}")
    
    # Test cross effects (Oil+ => Stock-)
    print("\n--- Testing: Oil+ => Stock- ---")
    result_pos_neg = asymmetric_causality_test(
        y=stock_price,
        z=oil_price,
        component='positive_to_negative',
        criterion='hjc',
        max_lag=10,
        integration_order=integration_order,
        n_bootstrap=1000,
        var_names=('Oil', 'Stock'),
        random_state=42
    )
    print(f"Wald Statistic: {result_pos_neg.wald_stat:.4f}")
    print(f"Bootstrap CV (5%): {result_pos_neg.bootstrap_cv[1]:.4f}")
    print(f"Reject at 5%: {'Yes' if result_pos_neg.reject_null['5%'] else 'No'}")
    
    # Test cross effects (Oil- => Stock+)
    print("\n--- Testing: Oil- => Stock+ ---")
    result_neg_pos = asymmetric_causality_test(
        y=stock_price,
        z=oil_price,
        component='negative_to_positive',
        criterion='hjc',
        max_lag=10,
        integration_order=integration_order,
        n_bootstrap=1000,
        var_names=('Oil', 'Stock'),
        random_state=42
    )
    print(f"Wald Statistic: {result_neg_pos.wald_stat:.4f}")
    print(f"Bootstrap CV (5%): {result_neg_pos.bootstrap_cv[1]:.4f}")
    print(f"Reject at 5%: {'Yes' if result_neg_pos.reject_null['5%'] else 'No'}")
    print()
    
    # =========================================================================
    # 6. Full Analysis Summary
    # =========================================================================
    print("6. COMPREHENSIVE ANALYSIS SUMMARY")
    print("-" * 70)
    
    full_results = full_asymmetric_causality_analysis(
        y=stock_price,
        z=oil_price,
        criterion='hjc',
        max_lag=10,
        integration_order=integration_order,
        n_bootstrap=1000,
        var_names=('Oil', 'Stock'),
        random_state=42
    )
    
    print(print_full_analysis(full_results))
    
    # =========================================================================
    # 7. Detailed Summary for One Test
    # =========================================================================
    print("7. DETAILED SUMMARY (Positive Components)")
    print("-" * 70)
    print(result_pos.summary())
    
    # =========================================================================
    # 8. Interpretation
    # =========================================================================
    print("\n8. INTERPRETATION OF RESULTS")
    print("-" * 70)
    print("""
Based on the asymmetric causality analysis:

1. STANDARD CAUSALITY (O => S):
   Tests whether oil price changes (overall) Granger-cause stock prices.
   
2. POSITIVE COMPONENTS (O+ => S+):
   Tests whether cumulative positive oil shocks cause positive stock movements.
   This captures the effect of oil price INCREASES on stock market GAINS.

3. NEGATIVE COMPONENTS (O- => S-):
   Tests whether cumulative negative oil shocks cause negative stock movements.
   This captures the effect of oil price DECREASES on stock market LOSSES.

4. CROSS EFFECTS (O+ => S-, O- => S+):
   Tests asymmetric effects where shocks of one sign cause opposite effects.

The bootstrap critical values are more reliable than chi-squared when:
- Data exhibits non-normality (common in financial data)
- ARCH effects are present (volatility clustering)
- Sample size is relatively small

Reference:
Hatemi-J, A. (2012). Asymmetric Causality Tests with an Application.
Empirical Economics, 43(1), 447-456.
""")


if __name__ == "__main__":
    main()
