Everyone can quote the Black-Scholes formula. Far fewer can say what it is — where it comes from, why those two normal CDFs are there, and what would have to be true for it to be wrong.
The formula is not a model of what stocks do. It’s the answer to a narrower and much stranger question: if I sold this option and hedged it perfectly, what would that hedge have cost me? This post derives it from that question, then does the thing most derivations skip — actually runs the hedge, path by path, and checks that it replicates the payoff.
The setup, and what we’re assuming
We assume the stock follows geometric Brownian motion:
![]()
and that we can trade continuously, borrow and lend at a constant rate
, and face no transaction costs. Every one of those is false in the real world. We’ll come back to which ones matter.
Write
for the value of the option. It’s a function of time and the stock price — that’s the only structural assumption we need about it.
Step one: what happens to the option’s value
The stock moves randomly, so
moves randomly too. To describe how, we need Ito’s lemma — the chain rule for stochastic processes:
![]()
If you’ve only seen ordinary calculus, that third term in the bracket is the surprise. In ordinary calculus a second-order term would be negligible. Here it isn’t, because
rather than something vanishingly small — a Brownian path wiggles so violently that its squared increments accumulate at a finite rate. That single fact is where the
term comes from, and it’s ultimately why volatility has a price at all.
Step two: build a portfolio with no risk
Here’s the trick the whole thing rests on. Notice that
and
are driven by the same
. So we can cancel it.
Form a portfolio: short one option, long
shares.
![]()
Its change over an instant:
![]()
Substitute both expressions and collect the random parts. The
terms are:
![]()
Choose
![]()
and they cancel exactly. The portfolio has no random component left. Over the next instant, we know precisely what it will be worth.
That
is the option’s delta, and this is where it comes from — not a sensitivity someone decided to define, but the number of shares that makes the risk disappear.
Step three: no risk means no excess return
We now hold something riskless. If it earned more than the risk-free rate, you’d borrow at
, buy it, and pocket the difference with no risk — an arbitrage. If it earned less, you’d do the reverse. So it must earn exactly
:
![]()
Substitute, cancel the
, and rearrange. The
terms cancel along the way — which is the fact worth pausing on, and which we’ve looked at properly elsewhere. What survives is the Black-Scholes PDE:
![]()
Read it as a statement about a hedged book rather than as an equation. Each term is a P&L stream:
— theta: what you lose to time passing.
— gamma: what you earn from rebalancing as the stock moves around.
— carry: the financing on the shares you hold and the money you tied up.
The equation says these three sum to zero. A delta-hedged option book is a bet that gamma income covers theta bleed. That’s not an interpretation of the PDE — it is the PDE.
Step four: the boundary condition does the rest
The PDE describes any derivative on this stock. What makes it a call is the terminal condition:
![]()
Solve the PDE with that boundary and you get the formula:
![]()
![]()
What
and
actually mean
These get memorised and rarely understood, which is a shame because they’re the most quotable part of the formula.
is the probability the option finishes in the money — under
, not under your own view. So
is the discounted strike you expect to pay, weighted by the chance you’ll pay it.
is the delta: the shares you hold today. It’s also a probability, but under a different measure — one where the stock itself is the numeraire. So
is the value of the stock you expect to receive, weighted appropriately.
Price equals what you expect to receive minus what you expect to pay. The formula is a two-line accounting statement wearing a lot of notation.
Does the hedge actually work? Run it.
This is the part worth doing yourself, because it turns the derivation from an argument into a fact.
The claim: sell the call for the Black-Scholes price, delta-hedge it, and at expiry your portfolio should be worth exactly the payoff you owe. No profit, no loss.
import numpy as np
from scipy.stats import norm
S0, K, r, sigma, T = 100.0, 100.0, 0.05, 0.20, 1.0
mu = 0.10 # real-world drift; should not matter
n_paths, n_steps = 50_000, 252 # daily rebalancing
dt = T / n_steps
def bs_call(S, K, r, sigma, tau):
d1 = (np.log(S/K) + (r + 0.5*sigma**2)*tau) / (sigma*np.sqrt(tau))
d2 = d1 - sigma*np.sqrt(tau)
return S*norm.cdf(d1) - K*np.exp(-r*tau)*norm.cdf(d2)
def bs_delta(S, K, r, sigma, tau):
d1 = (np.log(S/K) + (r + 0.5*sigma**2)*tau) / (sigma*np.sqrt(tau))
return norm.cdf(d1)
np.random.seed(1)
S = np.full(n_paths, S0)
V0 = bs_call(S0, K, r, sigma, T) # we sell at this price
delta = bs_delta(np.array([S0]), K, r, sigma, T)[0]
cash = V0 - delta*S0 # premium in, shares bought
shares = np.full(n_paths, delta)
for i in range(1, n_steps + 1):
Z = np.random.standard_normal(n_paths)
S = S * np.exp((mu - 0.5*sigma**2)*dt + sigma*np.sqrt(dt)*Z)
cash = cash * np.exp(r*dt) # cash earns the risk-free rate
tau = T - i*dt
new_delta = (bs_delta(S, K, r, sigma, tau) if tau > 1e-12
else (S > K).astype(float))
cash -= (new_delta - shares) * S # buy/sell to the new delta
shares = new_delta
portfolio = shares*S + cash
payoff = np.maximum(S - K, 0.0)
err = portfolio - payoff
print(f"Black-Scholes price at t=0: {V0:.4f}")
print(f"Mean hedge error: {err.mean():+.4f}")
print(f"Std dev of hedge error: {err.std():.4f}")
Which gives:
Black-Scholes price at t=0: 10.4506
Mean hedge error: -0.0010
Std dev of hedge error: 0.4290
On average, the hedge lands on the payoff to within a tenth of a cent. We sold at 10.45, ran the hedge, and ended up owing exactly what we had. The premium was the cost of the hedge — which is what the derivation claimed.
Two things worth noticing. First, we simulated the stock with
, nowhere near the risk-free rate, and the hedge still worked. The drift genuinely doesn’t matter. Change it to 30% or to
and the mean error stays at zero.
Second, that standard deviation of 0.43 is not model error. It’s the price of rebalancing 252 times instead of continuously.
The gap between theory and a real desk
Watch what happens when we vary how often we rebalance:
4 rebalances mean error -0.0184 std 3.1490
21 rebalances mean error -0.0138 std 1.4574
63 rebalances mean error -0.0110 std 0.8526
252 rebalances mean error -0.0062 std 0.4232
1008 rebalances mean error +0.0006 std 0.2138
The mean stays at zero throughout — the hedge is unbiased however lazily you run it. But the spread shrinks roughly like
: quadruple the rebalancing, halve the error. Hedge four times a year and any individual trade can be off by several points. Hedge daily and you’re within half a point.
This is the real content of “continuous trading”. Black-Scholes doesn’t need the world to be continuous; it needs you to rebalance often enough that the leftover noise is small relative to your risk appetite. And in practice you can’t just rebalance a thousand times, because every trade costs money — which is why real desks hedge on bands and thresholds rather than on a schedule.
Which assumptions actually break
The famous list of Black-Scholes assumptions is not equally famous for being wrong. Ranked by how much they hurt:
- Constant volatility — badly wrong, and it shows. Real option prices imply different volatilities at different strikes. That’s the smile, and it exists because returns aren’t lognormal: crashes are fatter and more sudden than the model allows. Everything from local vol to stochastic vol exists to patch this.
- Continuous paths — wrong, and it matters for the wings. Prices gap. A hedge that assumes you can always trade at the last price fails precisely when you need it.
- No transaction costs — wrong, and it changes your behaviour. It’s why nobody hedges continuously even when they could.
- Single constant rate — wrong, but manageable. Real desks discount on a curve and worry about funding spreads. Structurally fine, just more bookkeeping.
- Lognormal terminal distribution — wrong, but it’s the same objection as constant vol.
Given all that, why does anyone still use it? Because it survives as a language rather than as a forecast. Nobody believes the volatility surface is flat; everyone quotes options in Black-Scholes implied vol because it’s a clean way to express a price. The formula became the unit of measurement even after it stopped being the model.
What to take away
Black-Scholes is a hedging argument, not a prediction. Build a portfolio whose risk cancels, insist that riskless things earn the riskless rate, and the price falls out. Delta is what makes the cancellation work, gamma is what you’re paid for, theta is what you pay, and the drift never enters because a hedged book doesn’t care about direction.
If you want to see this built rather than argued — replication and no-arbitrage from first principles, then the measure change, then a Monte Carlo pricer benchmarked against exactly this formula with a full validation suite — that’s the arc of Risk-Neutral Valuation.
Until then: take the hedging code above, set volatility in the simulation to something different from the volatility in the delta, and watch the mean error stop being zero. That gap is vega, and it’s where the next set of models begins.
Get the Quant Reference Card — four pages covering stochastic calculus, measure change, the models you’ll actually meet, discretisation, rates, credit and XVA, with the practitioner notes that don’t make it into textbooks. Free.