Skip to main content

GJR-GARCH models with exogenous regressors in the variance equation

Project description

gjr-garch-x

PyPI version DOI License: MIT Python 3.9+

GJR-GARCH models with exogenous regressors in the variance equation.

A pure Python implementation of Glosten-Jagannathan-Runkle (1993) GARCH models that properly supports exogenous variables in the conditional variance equation—a feature missing from standard econometrics packages.

Why This Package?

Standard GARCH packages (including Python's arch) don't natively support exogenous regressors in the variance equation. This matters for:

  • Event studies: Testing whether specific events (regulatory announcements, infrastructure failures) affect volatility
  • Sentiment analysis: Including sentiment indicators as volatility drivers
  • Regime-dependent volatility: Adding dummy variables for different market conditions

This package implements the full GJR-GARCH-X specification:

σ²_t = ω + α·ε²_{t-1} + γ·ε²_{t-1}·I(ε_{t-1}<0) + β·σ²_{t-1} + Σδⱼ·x_{j,t}

Where x_{j,t} are your exogenous variables with coefficients δⱼ estimated via maximum likelihood.

Installation

pip install gjr-garch-x

Quick Start

import pandas as pd
from gjr_garch_x import estimate_gjr_garch_x

# Your returns data (log returns × 100)
returns = pd.Series(...)

# Exogenous variables for variance equation
exog_vars = pd.DataFrame({
    'D_event': event_dummy,           # Event indicator
    'sentiment': sentiment_score,      # Continuous variable
}, index=returns.index)

# Estimate model
results = estimate_gjr_garch_x(returns, exog_vars)

# Results
print(f"Converged: {results.converged}")
print(f"AIC: {results.aic:.2f}")
print(f"Event effect: {results.event_effects['D_event']:.4f}")
print(f"Leverage effect (γ): {results.leverage_effect:.4f}")

# Full summary
print(results.summary())

Features

  • Student-t innovations: Captures fat tails in financial returns
  • GJR-GARCH leverage effect: Asymmetric response to positive/negative shocks
  • Robust standard errors: Numerical Hessian computation with proper inference
  • Stationarity constraints: Enforced during optimization
  • Pandas integration: Works directly with Series/DataFrame objects
  • No dependencies on arch: Standalone implementation
  • Type hints: Full type annotations for IDE support

Model Specification

Variance Equation (GJR-GARCH-X)

σ²_t = ω + α·ε²_{t-1} + γ·ε²_{t-1}·I(ε_{t-1}<0) + β·σ²_{t-1} + Σδⱼ·x_{j,t}

Parameters:

  • ω (omega): Intercept, baseline variance level
  • α (alpha): ARCH effect, response to recent squared shocks
  • γ (gamma): Leverage effect, additional response to negative shocks
  • β (beta): GARCH effect, persistence of conditional variance
  • δⱼ: Coefficients on exogenous variables
  • ν (nu): Degrees of freedom for Student-t distribution

Leverage Effect Interpretation:

  • Positive shocks: volatility impact = α
  • Negative shocks: volatility impact = α + γ
  • If γ > 0: bad news increases volatility more than good news

Stationarity Condition

α + β + |γ|/2 < 1

Enforced automatically during estimation.

API Reference

estimate_gjr_garch_x(returns, exog_vars, method='SLSQP', verbose=False)

Main estimation function.

Parameters:

  • returns: pd.Series of log returns (recommend × 100 for numerical stability)
  • exog_vars: pd.DataFrame of exogenous variables, aligned with returns index
  • method: Optimization method ('SLSQP', 'L-BFGS-B', 'trust-constr')
  • verbose: Print estimation progress

Returns: GJRGARCHXResults object

GJRGARCHXResults

Results container with attributes:

  • converged: bool — Did optimization converge?
  • params: Dict[str, float] — All parameter estimates
  • std_errors: Dict[str, float] — Standard errors
  • pvalues: Dict[str, float] — Two-sided p-values
  • log_likelihood: float
  • aic, bic: float — Information criteria
  • volatility: pd.Series — Conditional standard deviation σ_t
  • residuals: pd.Series — Demeaned residuals ε_t
  • exog_effects: Dict[str, float] — All exogenous variable coefficients
  • event_effects: Dict[str, float] — Event-type exogenous coefficients
  • sentiment_effects: Dict[str, float] — Sentiment-type coefficients
  • leverage_effect: float — γ parameter
  • iterations: int — Optimizer iterations
  • n_obs: int — Number of observations

Example: Cryptocurrency Event Study

import pandas as pd
from gjr_garch_x import estimate_gjr_garch_x

# Load BTC returns
btc = pd.read_csv('btc_returns.csv', index_col='date', parse_dates=True)
returns = btc['log_return'] * 100  # Convert to percentage

# Create event dummies
exog = pd.DataFrame(index=returns.index)
exog['D_infrastructure'] = 0
exog['D_regulatory'] = 0

# Mark infrastructure events (e.g., exchange hacks)
infra_dates = ['2022-11-11', '2022-05-09']  # FTX, Terra
for date in infra_dates:
    # 7-day event window
    mask = (exog.index >= pd.Timestamp(date) - pd.Timedelta(days=3)) & \
           (exog.index <= pd.Timestamp(date) + pd.Timedelta(days=3))
    exog.loc[mask, 'D_infrastructure'] = 1

# Mark regulatory events
reg_dates = ['2024-01-10', '2021-09-24']  # ETF approval, China ban
for date in reg_dates:
    mask = (exog.index >= pd.Timestamp(date) - pd.Timedelta(days=3)) & \
           (exog.index <= pd.Timestamp(date) + pd.Timedelta(days=3))
    exog.loc[mask, 'D_regulatory'] = 1

# Estimate
results = estimate_gjr_garch_x(returns, exog, verbose=True)

# Compare effects
print(f"Infrastructure effect: {results.event_effects['D_infrastructure']:.4f}")
print(f"Regulatory effect: {results.event_effects['D_regulatory']:.4f}")
print(f"Ratio: {results.event_effects['D_infrastructure'] / results.event_effects['D_regulatory']:.2f}x")

Backwards Compatibility

For users migrating from TARCH naming conventions, aliases are provided:

from gjr_garch_x import estimate_tarch_x, TARCHXResults, TARCHXEstimator

These are identical to the GJR-prefixed versions.

Citation

If you use this package in academic work, please cite:

@software{farzulla2025gjrgarchx,
  author = {Farzulla, Murad},
  title = {gjr-garch-x: GJR-GARCH Models with Exogenous Variance Regressors},
  year = {2025},
  publisher = {PyPI},
  url = {https://github.com/studiofarzulla/gjr-garch-x}
}

For the research paper that motivated this implementation:

@techreport{farzulla2025infrastructure,
  author = {Farzulla, Murad},
  title = {Market Reaction Asymmetry: Infrastructure Disruption Dominance
           Over Regulatory Uncertainty in Cryptocurrency Markets},
  year = {2025},
  type = {Working Paper},
  doi = {10.2139/ssrn.5788082}
}

References

  • Glosten, L. R., Jagannathan, R., & Runkle, D. E. (1993). On the relation between the expected value and the volatility of the nominal excess return on stocks. Journal of Finance, 48(5), 1779-1801.
  • Engle, R. F., & Ng, V. K. (1993). Measuring and testing the impact of news on volatility. Journal of Finance, 48(5), 1749-1778.
  • Bollerslev, T., & Wooldridge, J. M. (1992). Quasi-maximum likelihood estimation and inference in dynamic models with time-varying covariances. Econometric Reviews, 11(2), 143-172.

License

MIT License. See LICENSE for details.

Contributing

Contributions welcome. Please open an issue first to discuss proposed changes.

Author

Murad Farzulla MSc Finance Analytics, King's College London ORCID: 0009-0002-7164-8704

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

gjr_garch_x-0.1.0.tar.gz (13.9 kB view details)

Uploaded Source

Built Distribution

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

gjr_garch_x-0.1.0-py3-none-any.whl (12.1 kB view details)

Uploaded Python 3

File details

Details for the file gjr_garch_x-0.1.0.tar.gz.

File metadata

  • Download URL: gjr_garch_x-0.1.0.tar.gz
  • Upload date:
  • Size: 13.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for gjr_garch_x-0.1.0.tar.gz
Algorithm Hash digest
SHA256 9cd9f0b42a41e8db45e3132908ef5f1ebd77cbd3e4ad24e23c054587a1bb9de5
MD5 2d600045728c64f82c39c6981716dc9b
BLAKE2b-256 521ad410dd1a7daca87e09ba7f92b0e9a868da4a1bd7a2571418c204c73d1f41

See more details on using hashes here.

File details

Details for the file gjr_garch_x-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: gjr_garch_x-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for gjr_garch_x-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 581db1d2084950842882a4c7b689d2b96b57f930f310a870c71c415ea9d51cf6
MD5 0bb9df7074208f6d0461e4a71dad8d8b
BLAKE2b-256 64df4e59365fc7e4179a58c48e9672017a2f16a24de8dace0644d91cb743da83

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