- core/vol_forecast.py: forecasts average variance over the next 1D/1W/1M
with HAR-RV (weekend dummy for 24/7 crypto), GJR-GARCH(1,1) QMLE with a
vectorised filter, HistGradientBoosting on HAR/return/calendar features,
and EWMA as benchmark. Garman-Klass + overnight-gap proxy scaled to
close-to-close on pre-backtest data only.
- Rolling out-of-sample backtest (refit every 21 days, no look-ahead),
QLIKE / RMSE / bias per model (Patton 2011), inverse-QLIKE ensemble.
- 2-state Gaussian HMM (Baum-Welch) regime probabilities and durations.
- For BTC/ETH: ensemble forecast vs Deribit ATM implied -> rich/cheap view.
- GET /api/vol/forecast/{pair} (cached 30 min; 503 when history is short
or sources are down); scikit-learn added (models degrade gracefully
without it).
- Vol Forecast tab: KPIs, forecast term structure vs implied, HMM regime
history, OOS backtest vs realised (+DVOL), model leaderboard per horizon.
- 7 new tests on simulations with known answers (proxy bias, GARCH and HMM
parameter recovery, weekend effect, look-ahead check, endpoint).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FpiqUMAyo4RL5DdQHMWbwE
Phone mail apps can glue the quoted header onto the reply
("ApproveOn 29 Sep 2026, at 10:48 AM, ... wrote:"), so the first word was
read as "approveon" and the approval on #3 was ignored. Parse in Python:
strip the quoted email ("On <date> ... wrote:" and '>' lines), then match
approve/lgtm/reject by prefix. Reasons keep their full text, and the
GITHUB_OUTPUT delimiter is random.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FpiqUMAyo4RL5DdQHMWbwE
Volatile instruments
- Add XAGUSD (SI=F, silver lease rate as r_f), BTCUSD and ETHUSD end to end:
pair metadata, live rates/OHLC/signals, CFTC positioning mappings
- Asset-class calendars: crypto annualised on 365 days, FX/metals on 252,
threaded through the signal engine
- Pair switch loads a typical ATM vol, rescales legs by moneyness, and
strategy templates use a ~1%-of-spot strike step
Vol Lab tab
- /api/vol/crypto/{BTC,ETH}: Deribit book summaries -> raw SVI fit per
expiry with Durrleman butterfly-arbitrage check, ATM / 25d RR / 25d BF
(Black-76 forward delta), DVOL, 30d constant-maturity IV, realised vol
and vol risk premium; cached 60s, 503 when Deribit is unreachable
- /api/vol/cone/{pair}: Burghardt-Lane realised-vol cone on the asset's
calendar
- UI: KPIs, cone with implied term-structure overlay, per-expiry smile
(market vs SVI), term-structure table with 'Use' to load T/sigma/RR/BF
into pricing and the Vol Smile tab
Fixes in the signal engine
- OU half-life divided by 252 twice; stationary sd used sqrt(252k) not sqrt(2k)
- Fallback realised vol returned decimals under *_pct keys
Tests: backend/tests (pytest) validate SVI recovery, exact 25d strikes,
cone calibration on both calendars and the endpoints with mocked feeds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FpiqUMAyo4RL5DdQHMWbwE
Builds the implied-vol smile from the three standard FX market quotes
(ATM delta-neutral straddle, 25-delta risk reversal, 25-delta butterfly)
using Castagna & Mercurio's second-order Vanna-Volga approximation, and
reprices each portfolio leg off the smile vs the flat vol.
- backend: core/vanna_volga.py (delta->strike, DNS ATM, VV smile) and
POST /api/smile
- frontend: new "Vol Smile" dashboard tab with quote inputs, smile
chart, pillar table and smile-vs-flat leg repricing
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FpiqUMAyo4RL5DdQHMWbwE
Adds a workflow that pings the repo owner on each daily Claude PR and
acts on their reply: "approve" merges it, "reject: <reason>" closes it
with the reason recorded and a "rejected" label.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FpiqUMAyo4RL5DdQHMWbwE