Noisy quotes in.
An arbitrage-free surface out.
Chalk resolvers invert Black-Scholes for every bid and ask of an option chain, fit a raw SVI smile to each expiry and keep the whole surface free of butterfly and calendar arbitrage. Pick an expiry, add noise, drop quotes, and watch the constrained fit hold while the unconstrained one breaks. Then price American, FLEX and structured products off the surface and stress a whole book, with Greeks, all as live Chalk queries.
Fit the smile, keep the surface honest
Each bar is one quote's bid-to-ask range in implied vol. Both fits see the same quotes: the lime smile is constrained to be arbitrage-free, the coral one is free to chase the noise. Where the coral smile bends the wrong way, its implied probability density turns negative, which is a butterfly spread that costs less than nothing. Stack the expiries into a surface and the unconstrained one also crosses itself in time: calendar arbitrage, in coral.
| Expiry | Butterfly | Calendar | RMS 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.
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.
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.
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.
| Greek | Now | Stressed |
|---|---|---|
| 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 | – | – |
| 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.
| Position | Qty | Value now | P&L | Delta | Gamma | Vega | Theta | Vanna | Volga |
|---|---|---|---|---|---|---|---|---|---|
| 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.
How it works
One online query for a VolSurfaceruns 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).
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.
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 docsfrom chalk import DataFrame
from chalk.features import features, has_many
@features
class OptionQuote:
id: str
surface_id: str
expiry_days: int
t: float # years to expiry
strike: float
is_call: bool
forward: float
discount: float
bid: float
ask: float
dropped: bool # held out of the fit
log_moneyness: float
iv_bid: float | None # None when no vol reproduces the price
iv_ask: float | None
implied_vol: float | None # of the mid
@features
class VolSurface:
id: str # "<seed>:<noise>:<drop>"
seed: int
noise: str
drop: float
quotes: DataFrame[OptionQuote] = has_many(
lambda: OptionQuote.surface_id == VolSurface.id
)
smiles: str # per expiry: truth, unconstrained and arbitrage-free SVI
arbitrage_free: bool
raw_arbitrage_slices: int
fit_ms: floatWhat Chalk handles
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.
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.