Live demo · Monte Carlo options pricing

A million paths per option.
A whole book in one query.

Path-dependent options have no closed form, so risk teams simulate them. A PyTorch Monte Carlo pricer runs on a GPU ScalingGroup, and ChalkSQL calls it for every position: mark a 2,000-option book, shock spot and volatility, and get the P&L by sector from a single query.

Simulate, then stress the book

Price a single option and watch its paths, or shock the market and reprice every position. Both run live on Chalk each time you click.

Price one option

Pick an underlying from the synthetic universe and a payoff. The GPU prices it with Greeks; run the same request on the replica's CPUs to compare.

40 of … simulated paths · terminal prices on the right
Price
–
Black–Scholes
no closed form
path-dependent payoff
Delta
–
Gamma
–
Vega
–
per vol point
Compute
–

Stress the whole book

2,000 positions across 40 underlyings, repriced under a market shock by one ChalkSQL query that calls the GPU pricer for every row.

Book P&L
–
Net delta after
–
P&L by sector
Biggest moversOptionQtyP&L

Every underlying (SYN01 to SYN40), price, volatility and position here is synthetic, generated from a fixed seed; none of it is market data or advice. The model is geometric Brownian motion with constant volatility and a 4% rate; barriers and averages are monitored at 64 dates. Prices run live on a Chalk GPU ScalingGroup; identical requests are cached for ten minutes, and custom stress tests and CPU runs share a per-minute budget.

Measured, not claimed

Numbers from the deployed demo. Scenario P&L reuses the marks' random numbers, so a shock moves prices, not simulation noise.

European prices vs Black–Scholes986 / 991 within 2 standard errorsthe 991 European positions in the book, marked at 50,000 paths; median error 0.05%
One option with Greeks, GPU7.8 ms200,000 paths × 64 steps, price plus four bumped repricings, NVIDIA L4
The same on 4 CPU cores108 mssame replica, same code, same random numbers: 14× slower
Mark the whole book4.0 s2,000 positions at 50,000 paths, one ChalkSQL query
One stress scenario3.6 sreprice every position, P&L by sector, end to end through ChalkSQL

How it works

A vectorized pricer on a GPU, exposed as a function your queries can call, fed a whole table at a time.

A synthetic universe

Forty fictional underlyings in five sectors, each with its own spot, volatility and dividend yield, and a 2,000-position book of European, Asian and barrier options on them. Nothing is market data.

Monte Carlo on a GPU

PyTorch simulates geometric Brownian motion with antithetic paths on a GPU ScalingGroup. Asian averages and barriers are monitored at 64 steps; Greeks come from bumps on the same random numbers.

One function, coalesced

A Chalk function wraps the pricer. Rows arriving together become one GPU request, so pricing a whole table costs a few kernel launches, not a network call per option.

Risk in one query

ChalkSQL marks the book once, then reprices every position under a scenario with catalog_call and rolls the P&L up by sector with a window function.

Getting started

Run your own risk on GPUs

Check the pricer against closed forms, generate the synthetic book, deploy the GPU pricer and its Chalk function, and mark the book with one query. Stress scenarios are the same query with shocked inputs, in SQL or as a DataFrame.

Point it at your own positions table and the queries do not change: the book is just a table with a kind, strike, barrier and expiry per row.

chalk-ai/options-monte-carlo
-- Spot -20%, volatility x1.5: every position repriced on the GPU, one query.
WITH priced AS (
    SELECT b.position_id, b.underlying, b.sector, b.kind, b.quantity, b.mark,
           catalog_call('function.option-mc-price',
                        b.kind, b.spot * 0.80, b.strike, b.barrier, b.expiry_years,
                        b.vol * 1.50, b.rate, b.div_yield, 50000) AS r   -- [price, stderr, delta, gamma, vega]
    FROM read_parquet('https://<app>/data/book_marked.parquet') AS b
)
SELECT position_id, underlying, sector, kind, quantity,
       quantity * 100 * (r[1] - mark) AS pnl,
       sum(quantity * 100 * (r[1] - mark)) OVER (PARTITION BY sector) AS sector_pnl
FROM priced
ORDER BY abs(pnl) DESC

What Chalk handles

GPUs, batching and the query engine, so the quant code stays a pricer.

GPUs on demand

ScalingGroups run any container on a GPU between replica bounds you set: one L4 for this demo, a pool for an overnight risk run.

Models inside queries

catalog_call puts a pricer, a model or any service in the middle of a SQL query or DataFrame, next to joins, filters and aggregations.

Batching built in

Functions buffer concurrent calls and hand them to your code together, so a vectorized GPU kernel sees the whole batch.

Checked, not assumed

European prices are compared with Black–Scholes on every run, and the same request on CPU and GPU returns the same numbers.

Positions stay in your cloud

The book, the pricer and the queries run in your Chalk environment. Nothing leaves for a third-party risk service.

Bring your own model

Swap GBM for Heston, local volatility or a neural surrogate. The function signature and the queries stay the same.

Put your risk models next to your data

Pricing, stress testing or any simulation that needs GPUs on demand: talk to an engineer about running it on Chalk.