Skip to content

Three ways to price an option, and the surface to price it on

Black-Scholes, a binomial tree and Monte Carlo that agree within their error bars, Greeks computed four ways, and arbitrage-free SVI volatility surfaces fitted to SPY and QQQ option chains.

By Mizan Nurani

Data as of October 9, 2026

Built with Python, NumPy, SciPy, TypeScript

European (Black-Scholes)

$15.07

intrinsic $0.00, time value $15.07

American (binomial tree)

$15.07

early-exercise premium $0.000

Implied vol used

12.61%

off the surface at 99.7% of the forward

Probability in the money

52.1%

risk-neutral; breakeven $795.07

Greeks, per share (a listed contract is 100 shares)

Delta
0.5390
per $1 of spot
Gamma
0.01152
delta per $1
Vega
$1.0854
per vol point
Theta
−$0.1987
per calendar day
Rho
$0.4988
per point of rates
Vanna
−0.00169
delta per vol point
Volga
$0.00045
vega per vol point
Dollar gamma
$0.349
P&L for a 1% move

Black-Scholes Greeks with the vol held fixed. The American price is the closed form plus the gap between American and European 400-step trees, which cancels most of the tree’s own error.

Put-call parity

C − P = 2.605643
S e−qT − K e−rT = 2.605643

Gap below 5e-14

Monte Carlo, 200,000 paths

Antithetic pairs, seed 2026, one step to expiry.

σ = 12.609%

Exhibit 1Value against spot

Per share, today, with 23 days left and at expiry. Vol re-read from the surface at each spot.

  • Today
  • 23 days left
  • At expiry

Black-Scholes on the fitted surface. Author’s calculations.

Exhibit 2How the risk moves with spot

Delta per share

Greek

  • Today
  • 23 days left
  • 7 days left

Analytical Black-Scholes Greeks. Author’s calculations.

Exhibit 3Scenario grid

Change in value per share for a spot move (rows) and a parallel vol shift (columns), the same day. The outlined cell is today.

Spot / Vol−5 pts−2 pts0 pts+2 pts+5 pts
−10% ($701)−15.07−15.06−14.99−14.82−14.28
−5% ($740)−15.04−14.54−13.78−12.73−10.76
−2% ($763)−12.75−10.07−8.13−6.13−3.06
0% ($779)−5.42−2.170.00+2.17+5.43
+2% ($794)+6.46+9.16+11.10+13.09+16.16
+5% ($817)+27.89+29.59+30.99+32.54+35.06
+10% ($856)+66.00+66.87+67.67+68.64+70.36

Black-Scholes on the fitted surface, under the spot rule chosen above. Author’s calculations.

The SPY surface

Moving spot in the pricer moves this surface under the rule you chose (spot 0.0%). Shocks act on implied vol by moneyness, and the pricer reads the shocked vol.

0.00 pts
0.00 pts

Fades with a three-month time constant

1.00×
  • No butterfly arbitrage
  • No calendar arbitrage

Checked live at every fitted expiry: the butterfly condition over the quoted strikes plus 10%, and total variance against the previous expiry where both are quoted.

Exhibit 4The smile at 45 days

Implied vol by strike as a share of the forward, over the strikes quoted near that expiry

  • Fitted
  • Your option

SVI fits to SPY option quotes; Mizan Nurani, options-engine. Author’s calculations.

Exhibit 5At-the-money vol by expiry

Implied vol at the forward, from a week to two years, log scale in time

  • SPY
  • QQQ

SVI fits to SPY and QQQ option quotes; Mizan Nurani, options-engine. Author’s calculations.

Exhibit 6The surface, expiry by strike

Implied vol (%) at every other fitted expiry, by strike as a share of the forward. Blank where that expiry has no quotes.

Expiry / K/F80%85%90%95%100%105%110%
2026-10-16 (7d)30.918.29.5
2026-10-30 (21d)37.430.122.816.111.110.2
2026-11-13 (35d)33.427.521.716.412.110.512.3
2026-11-30 (52d)30.225.320.415.912.310.411.2
2026-12-31 (83d)27.923.819.916.313.311.311.0
2027-01-29 (112d)26.623.019.616.413.811.911.2
2027-03-19 (161d)25.022.019.216.714.613.012.0
2027-06-17 (251d)23.821.419.217.215.514.113.1
2027-09-17 (343d)23.121.019.217.516.014.913.9
2027-12-17 (434d)22.520.819.117.716.415.414.5
2028-06-16 (616d)21.920.419.117.916.815.915.1
2028-12-15 (798d)21.620.319.118.017.016.215.5

SVI fits to SPY option quotes; Mizan Nurani, options-engine. Author’s calculations.

Three pricers, one answer

The engine prices a European option three independent ways and treats any disagreement as a bug. Black-Scholes-Merton with a continuous dividend yield qq is the closed form:

C=Se−qTN(d1)−Ke−rTN(d2),d1,2=ln⁡(S/K)+(r−q±12σ2)TσTC = S e^{-qT} N(d_1) - K e^{-rT} N(d_2),\qquad d_{1,2} = \frac{\ln(S/K) + (r - q \pm \tfrac{1}{2}\sigma^2)T}{\sigma\sqrt{T}}

The Cox-Ross-Rubinstein tree moves the stock up by u=eσΔtu = e^{\sigma\sqrt{\Delta t}} or down by d=1/ud = 1/u with risk-neutral probability p=(e(r−q)Δt−d)/(u−d)p = (e^{(r-q)\Delta t} - d)/(u - d), then rolls the payoff back to today. An American option takes the larger of holding and exercising at every node. The tree oscillates as the strike falls between nodes at a position that shifts with the number of steps; averaging N and N+1 steps removes most of it (Exhibit 7). With the same inputs, the tree values the American put at 10.390 against 10.056 for the European, an early-exercise premium of 0.334.

Exhibit 7The binomial tree converges to Black-Scholes, with a sawtooth

Call price by number of steps (S 100, K 105, nine months, 25% vol, 4% rate, 1% yield)

  • Average of N and N+1 steps
  • Tree at N steps, even and odd

Cox-Ross-Rubinstein tree, run on this page’s engine. Author’s calculations.

Monte Carlo draws the terminal price exactly in one step and reports every estimate with its standard error, so agreement is judged in standard errors rather than digits. On a million paths, antithetic pairs cut the variance by only 1.4x, because an out-of-the-money call’s payoff is far from linear in the normal draw. A control variate on the discounted terminal price, whose expectation is known, cuts it by 4.2x (Exhibit 8).

Exhibit 8Monte Carlo, with and without variance reduction

The call in Exhibit 7, a million paths, seed 2026

MethodEstimateStandard errorDistance from closed formVariance reduction
Plain7.41260.01340.07 SE1.0x
Antithetic variates7.41170.01120.01 SE1.4x
Control variate7.41370.00660.31 SE4.2x

Closed form 7.4117.

Mizan Nurani, options-engine (results/mc_variance_reduction.csv).

Greeks four ways

Each Greek is computed four ways: the closed form, central differences on the closed form, central differences on Monte Carlo, and pathwise Monte Carlo, which differentiates the payoff along each simulated path:

Δ=e−rT E ⁣[f′(ST) STS],ν=e−rT E ⁣[f′(ST) ST(TZ−σT)]\Delta = e^{-rT}\,\mathbb{E}\!\left[f'(S_T)\,\frac{S_T}{S}\right],\qquad \nu = e^{-rT}\,\mathbb{E}\!\left[f'(S_T)\,S_T\big(\sqrt{T}Z - \sigma T\big)\right]

That works because a call or put payoff is Lipschitz. It fails for gamma: f′f' is a step at the strike, so its derivative is a spike the simulation never samples. Gamma uses the likelihood-ratio estimator instead, which differentiates the density rather than the payoff:

Γ=e−rT E ⁣[f(ST)(Z2−1S2σ2T−ZS2σT)]\Gamma = e^{-rT}\,\mathbb{E}\!\left[f(S_T)\left(\frac{Z^2 - 1}{S^2\sigma^2 T} - \frac{Z}{S^2\sigma\sqrt{T}}\right)\right]

The bumped Monte Carlo reuses the same draws for the up and down bumps, so most of the noise cancels path by path. Every estimate in Exhibit 9 sits within 0.63 standard errors of the closed form.

Exhibit 9Greeks four ways

The option in Exhibit 7. Monte Carlo on 500,000 paths, seed 2026; z is the pathwise estimate’s distance from the closed form in standard errors. Vega and rho per unit.

Option

GreekClosed formBumped closed formBumped Monte CarloPathwise Monte Carloz
Delta0.491050.491020.49103 ± 0.000840.49113 ± 0.00085+0.10
Gammalikelihood ratio0.018290.018280.01823 ± 0.000160.01839 ± 0.00016+0.63
Vega34.28834.28834.302 ± 0.09234.303 ± 0.092+0.16
Theta, a year−6.891−6.891−6.894 ± 0.017−6.894 ± 0.017−0.16
Rho31.27031.27031.273 ± 0.05331.275 ± 0.053+0.09

Mizan Nurani, options-engine (results committed in the repository). Author’s calculations.

What discrete hedging leaves behind

The engine sells a six-month at-the-money call for $6.37, hedges it at Black-Scholes delta, and lets the stock drift at 8% a year in the real world. The P&L is centered on zero whatever the drift, which is the replication argument at work. What is left is the error from hedging at intervals: with 26 rebalances, about weekly, its standard deviation is $0.93, 15% of the premium; with 126, about daily, it falls to $0.44 (7%). The fitted slope of −0.49 in Exhibit 10 is close to the theoretical one half.

Exhibit 10Hedging error shrinks with the square root of the rebalances

Standard deviation of the P&L of a short six-month at-the-money call hedged at Black-Scholes delta (premium $6.37). Log scales; fitted slope −0.49.

  • Simulated, 20,000 paths
  • One over the square root of n

Mizan Nurani, options-engine (results committed in the repository). Author’s calculations.

From option chains to a surface

The second half of the engine builds the SPY and QQQ surfaces in the lab above from a snapshot of their option chains at the October 9, 2026 close. Every filter counts what it drops (Exhibit 11): expiries under a week or over 800 days, zero bids, crossed markets, prices under five cents, spreads wider than half the mid, no open interest, and the in-the-money side of each strike, which keeps the early-exercise bias small.

Exhibit 11Every dropped quote is counted

Option quotes at the October 9, 2026 close, filters applied in order

StepSPY droppedQQQ dropped
Raw quotes8,6467,810
Expiry outside window620755
Zero or missing bid494303
Crossed or locked market21
Mid below 0.05297205
Relative spread above 50%49191
No open interest371333
OTM selection (ITM side dropped)2,7302,699
Out-of-the-money quotes used4,0833,323
Isolated stale quotes removed before fitting4621

Mizan Nurani, options-engine (results/cleaning_*.csv); quotes from Yahoo Finance.

Discount rates from the right options

Put-call parity gives each expiry’s discount factor and forward without assuming a rate: regressing C−PC - P on the strike gives slope −DF-DF and intercept DF⋅FDF \cdot F. On SPY and QQQ that regression is biased, because the early-exercise premium in in-the-money puts lowers C−PC - P at high strikes; it implies rates as low as −35%. European SPX options carry no such premium, so the curve comes from SPX (Exhibit 12). Fitted as r(T)=c0+c1ln⁡Tr(T) = c_0 + c_1 \ln T, it gives 4.42% at three months and 4.88% at a year.

Exhibit 12Discount rates from European SPX options

Zero rate implied by put-call parity at each SPX expiry, and the curve r(T) = c₀ + c₁ ln T fitted through them

  • Fitted curve
  • Implied by one expiry

Mizan Nurani, options-engine (results committed in the repository). Author’s calculations.

De-Americanizing the quotes

Each quote is then inverted on the American tree rather than the closed form. The bias from treating it as European is small in the middle of the chain (a median of 0.04 vol points for SPY) but reaches 4.3 vol points for long-dated puts near the forward. With rates well above the dividend yield the forward sits far above spot, so a long-dated put can be out of the money against the forward and in the money against spot, where early exercise is worth something.

A first attempt took the dividend yield from the parity forward and over-corrected, because that forward came from American prices and already carried the put’s premium. The fix calibrates the yield per expiry so that American-model put and call vols agree at the six strikes nearest the money. Checked out of sample at strikes further out, the median put-call gap falls from 0.65 to 0.04 vol points for SPY, and from 0.56 to 0.02 for QQQ. The calibrated yields also recover SPY’s quarterly dividend without being told about it (Exhibit 13): within 0.15% of zero for the November expiries, then 0.6% for December 18 and 1.1% for December 31, after the mid-December ex-dividend date. The yield also absorbs any cost of borrowing the ETF.

Exhibit 13Calibrated dividend yields find the ex-dividend dates

The continuous yield per expiry at which American-model put and call vols agree near the money

  • SPY
  • QQQ

Mizan Nurani, options-engine (results committed in the repository). Author’s calculations.

An arbitrage-free fit

Each expiry is fitted with raw SVI, in total variance w=σ2Tw = \sigma^2 T against log-moneyness k=ln⁡(K/F)k = \ln(K/F):

w(k)=a+b(ρ (k−m)+(k−m)2+s2)w(k) = a + b\left(\rho\,(k - m) + \sqrt{(k - m)^2 + s^2}\right)

The fit minimizes implied-vol errors scaled by the bid-ask half-spread, with three no-arbitrage conditions as penalties: the Gatheral-Jacquier butterfly function g(k)≥0g(k) \ge 0 over the quoted strikes plus a margin (a non-negative density), total variance that never falls with maturity where adjacent expiries are both quoted, and Roger Lee’s wing bound b(1+∣ρ∣)≤2b(1 + |\rho|) \le 2. Fitted freely, the SPY surface had butterfly arbitrage in 4 slices (QQQ 0) and 1 calendar violation (QQQ 1). With the constraints there are none, and the median fit error for SPY is unchanged at 0.13 vol points.

The constraints hold the fitted slices right at their boundary, which is why the live check in the surface section flags arbitrage after only a small change: a skew 5% steeper than fitted is enough for SPY. At the money, vol rises with maturity, from 9.5% at a week to 17.0% at 2.2 years for SPY (14.6% to 22.1% for QQQ), and QQQ carries 5.1 to 6.1 vol points more than SPY at every expiry both list (Exhibit 5).

How it is checked

  • Known values. Hull’s textbook examples, including the five-step American put, and the standard at-the-money reference call.
  • Invariants. Put-call parity on thousands of random inputs, prices inside the model-free bounds, the call and put deltas a dividend discount apart, an American call without dividends worth exactly the European, and an American put never below intrinsic value.
  • Inversion. Implied vol reprices every option it inverts, and returns nothing rather than a wrong answer outside the no-arbitrage bounds.
  • Simulation. Monte Carlo within four standard errors of the closed form for every variance-reduction choice, a standard error that falls with the square root of the paths, and results that repeat from a seed.
  • The surface pipeline, on synthetic chains with known answers. The parity regression recovers the forward and discount factor and ignores a stale quote, each cleaning rule drops exactly its target, the American inversion recovers a known vol, and the dividend calibration recovers a known yield.
  • Two implementations. The TypeScript engine on this page reproduces the closed-form Greeks committed in the Python repository to twelve significant digits (the bumped ones to nine), and recomputes every fitted slice’s at-the-money vol, butterfly minimum, wing slope and calendar gap from its parameters.

What it leaves out

  • The pricers assume constant volatility and rates; the tree is plain Cox-Ross-Rubinstein.
  • The hedging experiment ignores transaction costs, which would penalize frequent rebalancing.
  • The surface is one snapshot of end-of-day quotes, with no check that calls and puts were quoted at the same moment. Your numbers would differ on another day.
  • Dividends are a continuous yield per expiry rather than cash amounts on known ex-dates.
  • Raw SVI has five parameters per expiry and cannot follow the steepest short-dated put wings: the worst slice is QQQ at 42 days, 0.74 vol points of fit error. SSVI or eSSVI would give a jointly arbitrage-free surface with fewer slice-by-slice compromises.
  • Next steps: price an exotic off the fitted surface, a Dupire local-volatility model, and a cross-check against QuantLib.

Model, data pipeline and fits from Mizan Nurani’s options-engine (commit f4376f5, October 11, 2026). Option chains from Yahoo Finance at the October 9, 2026 close. This is a study, not a recommendation.