An adaptive options market-making & volatility-surface engine for NSE Nifty50 — a SIMD-vectorized C++17 pricing core, a multi-strike Avellaneda–Stoikov quoter, microstructure-aware toxicity/jump signals, a no-look-ahead tick backtester, and an interactive dashboard.
Price the whole chain. Quote the whole surface. Hedge the risk that's left. VolForge takes an options desk end-to-end: a microsecond C++ pricing core (Black–Scholes, Heston, arbitrage-free SVI) feeds a Greeks-constrained multi-strike market maker, whose quotes are stress-tested on a bitemporal, no-look-ahead backtester over three years of real NSE data — and then the one thing that stays modeled (the fills against our own quotes) is validated on real option microstructure with no broker account.
The centerpiece: a real NSE NIFTY implied-vol surface calibrated arbitrage-free across 158 trading days — vol crush, the June-2024 election spike, and the April-2025 tariff shock all show up as skew and term-structure moves.
Most "options pricing" projects stop at a Black–Scholes function and a smile plot. Market making is a harder question:
Given a whole chain of correlated strikes, a limited risk budget, and adversaries who trade against you when they know something — where do you place your bid and ask, and how much do you hedge?
VolForge answers that question as a connected system, and then holds itself to the standard that matters for a trading study: could this survive contact with real data? Every layer is either real, or calibrated to real and validated, and the modeling boundary is written down.
Keywords: options market making, Avellaneda–Stoikov, volatility surface, SVI, arbitrage-free calibration, Greeks hedging, VPIN, order-flow toxicity, bipower variation, jump detection, Lee–Mykland, high-frequency econometrics, P&L attribution, SIMD, C++, pybind11, Next.js, quantitative finance.
| Sub-problem | Why it's non-trivial | What VolForge does |
|---|---|---|
| Speed | A desk reprices hundreds of strikes many times a second; a Python loop can't keep up | SIMD-vectorized C++17 core (AVX2/NEON) — a 500-strike chain in ~8 µs |
| Correlated inventory | Strikes aren't independent; a delta in one is a delta in all | Inventory is a portfolio-Greeks vector coupled by a factor-risk matrix Q = BΣ_FBᵀ |
| Risk limits | You must cap |Δ|,|Γ|,|V| without killing the spread |
Closed-form KKT barrier on the quote (no inner QP) |
| Adverse selection | Informed flow picks you off; jumps gap through your quotes | VPIN toxicity surface + BN–S bipower jump detector widen quotes in bad regimes |
| Honest evaluation | Look-ahead and invented fills make any backtest look good | No-look-ahead bitemporal replay + calibrated, real-data-validated fills |
| Credibility | "Your wiggle / your fills are made up" | Real intraday path, real EOD surfaces, real option bars, and a live exchange cross-check |
| Start here | What you'll find |
|---|---|
Run the dashboard → dashboard/ |
Animated 3D surface, live Greeks book, spread-decision replay |
Mathematical Core + core/quoting.cpp, python/volforge/micro/ |
Multi-strike A-S, VPIN, bipower jumps |
core/ + benchmarks/ |
SIMD tri-path pricer, QuantLib oracle, latency benchmarks |
Grounded in real data + python/volforge/backtest/ |
Bitemporal store, calibrated DGP, P&L attribution |
Phase D + python/volforge/backtest/shadow.py, live/ |
Real option-bar shadow fills + a live no-account NSE check |
| Metric | Result | Meaning |
|---|---|---|
| Chain pricing | ~8 µs / 500 strikes (~60 M opts/s) | ~64× a vectorized SciPy loop; matched to QuantLib < 1e-5 |
| Quote latency | 3.2 µs core / 29.8 µs full loop | whole-chain A-S + VPIN + jump, O(n) in strikes |
| SVI surface | 158 days, 100% arbitrage-free | butterfly + calendar, real NSE 2023–2025 |
| Vol forecast | LSTM R² −0.06 vs GARCH −0.61 | OOS 5-day realized vol, strict expanding window |
| Delta-hedging | Sharpe 1.85 → 5.77 | on the real 5-min NIFTY path; peak |net Δ| 55 → 0.5 |
| Microstructure lift | +₹1.3k/day, t = 3.9 | positive out-of-sample every year (t up to 7.3) |
| Real-fill validation | 110k+ shadow fills, 6 expiries | net-edge lift positive every month on real option bars |
| Live pricing check | IV matched to 0.55 vol-pt | vs NSE's own published IV, live, no account |
| P&L attribution | residual < 1e-6 | exact reconciliation; future-shuffle byte-identical |
| Test suite | 984 pytest | C++ oracle → SVI → micro → backtest → live |
An interactive Next.js + Plotly front-end — a static app fed by exported JSON, so it deploys to Vercel with no backend.
| Screen | What it shows |
|---|---|
| Overview & Performance | Equity curve, hedged-vs-naked P&L, robustness sweep, latency, provenance, and the Phase-D real-fill / live-validation panels |
| 3D Vol Surface | The 158-day NIFTY IV surface with a play/scrub timeline, term structure, and smile snapshots |
| Greeks Book | Real-time gross-vs-net (hedged) delta, vega, and a P&L attribution waterfall |
| Spread Replay | Bar-by-bar bid/ask band, inventory, spot, and the net-Δ badge — watch each quoting decision |
cd dashboard && npm install && npm run dev # http://localhost:3000flowchart LR
subgraph Data["Real NSE data (free)"]
A["Bhav copy EOD<br/>(F&O chain)"]
B["5-min NIFTY path<br/>(EOD-validated vs ^NSEI)"]
C["1-min option bars<br/>(Hugging Face)"]
D["Live option-chain JSON<br/>(no account)"]
end
subgraph Core["C++17 SIMD core"]
E["Black-Scholes + Greeks"]
F["Heston (Carr-Madan FFT)"]
G["Multi-strike A-S quoting<br/>Q = BΣ_FBᵀ, O(n)"]
end
subgraph Signals["Microstructure"]
H["VPIN toxicity surface"]
I["BN-S bipower jumps"]
end
subgraph Eval["Evaluation"]
J["No-look-ahead<br/>bitemporal backtester"]
K["Exact P&L attribution"]
L["Phase-D real-fill<br/>shadow validation"]
end
A --> M["Arbitrage-free SVI surface"]
M --> G
E --> G
F --> M
B --> J
H --> G
I --> G
G --> J
J --> K
C --> L
D --> L
K --> N["Next.js + Plotly dashboard"]
L --> N
Classic Avellaneda–Stoikov quotes a single asset around a reservation price. VolForge generalizes it to a whole options chain whose strikes share risk. Let q be the vector of positions and B the strike→factor loading (delta/gamma/vega exposures). Inventory risk is the portfolio-Greeks vector G = Bᵀq, and strikes are coupled through the low-rank factor-risk matrix
Each strike i is quoted around a risk-adjusted reservation price with a risk-scaled half-spread:
Because Q = BΣ_FBᵀ is low-rank, a whole-chain quote never forms the n×n matrix — a factor-space contraction makes it O(n) in strikes (hot-loop-fast, zero-copy, GIL-released). At N = 1 it reduces exactly to scalar Avellaneda–Stoikov (to 1e-12). Delta/gamma/vega budgets |Δ|,|Γ|,|V| are imposed by a closed-form quadratic-barrier KKT multiplier — no inner quadratic program.
Per expiry, VolForge fits the raw SVI total-variance smile
then enforces no static arbitrage on the traded moneyness band: Durrleman's butterfly condition g(k) ≥ 0 (with a guaranteed-feasible b-shrink fallback) and calendar monotonicity via monotone rearrangement. A hard lesson baked into the code: enforcing no-arb far out on the extrapolated wings collapses short-dated smiles and fabricates calendar violations — so it's enforced where options actually trade. Result: 100% arbitrage-free across 158 real NSE days.
Order-flow toxicity is estimated per strike: adaptive volume buckets V_k = ADV_k / B, bulk-volume classification (own-price + delta-aware, reusing the C++ SIMD norm_cdf), and Nadaraya–Watson smoothing across moneyness. An elevated VPIN_k widens that strike's quote; a single strike reduces to canonical VPIN.
A Barndorff-Nielsen–Shephard realized-vs-bipower variation Z-test (RV/BV/TQ, overnight excluded) flags jump days on 5-min bars, and Lee–Mykland localizes the exact bar online. A detected jump widens all spreads by an exponentially-decaying premium. Measured size 0.85% @ α = 0.1%, power 99% at a ~13σ bar.
VolForge is checked at the numerical level, the statistical level, and the trading level.
| Check | What it verifies |
|---|---|
| QuantLib oracle | Black–Scholes prices + Greeks and Heston FFT match QuantLib to < 1e-5 |
| Scalar-limit test | Multi-strike A-S at N=1 equals scalar Avellaneda–Stoikov to 1e-12 |
| SVI round-trips | Raw-SVI parameter recovery to ~1e-9; price→IV round-trip to 6e-7 |
| No-arbitrage | Butterfly g(k) ≥ 0 + calendar monotonicity on all 158 days |
| Future-shuffle | Corrupting every row dated ≥ a cutoff leaves the prior replay byte-identical (zero look-ahead, demonstrated) |
| P&L reconciliation | spread + theta + jump + diffusion + hedge − fees − hedge_cost matches realized equity, residual < 1e-6 |
| DGP calibration | Simulated vs real high-frequency stylized facts agree (KS p = 0.25, kurtosis 1.28 vs 1.42, jump-rate 10% vs 11%) |
| Real EOD cross-check | Option-bar closes vs our own Bhav copy at log-corr 0.999–1.000 |
| Live exchange check | Our C++ implied vol reproduces NSE's published IV to 0.55 vol-pt |
A market-making backtest is only as honest as its inputs. VolForge is built on free, no-fee, mostly no-account data, and it states exactly what is real vs modeled.
| Layer | Source (free) | Status |
|---|---|---|
| Intraday underlying path | Real 5-min NIFTY (Kaggle dump; EOD-validated vs ^NSEI, corr 1.00000, median |Δ| 0.05%) |
Real |
| EOD option chain → surfaces | NSE Bhav copy → 158 arbitrage-free SVI surfaces | Real |
| Intraday per-option marks | Hugging Face thetrademarkk/india-index-options-1m (1-min OHLCV) |
Real |
| Live L1 bid/ask (forward) | Public NSE option-chain JSON (option-chain-v3, cookies only) |
Real (forward) |
| Order flow / fills vs our quotes | Counterfactual — our quotes never existed | Modeled → calibrated & validated |
| Still modeled | Why it can't be "downloaded" | Mitigation |
|---|---|---|
| Fills vs. our own quotes | Our quotes never existed in the tape | A-S intensity calibrated to Bhav-copy volume (A = 12.9) + a sign-stable (A, κ) sensitivity grid + Phase-D bar-level shadow fills on real option 1-min bars + a tier-1 volume reality check |
| Intraday L1 depth / queue | Free feeds give OHLCV bars, not order-book depth | OHLC-range shadow fills approximate a touch; the live NSE chain captures forward L1 snapshots |
- Phase A — real path. Each backtest day is replayed on the realized 5-min NIFTY path. The full-stack microstructure lift survives on real data (smaller than on the engineered bridge, as expected).
- Phase B — calibrated DGP. Where a synthetic path is still needed (warm-up, gaps, Monte-Carlo flow), it's an AR(1)-SV bridge calibrated to real bars and validated with KS / moment tests (p = 0.25).
- Phase C — data-grounded fills. The A-S arrival scale
Ais anchored to real near-ATM Bhav-copy volume; the lift stays positive across a(A, κ, informed_gain, toxicity, hedge_band)sweep — it's a property of the quoting logic, not a tuned point. - Phase D — real-fill validation (the standout). Replaying our exact quoting and letting the real option bar decide each fill (a trade hits our quote when the bar
[low, high]brackets it): across 110k+ shadow fills / 45 days / 6 monthly expiries, the microstructure book beats naïve A-S on net edge every month (full +₹0.806 vs naïve +₹0.780 /contract) and dodges toxic jump fills. It also surfaces a genuine limitation — the carry-forward monthly surface can't reprice the expiry-week vol spike (mark error ~18% → 35% into expiry) — which is exactly why shadow fills anchor to the real contemporaneous mid ± our own spread. - Phase D tier-3-lite — run live. A no-account poller of the public NSE option-chain JSON (15 one-minute snapshots of the NIFTY weekly): our C++ pricer reproduced NSE's own published IV to 0.55 vol-pt, the real ATM half-spread was ~15 bps, a naked 1-min quote faced ~20× its spread in directional risk, and delta-hedging removed ~43% of the 1-min ATM P&L variance. Baked into a static report (no frontend polling).
Caveats: shadow quotes don't sit in the real queue (no queue-priority truth); OHLC-range fills assume a touch = a fill; tier-3-lite is forward-only, minute-cadence, single-L1, and ToS-bound.
VolForge/
├── core/ # C++17 pricing core
│ ├── pricer.{h,cpp} # Black-Scholes (+IV), Heston (Carr-Madan FFT), SVI eval
│ ├── greeks.{h,cpp} # 7 Greeks incl. Vanna/Volga; fused SoA SIMD batch
│ ├── quoting.{h,cpp} # multi-strike Avellaneda-Stoikov (Q=BΣ_FBᵀ, O(n) hot path)
│ ├── fft.{h,cpp} # dependency-free radix-2 FFT (Carr-Madan chain)
│ └── simd/ # AVX2/NEON/scalar exp + West-2009 normal CDF
├── bindings/ # pybind11 module -> volforge._core
├── python/volforge/
│ ├── data/ # Bhav copy, bitemporal store, calendar, real 5-min path,
│ │ # option_intraday (Phase-D 1-min option bars)
│ ├── vol/ # SVI (calibration + no-arb), GARCH, LSTM, 158-day history, viz
│ ├── micro/ # vpin (toxicity surface), jumps (BN-S + Lee-Mykland)
│ ├── mm/ # quoting wrapper, engine (the closed loop)
│ ├── live/ # Phase-D tier-3-lite: no-account NSE option-chain snapshots
│ └── backtest/ # fills, book, pnl, surface, simulator, strategies,
│ # realpath (real path), calibrate (DGP), shadow (real fills)
├── dashboard/ # Next.js + Plotly (3D surface · Greeks book · spread replay)
├── scripts/ # reproducible Phase 1-4 + Phase A-D pipelines
├── benchmarks/ # C++ + Python latency / accuracy benchmarks
├── tests/ # 984 pytest (QuantLib oracle → SVI → micro → backtest → live)
├── docs/figures/ # generated surface / backtest / validation figures
├── requirements.txt # arm64 / M-series deps
└── CMakeLists.txt # feature-probed -O3/-march/-mavx2/-mfma, pybind11
Prereqs: a C++17 compiler + CMake, Python 3.13 (Homebrew CPython on macOS for full arm64 wheels), and Node 18+ for the dashboard.
git clone https://github.com/PratyushGupta7/VolForge.git
cd VolForge
# Python + native core
/opt/homebrew/bin/python3.13 -m venv .venv # or any CPython 3.11+
source .venv/bin/activate
pip install -r requirements.txt
# Build + import + execute the C++ core (GATE 0)
python tests/smoke_test.pyThen run any of the reproducible pipelines:
python scripts/phase2_deliverables.py # 3D surface + GARCH figures
python scripts/build_surface_history.py --mode weekly # 158-day cube + ANIMATED 3D surface
python scripts/lstm_vs_garch.py # LSTM vs GARCH OOS (5d RV)
python scripts/phase3_demo.py # closed-loop quoting on real NIFTY
python scripts/phase4_backtest.py # no-look-ahead backtest + P&L lift + dashboard export
python scripts/shadow_validate.py # Phase D t1/t2: real-fill validation on 1-min option bars
# Phase D t3-lite (market hours only): live NSE chain -> static report
python scripts/capture_nse_chain.py --duration-min 15 && python scripts/live_validate.pyDashboard:
cd dashboard && npm install && npm run dev # http://localhost:3000python tests/smoke_test.py # configure + build + import + execute -> GATE 0
pytest # full suite (984 passing)
python benchmarks/benchmark.py # C++ SIMD vs NumPy/scipy
python benchmarks/bench_svi.py # full-surface SVI calibration latency
./build/bench_pricer 500 5000 # standalone C++ latency (SIMD vs scalar)Dashboard checks:
cd dashboard && npm run build # type-check + lint + static exportThe dev machine is arm64 (Apple Silicon, NEON); the AVX2 benchmark target is x86-64. Every SIMD kernel ships three implementations behind one signature, selected at compile time — CMake only adds -mavx2/-mfma where the compiler accepts them, so the same source is fast on both. Published speedups are reported against the host CPU string. The compiled core is built into the package as python/volforge/_core*.so; import volforge re-exports it alongside volforge.data / volforge.vol.
- 500-strike chain (price + 7 Greeks) in ~8 µs — ~120× inside a < 1 ms budget; ~60 M options/s.
- Vectorized normal CDF (West 2009): 4× vs scipy, max error 2.2e-16.
- Heston whole-chain FFT (4096-pt): ~0.47 ms, matches QuantLib to < 1e-5.
- Closed-loop quote latency: 3.2 µs (C++ A-S core) / 29.8 µs (full VPIN + jump loop).
- Make the math visible. From the KKT barrier to the SVI no-arb band, the derivations live in the code, not just in charts.
- Document the modeling boundary. It's a table in the README, and the limitation Phase D surfaced (expiry-week mark error) is written down next to the results it affects.
- Never look ahead. Bitemporal surfaces + a byte-identical future-shuffle test make the no-look-ahead claim testable, not asserted.
- Calibrate, then validate. Whatever can't be downloaded is calibrated to real data and checked with statistical tests.
- Relative lift is the robust result. Under shared, calibrated flow, the lift of microstructure-aware quoting over naïve A-S is what generalizes — and it does, out-of-sample, every year.
- Deploy the static dashboard to a custom domain.
- Second underlying (BANKNIFTY) via the same free pipeline → external validity.
- Block-bootstrap confidence intervals for the lift over real paths.
- Regime split (2023 calm / 2024 election / 2025 tariff) on the real intraday path.
- Optional live L1/tick feed (broker websocket) for true queue-aware fills.
Is this financial advice or a live trading system? No. It's a research and engineering project — a backtest and a live measurement tool, not an order router.
Why not just buy a paid data feed? A paid feed would make historical option marks real, but it would not fix the counterfactual fills (our quotes never existed). Grounding + honest calibration is a better use of ₹0 than a feed that doesn't close the actual gap.
Why is the reported real-path lift smaller than on the simulated path? Because the simulated path injected its own jumps and clustering. On the real path the lift is smaller but honest — and it's still positive and significant out-of-sample in every year.
Can I reproduce the numbers? Yes — every figure and JSON is produced by a script in scripts/, from cached parquet. The C++ core is validated against QuantLib in the test suite.
This repository is for research and educational use only. It is not financial advice, an offer to buy or sell securities, or a recommendation to deploy capital. Market data can be delayed, incomplete, or unavailable; backtests are historical simulations; and live captures depend on external, rate-limited, ToS-bound public endpoints.
If you reference this project, please cite:
Gupta, P. (2026). VolForge: An Adaptive Options Market-Making & Volatility-Surface Engine. GitHub. https://github.com/PratyushGupta7/VolForge
A companion research abstract, "Microstructure-Aware Options Market Making: A Greeks-Constrained Multi-Strike Avellaneda–Stoikov Engine," was submitted to CFE-CMStatistics 2026.
MIT License — see LICENSE.
Built by Pratyush Gupta.
If VolForge made you think differently about how a desk prices, quotes, and hedges an options chain, star the repository and open the dashboard.



