Option Pricing, Done Honestly: Black-Scholes + Monte Carlo as a FastAPI Microservice
An open-source option-pricing API: closed-form Black-Scholes, seeded Monte Carlo with antithetic variates, and all five Greeks — with a pytest suite that checks the math against textbook values. And yes, the repo name says "quantum." The code is refreshingly honest about that.
TL;DR: POST /price with spot, strike, expiry, rate, and volatility, and you get back the Black-Scholes closed-form price, delta/gamma/vega/theta/rho, plus a seeded Monte Carlo estimate with its standard error — reproducible to the digit because the RNG seed is part of the request. The implementation is classical quantitative finance (the README, the docstring, and the /health endpoint all say so: "quantum": false). Tests verify the pricer against known textbook values (S=100, K=100, T=1, r=5%, σ=20% → call ≈ 10.4506), put-call parity, and Monte Carlo convergence.
The problem: pricing code nobody can audit
Option pricing is one of those domains where "the spreadsheet says so" passes for infrastructure. A surprising amount of production pricing logic lives in Excel models and opaque scripts — hard to test, hard to reproduce, and impossible to call from an API. Meanwhile, the math itself is a solved problem: Black-Scholes has a closed form, Monte Carlo converges to it, and the Greeks have analytic formulas. What the world needs is not new math but boring, correct, callable math — a service that prices, shows its work, and can be tested against known values.
That's what this repo is. A FastAPI service with two pricing engines, five Greeks, strict input validation, and a test suite that treats the textbook as the specification. It also carries an unusual virtue for finance software: it tells you what it is not. The repo is named finance-quantum-option-pricing; the first thing the README does is clarify that no quantum hardware or quantum algorithm is involved. In a field full of quantum-washing, that honesty is a feature.
How it works: two engines, one endpoint
Engine 1 — Black-Scholes closed form
bs_price() implements the textbook formulas directly, with the standard normal CDF built from math.erf — no SciPy dependency:
def norm_cdf(x: float) -> float:
return 0.5 * (1.0 + math.erf(x / math.sqrt(2.0)))
d1 = (math.log(S / K) + (r + 0.5 * sigma * sigma) * T) / (sigma * math.sqrt(T))
d2 = d1 - sigma * math.sqrt(T)
call = S * N(d1) - K * e^{-rT} * N(d2)
put = K * e^{-rT} * N(-d2) - S * N(-d1)
Engine 2 — Monte Carlo with antithetic variates
mc_price() simulates risk-neutral geometric Brownian motion paths with NumPy, using antithetic variates — half the random draws are mirrored (z concatenated with -z), a classic variance-reduction technique that tightens the estimate for free. It returns the discounted mean payoff and the standard error, so callers know how much to trust the number. The RNG is seeded (np.random.default_rng(seed), default 42), the seed is echoed in the response, and the test suite asserts that identical seeds produce identical prices. Seeded randomness is real stochastic math made reproducible — not fake AI, as the response payload itself notes.
The Greeks
greeks() returns all five analytic sensitivities with practitioner-friendly units:
| Greek | Meaning | Units in this API |
|---|---|---|
| Delta | Price change per $1 move in spot | Raw (0–1 for calls) |
| Gamma | Delta's change per $1 move in spot | Raw |
| Vega | Price change per volatility move | Per 1% vol move |
| Theta | Time decay | Per day |
| Rho | Price change per rate move | Per 1% rate move |
The API contract
Requests are validated by a Pydantic model — S, K, T, and sigma must be positive, n_paths is clamped between 1,000 and 5,000,000, and option is restricted to "call"/"put". Bad inputs get 400/422, not NaN. GET /health reports the available methods and — characteristically — "quantum": false.
Anatomy of a response
A single POST /price returns everything a quant needs to sanity-check the number, not just the number. The inputs block echoes the validated request back — useful when you're sweeping parameters and want each result to carry its own provenance. black_scholes_price sits next to d1 and d2, the intermediate variables, so anyone can verify the closed form by hand. The greeks object carries all five sensitivities. And the monte_carlo block reports not only the simulated price but the standard error, the path count, and the seed — plus a note field reminding you that seeded randomness is reproducible stochastic math. When the Monte Carlo price and the closed form agree within a few standard errors, you have two independent engines confirming each other. That's the whole point of shipping both.
Run it yourself
pip install -r requirements.txt # fastapi, uvicorn, numpy, pytest, httpx
uvicorn main:app --port 8000
curl -X POST localhost:8000/price -H 'Content-Type: application/json' -d '{
"S": 100, "K": 100, "T": 1, "r": 0.05, "sigma": 0.20,
"option": "call", "n_paths": 200000, "seed": 42}'
# expected: black_scholes_price ≈ 10.4506 (textbook value)
The response bundles inputs, the closed-form price, d1/d2, all Greeks, and the Monte Carlo block (price, standard error, path count, seed, and a method_note restating that this is classical math).
The test suite: the textbook is the spec
tests/test_pricing.py is the strongest part of the repo. Rather than testing that code runs, it tests that the math is right:
- Known values: S=100, K=100, T=1, r=5%, σ=20% must give call = 10.450583572 and put = 5.573526022 to six decimal places — the standard textbook reference.
- Put-call parity: C − P must equal S − Ke−rT to 1e-9 — an arbitrage identity the code must satisfy by construction.
- Greeks sanity: call delta in (0,1), gamma > 0, vega > 0, theta negative, rho positive; put delta in (−1,0); call/put gamma identical.
- Monte Carlo convergence: 400,000 paths must land within 3 standard errors of the closed form, with standard error under 0.05.
- Seed reproducibility: same seed, same price — asserted exactly.
- Endpoint + validation: the HTTP layer returns the textbook price, echoes the seed, reports
quantum: falseon health, and rejects negative spot with 400/422.
Run it with pytest -q. This is how quantitative code should be tested: against identities the math guarantees, not against snapshots of its own output.
Why the quantum disclaimer matters
"Quantum" is the most abused word in fintech marketing. Quantum-inspired, quantum-ready, quantum-adjacent — the terms multiply while the qubits stay the same. This repo does something unusual: it puts the correction in four places — the README's opening note, the module docstring, the /price response's method_note, and the /health endpoint's "quantum": false flag. A seeded NumPy RNG is doing the Monte Carlo work, and the code says so plainly: "that is real stochastic math, not fake AI — the seed is documented and reported so every run is reproducible."
That posture is worth more than it looks. When you're evaluating financial software — especially from an open-source repo — the first question is always "can I trust what this claims?" A codebase that volunteers its own limitations (classical only, European options only, constant volatility) is a codebase you can reason about. The disclaimer isn't modesty; it's the trust mechanism.
Deployment
The repo ships a Dockerfile and a GitHub Actions workflow (.github/workflows/deploy.yml), so the path from clone to hosted API is short: pip install -r requirements.txt for local runs, containerize for anything else. The dependency list is deliberately thin — FastAPI, Uvicorn, NumPy, pytest, httpx — no SciPy, no pandas, no heavy quant libraries. The normal CDF comes from math.erf; everything else is arithmetic. Thin dependencies mean fast cold starts and fewer supply-chain surprises, which is exactly what you want from a pricing microservice.
Honest status and limits
Status: working. The closed form, the Greeks, the Monte Carlo engine, input validation, and the test suite are all implemented and consistent. The repo also ships a Dockerfile and a GitHub Actions deploy workflow.
The limits are scope, not bugs:
- European options only. No early-exercise (American) pricing, no dividends, constant volatility — the classic Black-Scholes assumptions. Fine for education and baseline pricing; not a trading desk.
- No implied-volatility solver. You can price from vol, but you can't yet invert a market price to get vol — the most common real-world use.
- Single-contract requests. No batch endpoint; pricing a whole book means one HTTP call per contract.
- The name. It says quantum; it isn't. The code discloses this three times over. Rename-worthy, but the honesty is already in place.
Roadmap
- Implied volatility via Newton-Raphson/bisection on the closed form.
- Dividends (continuous yield) and American options (binomial tree / Longstaff-Schwartz).
- Batch pricing — price a list of contracts in one request with vectorized NumPy.
- Surface endpoints — vol smile input, scenario grids (price vs. spot/vol).
- Historical calibration — estimate σ from price history instead of taking it as input.
Frequently asked questions
No — and the repo says so explicitly in the README, the module docstring, the API response, and the
/health endpoint ("quantum": false). It's classical Black-Scholes plus Monte Carlo. The name is a misnomer the code refuses to let you misunderstand.The pytest suite checks the implementation against published textbook values to six decimal places, verifies put-call parity (an arbitrage identity), and confirms Monte Carlo converges to the closed form within statistical tolerance.
Yes. The RNG seed is a request parameter (default 42), it's echoed back in the response, and the test suite asserts identical seeds give identical prices.
Not as-is: it prices European options under constant-volatility Black-Scholes assumptions, with no dividends and no implied-vol solver. It's a correct, tested baseline — extend it (see roadmap) before putting capital behind it.
The bottom line
This is a small repo with an outsized virtue: it prices options correctly, proves it with real tests, and tells you exactly what it isn't. In quantitative finance — and frankly in all of open source — that combination is rarer than it should be. The code is public and the textbook values are waiting.
Try it: github.com/Shivay00001/finance-quantum-option-pricing — built by Shivam Kumar, VisionQuantech. Need quantitative tooling or a pricing API built for your desk? [email protected]