Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🌊 Surfotility

No-Arbitrage Volatility Surface Calibration Engine

A high-performance, explainable volatility surface modeling library written in C++20,
with an interactive React/Vite dashboard for real-time calibration visualization.

Inspired by gnsqd/surface (Rust) — reimplemented from scratch in modern C++.


📋 Table of Contents


Overview

Surfotility is a modular, production-grade volatility surface calibration engine that takes raw option chain data and produces arbitrage-free implied volatility surfaces using the Stochastic Volatility Inspired (SVI) parameterization.

The engine features a two-stage global+local hybrid optimizer (CMA-ES → L-BFGS-B), Durrleman-condition arbitrage verification, full analytical Black-Scholes Greeks, and a diagnostic explainability layer — all exposed through both a C++ CLI and a React web dashboard.


🔄 Pipeline Architecture

Option Chain (CSV/JSON)
       ↓
Implied Volatility (Newton-Raphson BS Inversion)
       ↓
Clean / Filter Data (Strike bounds, Vega weighting)
       ↓
SVI Calibration (per-expiry, CMA-ES → L-BFGS-B)
       ↓
Arbitrage Checks (Variance, Butterfly, Calendar)
       ↓
Surface Construction (Multi-slice interpolation)
       ↓
Greeks (Δ, Γ, V, Θ, ρ, Vanna, Volga)
       ↓
Explainability Report (Markdown + JSON)
       ↓
React Dashboard (Real-time visualization)

✨ Features

C++ Core Engine

Feature Description
SVI Parameterization Raw SVI model: w(k) = a + b(ρ(k−m) + √((k−m)² + σ²)) with 5 free parameters
Two-Stage Optimizer CMA-ES global search (population-based) → Projected L-BFGS-B local refinement with Armijo line search
Optimization Presets Minimal, Fast, Production, Research — tuneable iterations, population size, tolerances
Black-Scholes Pricer Analytical European option pricing with put-call parity verification
Full Greeks Suite Delta, Gamma, Vega, Theta, Rho, Vanna, Volga — all closed-form
IV Solver Newton-Raphson implied volatility inversion from market prices
Arbitrage Detection Variance positivity, Durrleman butterfly density g(k) ≥ 0, calendar spread dw/dT ≥ 0
Multi-Expiry Surface Per-expiry SVI calibration with linear interpolation across the time dimension
3D Surface Grid Dense mesh generation for rendering: (strike × expiry) → implied vol
Explainability Engine Physical interpretation of each SVI parameter + quantitative diagnostics (RMSE, MAE, R²)
JSON Export Structured output for web dashboard consumption
CSV Loader Parse option chain data from CSV files

React Dashboard

Feature Description
Smile Chart 2D volatility smile: market IV scatter vs. calibrated SVI curve
Arbitrage Density Durrleman risk-neutral density g(k) with arbitrage pass/fail indicator
Parameter Sandbox Interactive sliders for all 5 SVI parameters with real-time re-rendering
Preset Switching SPX Index and BTC Crypto presets with realistic market data
Client-Side Calibration Grid-search SVI calibration running entirely in the browser

📁 Project Structure

Surfotility/
├── CMakeLists.txt                      # Build configuration (C++20, -O3)
├── README.md
│
├── include/surface/                    # Public header API
│   ├── surface.hpp                     # Aggregate include header
│   ├── types.hpp                       # Core types: SVIParams, MarketDataRow, OptionGreeks, etc.
│   ├── black_scholes.hpp               # BS pricing, Greeks, IV solver
│   ├── svi_model.hpp                   # SVI formula, derivatives, RND, arbitrage validation
│   ├── optimizer.hpp                   # CMA-ES, L-BFGS-B, hybrid optimizer
│   ├── calibration.hpp                 # Single-expiry SVI calibration engine
│   ├── calibration_multi.hpp           # Multi-expiry per-slice calibration
│   ├── volatility_surface.hpp          # 3D surface construction & interpolation
│   ├── explainability.hpp              # Diagnostic reports & parameter explanations
│   └── option_chain.hpp                # CSV option chain loader
│
├── src/                                # Implementation files
│   ├── main.cpp                        # CLI entry point — full pipeline demo
│   ├── black_scholes.cpp               # BS pricing implementation
│   ├── svi_model.cpp                   # SVI math: w(k), w'(k), w''(k), g(k)
│   ├── optimizer.cpp                   # CMA-ES + L-BFGS-B optimizer (268 lines)
│   ├── calibration.cpp                 # Weighted least-squares SVI fitting
│   ├── calibration_multi.cpp           # Per-expiry calibration loop
│   ├── volatility_surface.cpp          # Surface interpolation & calendar arb checks
│   ├── explainability.cpp              # Markdown & JSON report generation
│   ├── option_chain.cpp                # CSV parser
│   └── export_multi_json.cpp           # Multi-expiry JSON exporter
│
├── tests/
│   └── test_surface.cpp                # Unit tests: BS parity, IV recovery, SVI calibration
│
└── web/                                # React/Vite interactive dashboard
    ├── package.json
    ├── vite.config.js
    ├── tailwind.config.js
    ├── index.html
    └── src/
        ├── components/
        │   ├── Header.jsx              # Dashboard header with preset switcher
        │   ├── SmileChart.jsx           # 2D volatility smile chart (Chart.js)
        │   ├── ArbitrageDensityChart.jsx# Durrleman RND density chart
        │   └── ParameterSandbox.jsx    # Interactive SVI parameter sliders
        └── utils/
            ├── svi_engine.js           # Browser-side SVI math (mirrors C++ core)
            └── sample_data.js          # SPX & BTC preset market data

🚀 Getting Started

Prerequisites

Tool Version Purpose
C++ Compiler C++20 (GCC 11+, Clang 14+, MSVC 19.30+) Core engine
CMake ≥ 3.20 Build system
Node.js ≥ 18 React dashboard
npm ≥ 9 Package management

Build the C++ Engine

# Clone the repository
git clone https://github.com/your-username/Surfotility.git
cd Surfotility

# Build with CMake
mkdir -p build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)

# Run the CLI
./surface_cli

Run Tests

cd build
./surface_tests

Expected output:

=========================================================
  🧪 Surface-Lib C++ Test Suite
=========================================================

[RUNNING TEST] Black-Scholes Put-Call Parity...
  [PASSED] Put-Call Parity holds
[RUNNING TEST] Implied Volatility Recovery...
  [PASSED] Implied Volatility recovered: 0.2 vs target 0.2
[RUNNING TEST] SVI Formula & Risk-Neutral Density...
  [PASSED] SVI params valid, RND density g(0)=0.847 > 0
[RUNNING TEST] SVI Calibration on Synthetic Smile...
  [PASSED] Calibration Converged with RMSE: 0.000124

✅ ALL UNIT TESTS PASSED SUCCESSFULLY!

Launch the Dashboard

cd web
npm install
npm run dev

Open http://localhost:5173 in your browser.


💻 Usage

Programmatic API (C++)

#include "surface/surface.hpp"
using namespace surface;

int main() {
    // 1. Prepare market data
    std::vector<MarketDataRow> data = {
        {"put",  90.0, 100.0, 0.25, 0.228, 0.92, 0},
        {"call", 100.0, 100.0, 0.25, 0.195, 1.15, 0},
        {"call", 110.0, 100.0, 0.25, 0.176, 0.62, 0},
    };

    // 2. Calibrate SVI (one slice)
    auto [rmse, params, bounds] = calibrate_svi(
        data,
        default_configs::fast()  // or production(), research()
    );

    // 3. Price with calibrated model
    FixedParameters env{0.02, 0.00};
    auto results = price_with_svi(params, data, env);

    // 4. Check arbitrage
    auto diag = SVIModel::validate_arbitrage(params);
    // diag.is_butterfly_arbitrage_free == true  ✅

    // 5. Build multi-expiry surface
    VolatilitySurface surf;
    surf.add_slice(0.25, params);
    double iv = surf.get_implied_volatility(105.0, 0.30, 100.0);

    return 0;
}

CSV Data Format

The CSV loader expects a header row followed by data rows:

option_type,strike,underlying,years_to_exp,market_iv,vega,expiration
put,90.0,100.0,0.25,0.228,0.92,1640995200
call,100.0,100.0,0.25,0.195,1.15,1640995200
call,110.0,100.0,0.25,0.176,0.62,1640995200

Open-source data: You can use SPX option chain data from CBOE DataShop (free samples) or Kaggle Options Datasets — reformat to the CSV schema above.

Optimization Presets

Preset Iterations Population Objective Tol Use Case
Minimal 100 20 1e-4 Quick prototyping
Fast 300 30 1e-6 Interactive / real-time
Production 600 50 1e-7 Trading systems
Research 1500 100 1e-9 Academic / publication

🖥️ Interactive Dashboard

The React dashboard provides real-time visualization of the calibrated volatility surface:

Panel Description
Header Preset selector (SPX / BTC), calibration trigger button
Smile Chart Market IV points (scatter) overlaid with smooth SVI curve w(k)
Arbitrage Density Durrleman RND density g(k) — green if arbitrage-free, red if violated
Parameter Sandbox Drag sliders for a, b, ρ, m, σ and watch the smile update live

The dashboard runs a browser-side SVI engine (svi_engine.js) that mirrors the C++ mathematical core, enabling instant parameter exploration without recompilation.


📐 Mathematical Background

SVI Total Variance

The raw SVI parameterization defines total implied variance as a function of log-moneyness k = log(K/F):

$$w(k) = a + b\left(\rho(k - m) + \sqrt{(k - m)^2 + \sigma^2}\right)$$

Parameter Symbol Range Interpretation
Base variance a a ≥ 0 Vertical shift — overall IV level
Slope b b ≥ 0 Wing steepness — tail volatility
Skew ρ −1 < ρ < 1 Asymmetry — equity put skew when ρ < 0
Shift m ℝ Horizontal displacement of the smile vertex
Curvature σ σ > 0 Vertex smoothness — small σ = sharp V, large σ = smooth U

Implied Volatility

$$\sigma_{\text{impl}}(k) = \sqrt{\frac{w(k)}{T}}$$

Durrleman Risk-Neutral Density

The Durrleman condition ensures absence of butterfly arbitrage:

$$g(k) = \left(1 - \frac{k , w'(k)}{2 , w(k)}\right)^2 - \frac{w'(k)^2}{4}\left(\frac{1}{w(k)} + \frac{1}{4}\right) + \frac{w''(k)}{2} \geq 0$$

If g(k) < 0 at any strike, the surface admits static butterfly arbitrage.

Calendar Arbitrage

For a surface to be free of calendar arbitrage, total variance must be non-decreasing in time:

$$\frac{\partial w(k, T)}{\partial T} \geq 0 \quad \forall , k$$


⚡ Optimization Engine

Stage 1: CMA-ES (Covariance Matrix Adaptation Evolution Strategy)

  • Population-based global optimizer over the 5D SVI parameter space
  • Diagonal covariance approximation for stability and speed
  • Configurable population size, step-size adaptation, and convergence tolerance
  • Bounded search with projection into feasible parameter region

Stage 2: L-BFGS-B (Projected Gradient Descent)

  • Local refinement seeded from the CMA-ES solution
  • Central-difference numerical gradients
  • Armijo backtracking line search with projected bounds
  • Typically converges in 20–50 iterations for well-conditioned problems

Hybrid Pipeline

CMA-ES (global exploration) → L-BFGS-B (local polish) → Best of both

The hybrid approach avoids local minima while achieving high numerical precision.


🛡️ Arbitrage Diagnostics

The engine performs three levels of arbitrage validation:

Check Condition Method
Variance Positivity w(k) > 0 ∀ k Grid scan over [-2, 2] with 200 points
Butterfly Arbitrage g(k) ≥ 0 ∀ k Durrleman density formula, 200-point grid
Calendar Arbitrage dw/dT ≥ 0 ∀ k, T Pairwise comparison of adjacent expiry slices

All diagnostics are reported in the ArbitrageDiagnostics struct and rendered in both the CLI markdown report and the React dashboard.


🗺️ Roadmap

  • SVI raw parameterization & calibration
  • CMA-ES + L-BFGS-B hybrid optimizer
  • Black-Scholes analytical Greeks (7 Greeks)
  • Multi-expiry surface construction
  • Durrleman butterfly & calendar arbitrage checks
  • Explainability engine (Markdown + JSON reports)
  • React dashboard with parameter sandbox
  • Per-expiry SVI calibration
  • SABR model calibration & comparison
  • Local volatility (Dupire) extraction
  • Delta hedging simulation
  • Monte Carlo hedging P&L attribution
  • Real market data ingestion (CBOE, Deribit API)
  • Raw vs SVI vs SABR vs Local Vol comparison charts

📚 References

  1. Gatheral, J. (2004). A parsimonious arbitrage-free implied volatility parameterization with application to the valuation of volatility derivatives. Presentation at Global Derivatives & Risk Management, Madrid.

  2. Gatheral, J. & Jacquier, A. (2014). Arbitrage-free SVI volatility surfaces. Quantitative Finance, 14(1), 59-71.

  3. Durrleman, V. (2003). From implied to spot volatilities. PhD thesis, Princeton University.

  4. Hansen, N. & Ostermeier, A. (2001). Completely derandomized self-adaptation in evolution strategies. Evolutionary Computation, 9(2), 159-195.

  5. gnsqd/surface — Original Rust implementation: github.com/gnsqd/surface


License

This project is licensed under the MIT License. See LICENSE for details.


Built with ❤️ for quantitative finance research

About

Volatility surface modelling and calibration

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages