Skip to content

FK-75/volatility-waves

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Volatility Waves 〰️

A dual-head Transformer that forecasts 21-day realised volatility and classifies the current volatility regime (Low / Normal / High Stress), then injects that forecast into a Monte Carlo simulation engine to generate realistic price paths.

The core innovation is replacing the fixed σ in standard Geometric Brownian Motion with a time-varying σ(t) produced by the model:

# Standard GBM — σ is a single historical constant
S(t+1) = S(t) × exp( (μ − σ²/2)dt + σ√dt × Z )

# Volatility Waves — σ(t) comes from the Transformer forecast
S(t+1) = S(t) × exp( (μ − σ(t)²/2)dt + σ(t)√dt × Z )

Pre-trained checkpoints are included for: SPY · AAPL · NVDA · MSFT · AMZN · GOOGL · GLD · QQQ · TLT · XOM · BTC-USD


Demo

streamlit run app.py

Pick a ticker, simulation horizon (5–63 days), number of paths (1k / 5k / 10k), and simulation mode. The app generates a percentile fan chart (5th / 25th / 50th / 75th / 95th) plus VaR, CVaR, and a regime probability table in real time.


Architecture

Input: (batch, 63 days, 9 features)
  └─ Linear projection + LayerNorm  →  d = 64
  └─ Learnable positional embedding
  └─ 3× TransformerEncoderLayer (4 heads, GELU, dropout = 0.1)
  └─ Last token  (current market state)
      ├─ Vol head:    LayerNorm → Linear(64,32) → GELU → Linear(32,1)   → scalar vol forecast
      └─ Regime head: LayerNorm → Linear(64,32) → GELU → Linear(32,3)  → softmax regime probs

~250 k parameters.  Trains in ≈5 min on CPU, ≈90 s on MPS/CUDA.
Loss = 0.7 × MSE(vol) + 0.3 × CrossEntropy(regime)

Simulation modes

Mode σ source
AI vol Time-varying σ(t) interpolated from current realised vol to Transformer forecast
Regime switch Per-path regime drawn from the model's softmax probabilities, each regime has its own σ and drift
GBM baseline Constant σ from trailing 21-day realised vol (standard GBM)

Features

Feature Description
log_ret Daily log return
rvol_5 5-day realised vol (annualised)
rvol_10 10-day realised vol (annualised)
rvol_21 21-day realised vol — also the regression target
rvol_63 63-day realised vol (annualised)
park_vol Parkinson high-low estimator
vvol Vol-of-vol: rolling std of rvol_21 — regime transition signal
vix VIX level (implied vol)
vix_ratio rvol_21 / VIX — > 1 means realised exceeded implied

Project Structure

volatility-waves/
├── app.py                        # Streamlit dashboard
├── requirements.txt
│
├── src/
│   ├── data/
│   │   └── fetch.py              # Download OHLCV via yfinance → data/raw/
│   ├── features/
│   │   └── build.py              # Leakage-safe feature engineering → data/processed/
│   ├── models/
│   │   ├── dataset.py            # VolDataset — sliding window over features
│   │   ├── vol_transformer.py    # Dual-head Transformer definition
│   │   └── inference.py          # load_bundle, infer_latest, infer_rolling
│   ├── simulation/
│   │   └── paths.py              # gbm_paths, ai_vol_paths, regime_paths, risk_metrics
│   ├── benchmarking.py           # GARCH(1,1), EWMA, Kupiec LR test
│   └── train.py                  # Walk-forward CV, final model, ablation study
│
├── scripts/
│   └── backtest.py               # Rolling 1-day VaR backtest over holdout period
│
├── notebooks/
│   └── 01_eda.ipynb              # Feature inspection, regime plots, lookahead sanity check
│
├── data/
│   ├── raw/                      # Yahoo Finance parquet files (git-ignored)
│   └── processed/                # Engineered features (git-ignored)
│
├── checkpoints/                  # Model weights + metrics JSON (git-ignored by default)
│   ├── SPY_best.pt
│   ├── SPY_metrics.json
│   └── ...
│
└── tests/
    ├── test_simulation.py
    ├── test_features.py
    ├── test_dataset.py
    ├── test_vol_transformer.py
    ├── test_benchmarking.py
    └── test_train_config.py

Setup

git clone https://github.com/YOUR_USERNAME/volatility-waves.git
cd volatility-waves
python -m venv venv
source venv/bin/activate        # Windows: venv\Scripts\activate
pip install -r requirements.txt

PyTorch backend

requirements.txt installs the default PyTorch build. For a specific backend:

# CUDA (Linux / Windows)
pip install torch --index-url https://download.pytorch.org/whl/cu121

# MPS is bundled in the standard macOS wheel — no extra step
pip install torch

# CPU only (e.g. Streamlit Cloud free tier)
pip install torch --index-url https://download.pytorch.org/whl/cpu

Training auto-detects the best device in order: CUDA → MPS → CPU. Override with --device cuda|mps|cpu.


Workflow

1 — Fetch data

python -m src.data.fetch

Downloads SPY, AAPL, NVDA, GLD, and ^VIX from Yahoo Finance (2010–2024) into data/raw/.

Optional — custom tickers or date range:

python -m src.data.fetch --tickers SPY AAPL VIX --start 2015-01-01 --end 2024-12-31

2 — Build features

python -m src.features.build

Computes all vol features per ticker with rolling quantile regime labels. All quantiles use only past data — no lookahead leakage.

3 — Run tests

pytest tests/ -v

The test suite covers feature leakage, dataset shapes, simulation properties (VaR coverage rate, CVaR ≥ VaR), and Kupiec test calibration.

4 — Train

python -m src.train --ticker SPY

Runs 5-fold walk-forward cross-validation, trains the final model on the selection set, evaluates on a 252-day holdout, and saves to checkpoints/SPY_best.pt.

Key flags:

Flag Default Description
--ticker SPY Ticker to train on
--epochs 100 Training epochs
--lookback 63 Input window (trading days)
--horizon 21 Forecast horizon (trading days)
--alpha 0.3 Regime classification loss weight
--device auto Force cuda, mps, or cpu
--run-ablation off 4-way ablation study
--n-splits 5 Walk-forward folds
--test-size 252 Holdout days
--seed 42 Global random seed

Ablation study:

python -m src.train --ticker SPY --run-ablation

Trains 4 variants (full / no regime head / no VIX / 1-layer encoder) and reports mean ± std vol MAE for each.

5 — Backtest

python scripts/backtest.py --ticker SPY

Rolls a 1-day VaR backtest over the 252-day holdout, comparing the AI vol model against GARCH(1,1) and EWMA via the Kupiec likelihood-ratio test.

Example output:

==============================================================
  VaR Backtest — SPY   (95% confidence)
==============================================================
Model          Breach  Expected   Kupiec LR   p-val   Result
--------------------------------------------------------------
AI vol         4.76%      5.00%       0.412  0.5211     PASS
GARCH          5.16%      5.00%       0.181  0.6706     PASS
EWMA           6.35%      5.00%       9.241  0.0024     FAIL
==============================================================

Optional flags: --conf 0.99, --test-size 504, --save.

6 — Dashboard

streamlit run app.py

7 — EDA notebook

jupyter notebook notebooks/01_eda.ipynb

Deploying to Streamlit Cloud

  1. Push the repo to GitHub.
  2. Go to share.streamlit.ioNew app → point to app.py.
  3. Confirm requirements.txt is detected in Advanced settings → Packages.
  4. The app falls back to GBM baseline automatically if no checkpoint is found — safe to deploy without weights.

For CPU-only deployment, replace the torch line in requirements.txt:

--index-url https://download.pytorch.org/whl/cpu
torch==2.5.1+cpu

Inference on the ~250k-parameter model runs in under 50ms on CPU.


License

MIT — see LICENSE.


Disclaimer

This project is for educational and research purposes only. It is not financial advice and should not be used to make investment decisions.

About

Dual-head Transformer for volatility forecasting & regime classification, injected into Monte Carlo price path simulation. Streamlit dashboard included.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors