Live demo · Volatility surfaces

Noisy quotes in.
An arbitrage-free surface out.

This live demo builds an implied volatility surface from an option chain using Chalk resolvers. It inverts Black-Scholes for every bid and ask, fits a raw SVI smile to each expiry, and keeps the whole surface free of butterfly and calendar arbitrage. It is for quant developers, derivatives desks and risk teams who need volatility models computed and served in real time. You will watch the constrained fit hold while an unconstrained fit breaks under noise and dropped quotes, then price American, FLEX and structured products off the surface and stress a 207-position book with Greeks.

Compare two fits to the same noisy option quotes

The lime fit enforces no-arbitrage constraints. The coral fit can follow the noise into invalid shapes.

Try this experiment · expected results

  1. 1Inspect the recorded fit

    Choose an expiry and compare the two curves with the bid–ask bars and the density plot.

    Expected: Coral regions below zero identify invalid implied density; check fit quality as well as constraint violations.

  2. 2Change one quote condition

    Change noise or missing quotes, then draw and fit a new chain. Compare the per-expiry checks.

    Expected: The constraints and unconstrained fit are tested on the same new synthetic quotes.

Recorded fit · chain #…
Expiry
Loading the recorded fit…
arbitrage-free SVIunconstrained SVItrue surface⊥ bid/ask vol · ● mid · ○ droppednegative density (butterfly arbitrage)
The chain
Quote noise
Quotes dropped at random
Quotes are
Checking the live backend…
The surface
Inspect consistency checks by expiry
No-arbitrage checks per expiry
ExpiryButterflyCalendarRMS err vs truth

Each cell is arbitrage-free fit / unconstrained fit. Butterfly: g(k) ≥ 0. Calendar: total variance never falls from the previous expiry. Both are checked on one grid spanning every expiry's strikes, and half that range again on each side. Error is the RMS gap from the true surface across the listed strikes, dropped ones included.

Every chain is synthetic: a fictional index at 100 with a 3% rate and a 1% dividend yield, quoted from a known SSVI surface (Gatheral and Jacquier) with spreads that widen in the wings and at the front, rounded to price ticks. Noise moves each mid vol by a random share of its spread. The true surface is drawn dashed so you can see how far each fit lands from it. No market data is used, and nothing here is investment advice. The recorded fits are the API's responses for chain #7, saved from the deployed demo.

Use this surface to price a product

Price what is not on the screen

A fitted surface is only useful if you can price off it. Pick a product and Chalk prices it off the arbitrage-free surface of the chain above, with Greeks: an American option with its early-exercise premium, a FLEX option with a strike set as a percentage of the index and an expiry between listed ones, or a structured note with a payout you draw yourself. FLEX options are a newer, harder-to-price product: nothing about them is listed, so every price leans on how the surface is interpolated.

Exercise at expiry only: Black-Scholes at the fitted vol for this strike and expiry.

Option
Expiry
Price per option, index at 100
Checking the live backend…

Priced off the arbitrage-free surface of the chain above (typical noise, 30% dropped, european quotes). Greeks are bump-and-reprice: spot ±1%, vol ±1 point, one day.

Use this surface to stress a portfolio

Stress the whole book

One Chalk query reprices every position in a fictional book under a spot and vol shock: listed European options, American options, FLEX options and structured notes, all off the same surface. It returns the P&L and delta, gamma, vega, theta, vanna and volga per position, before and after the shock. The grid answers which part of the book drives the drawdown; click a cell to see the positions in it.

Scenario
Loading…
The book–
GreekNowStressed
Delta $ per 1% move––
Gamma $ delta per 1% move––
Vega $ per vol point––
Theta $ per day––
Vanna $ delta per vol point––
Volga $ vega per vol point––
P&L by product
European$0
American$0
FLEX$0
Structured$0
Where it comes from
tenor \ K/S<90%90–97%97–103%103–110%≥110%expiry total
≤1m
1–3m
3–6m
6–12m
strike total

P&L, $, by expiry and strike as a share of spot (notes by their buffer or barrier level). Click a cell for its positions.

Largest positions by P&L
PositionQtyValue nowP&LDeltaGammaVegaThetaVannaVolga
No run loaded yet.

Greeks after the shock, in $. A fictional book on the synthetic index: 90 listed European options, 45 American, 60 FLEX at percent-of-spot strikes and off-cycle expiries, and 12 structured notes sold to clients. Spot moves are sticky-moneyness: the smile moves with the index; the vol shift is parallel.

Built on Chalk

The planning, batching, serving and deployment, so the model is the only thing you maintain.

  • Vectorized where it counts

    A DataFrame resolver gets the whole chain in one call, so 525 Black-Scholes inversions are a handful of NumPy operations, not 525 Python calls.

  • Relationships, not plumbing

    The fit reads its quotes through a has-many. Chalk plans the chain, the implied vols and the fit as one query and runs only what the requested outputs need.

  • Branches for research

    The whole model runs on a branch beside the mainline deployment: change the fit, apply in seconds, and query it from a notebook or an app.

  • Quotes in, surface out, online

    The same query serves a pricing service at request time or a backfill over every historical chain offline, from one definition.

Deploy your own

A volatility model as features

Two feature classes and four resolvers hold the whole model. The implied vol of a quote is a feature like any other, so the same definition serves a single option at request time, a whole chain in one call, or every historical chain in an offline backfill.

Swap the synthetic chain for a SQL or streaming resolver over your own quotes, change the smile to SSVI or SABR, or add features on top: skew, term structure, risk reversals, the fitted vol at each position's strike.

Read the docs
# The features and resolvers, as a branch next to the environment's mainline deployment
cd chalk_project && chalk apply --branch volatility-surface

# The page's API: a FastAPI app that runs one Chalk query per fit
./deploy.py      # chalkcompute ScalingGroup, 1 CPU, tagged demo=volatility-surface

# Count arbitrage across 180 chains locally, with the resolvers' own code
./bench.py
Implementation details

How it works

One online query for a VolSurface runs three resolvers: one lists the chain, one turns prices into implied vols, and one fits the smiles through the surface's has-many of quotes. Between expiries the surface is linear in total variance at fixed moneyness, which keeps it free of calendar arbitrage whenever the fitted slices are.

  • Quotes in

    A chain of out-of-the-money puts and calls across seven expiries, 7 days to a year, each with a bid and an ask in price ticks. Here it is drawn from a known surface plus noise.

  • Invert Black-Scholes

    A DataFrame resolver solves every bid, ask and mid at once: Newton steps on the vol, kept inside a bisection bracket so every price within the no-arbitrage bounds converges.

  • Fit a smile per expiry

    Raw SVI has five parameters. For a fixed centre and curvature, the other three are a small linear least-squares problem, so the search is only two-dimensional.

  • Keep it arbitrage-free

    The constrained fit keeps the implied density non-negative (no butterfly arbitrage) and each expiry's total variance above the one before (no calendar arbitrage).

Measured: 180 synthetic chains, 20 at each noise and drop setting
Arbitrage-free fits: slices with butterfly or calendar arbitrage0 of 1,250
Unconstrained fits: slices with butterfly or calendar arbitrage532 of 1,250
Prices inverted per chain (bid, ask and mid of 175 quotes)525
Recorded chains: mid prices with an implied vol175 of 175
One Chalk query: chain, implied vols and both fits0.65–1.02 s
Of which the 14 SVI fits0.41–0.77 s
American put quotes read as European: vol overstated at 1y by up to0.42 points
Book stress: 207 positions repriced 20 times for Greeks before and after0.14–0.15 s

A slice counts as arbitrage when its density function g(k) dips below zero, or its total variance falls below the previous expiry's, anywhere on one grid that spans every listed strike of every expiry plus half that range again on each side. The constraints cost little accuracy: across the listed strikes, the median RMS gap from the true surface is 0.26 vol points for the arbitrage-free fit against 0.24 unconstrained with typical noise, and 1.12 against 1.11 with stressed noise and 60% of quotes dropped. The constraints follow Gatheral and Jacquier, Arbitrage-free SVI volatility surfaces.

More capabilities

  • Apps next to the features

    The page's API is a ScalingGroup in the same environment, querying Chalk over gRPC with credentials that are Chalk secrets, not baked into the image.

  • Runs in your cloud

    Chalk deploys into your own AWS, GCP or Azure account, so proprietary quotes and models never leave it.

Serve your models where your quotes live

Volatility surfaces, curves, risk and pricing features: talk to an engineer about computing them in real time in your own cloud.