Skip to content

chenxi-bot21/market-risk-engine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

marketrisk — Multi-Asset VaR / ES Engine

CI Python Tests License

A market-risk engine covering the full desk workflow: Value-at-Risk and Expected Shortfall by four methods (historical, parametric-normal, Cornish-Fisher, Monte Carlo), EWMA and GARCH(1,1) volatility, Euler risk decomposition (component VaR), stress testing & scenario analysis (hypothetical shock library + historical worst-window replay), EVT tail estimation (Peaks-over-Threshold GPD for the 99.5%+ quantiles), and a regulatory-grade backtest (rolling out-of-sample VaR + Kupiec POF, Christoffersen independence / conditional coverage, Basel traffic light).

Pairs with the credit-risk PD/IFRS 9 project to cover both halves of a bank risk stack: credit + market risk.

Runs fully offline (reproducible synthetic multi-asset data, no API key); upgrades to real prices via yfinance when installed. GARCH is implemented directly on scipy MLE — no arch dependency.

➡️ How each method works and why: METHODOLOGY.md

Quickstart

pip install -e .            # numpy + pandas + scipy only
python -m marketrisk run    # synthetic 4-asset book, writes output/market_risk_report.md
Assets: EQUITY, BOND, GOLD, FX  |  1249 return days  |  weights: [0.25 0.25 0.25 0.25]

99% one-day VaR / ES
  Historical VaR                1.117%
  Historical ES                 1.234%
  Parametric (Normal) VaR       1.022%
  Parametric (Normal) ES        1.172%
  Cornish-Fisher VaR            1.057%
  Monte Carlo VaR               1.019%
  Monte Carlo ES                1.160%

GARCH(1,1): persistence=0.620, long-run vol=0.442%/day
Backtest: 16 violations vs 10.0 expected → Basel zone: YELLOW
  Kupiec POF                       LR= 3.089  p=0.079  pass
  Christoffersen independence      LR= 0.521  p=0.470  pass
  Conditional coverage (POF+ind)   LR= 3.610  p=0.164  pass

Note how the methods disagree: historical VaR (1.117%) sits above normal VaR (1.022%) because the data has fatter tails than a Gaussian — exactly the gap Cornish-Fisher (1.057%) partially recovers. That cross-method comparison is the point of running all four.

Your own portfolio

# CSV of prices (date index, one column per asset), custom weights & level
python -m marketrisk run --source csv --csv prices.csv --weights 0.5,0.3,0.2 --alpha 0.975

# Real prices from Yahoo Finance (optional dependency)
pip install -e ".[live]"
python -m marketrisk run --source yfinance --tickers SPY,TLT,GLD --start 2019-01-01

Dashboard

pip install -e ".[app]"     # streamlit + plotly
streamlit run app.py

Five tabs: VaR/ES method comparison · EWMA vs GARCH volatility (+ forecast) · backtest chart with violations and test table · component-VaR decomposition · stress scenarios.

What's inside

Module Contents
var.py Historical, parametric-normal, Cornish-Fisher (skew/kurtosis-adjusted), and Monte Carlo VaR & ES; one-call var_summary
volatility.py RiskMetrics EWMA (λ=0.94) and GARCH(1,1) by MLE (scipy L-BFGS-B, feasibility-penalised), with mean-reverting vol forecasts
decompose.py Marginal & component VaR via Euler allocation — components sum exactly to total VaR (tested to 1e-12)
backtest.py Walk-forward VaR (no look-ahead), Kupiec POF, Christoffersen independence & conditional coverage, Basel traffic light
evt.py Extreme Value Theory: Peaks-over-Threshold GPD tail fit, EVT VaR/ES for the far tail (99.5%+) where historical runs out of data
scenarios.py Stress testing: hypothetical shock library (GFC-style crash, rates spike, flight-to-quality…) + empirical worst-k-day historical replay with auditable dates
data.py Reproducible correlated-GBM synthetic book / CSV / yfinance (pluggable)
report.py, cli.py Markdown risk report + python -m marketrisk CLI

Engineering

  • src/ package layout, typed dataclasses, 58 unit tests including closed-form checks (normal VaR/ES vs analytic values), Euler-additivity to 12 decimals, seeded Monte-Carlo determinism, GARCH parameter recovery on simulated GARCH data, and statistical-test behaviour (clustered violations must fail Christoffersen; correct coverage must pass Kupiec).
  • CI on Python 3.11 / 3.12; core deps are just numpy + pandas + scipy.
python -m unittest discover -s tests -t .

License

MIT © Chenxi Zhao

About

Multi-asset market risk engine in Python: Value at Risk (VaR) and Expected Shortfall by 4 methods (historical, parametric, Cornish-Fisher, Monte Carlo), EWMA + GARCH(1,1) volatility by MLE, extreme value theory (EVT) tail risk, component VaR, stress testing, and Kupiec/Christoffersen/Basel traffic-light backtesting.

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages