Skip to content

Black-Scholes Derivation: From Replicating Portfolio to Closed Form

A complete derivation of the Black-Scholes formula via the replicating portfolio argument. From the stochastic differential equation to the boundary conditions to the d1, d2 closed form.

1 of 12 ~16 min

If you have ever opened a derivatives textbook, the first thing you saw was almost certainly the Black-Scholes formula. It is printed on mugs, embroidered on quants’ jackets, and quoted in every options explainer written since 1973. Most of those explainers treat it like scripture. This article treats it like a derivation that two guys figured out in a few weeks, because that is what it is.

Fischer Black and Myron Scholes published their model in 1973, and Robert Merton extended it the same year (Hull, 2018, Ch. 15). The paper is fifteen pages long and does not pull a PDE out of thin air. It pulls the PDE out of the observation that you can replicate an option payoff with a dynamic portfolio of the underlying and a risk-free bond. From there the rest is algebra.

The Setup

Let StS_t be the price of a non-dividend-paying stock at time tt, and let V(S,t)V(S, t) be the price of a derivative paying off at time TT. Assume:

  1. The stock follows geometric Brownian motion:
dSt=μSt dt+σSt dWtdS_t = \mu S_t \, dt + \sigma S_t \, dW_t

where μ\mu is the drift, σ\sigma is the volatility, and WtW_t is a standard Brownian motion under the physical measure.

  1. There is a constant risk-free rate rr, available for both borrowing and lending.
  2. Trading is continuous. No bid-ask spread. No transaction costs. You can go short.
  3. The stock pays no dividends.

The last three assumptions are how the model sells its soul to make the math clean. Drop any one and the closed form disappears (Hull, 2018, Ch. 15.1).

What we want is V(S,t)V(S, t). We do not care about μ\mu, and the fact that we will not need it is the entire trick.

The Replicating Portfolio

Construct a portfolio Π\Pi consisting of one short derivative and a position Δ\Delta in the underlying stock:

Π=V−ΔS\Pi = V - \Delta S

The cash from selling the derivative finances the position. Over an infinitesimal time dtdt, the portfolio changes by:

dΠ=dV−Δ dSd\Pi = dV - \Delta \, dS

By Itô’s lemma (Luenberger, 2013, Ch. 12), V(S,t)V(S, t) has a stochastic differential:

dV=(∂V∂t+μS∂V∂S+12σ2S2∂2V∂S2)dt+σS∂V∂S dWtdV = \left(\frac{\partial V}{\partial t} + \mu S \frac{\partial V}{\partial S} + \frac{1}{2}\sigma^2 S^2 \frac{\partial^2 V}{\partial S^2}\right) dt + \sigma S \frac{\partial V}{\partial S} \, dW_t

Subtract Δ dS\Delta \, dS:

dΠ=(∂V∂t+μS∂V∂S+12σ2S2∂2V∂S2−μΔS)dt+(σS∂V∂S−σΔS)dWtd\Pi = \left(\frac{\partial V}{\partial t} + \mu S \frac{\partial V}{\partial S} + \frac{1}{2}\sigma^2 S^2 \frac{\partial^2 V}{\partial S^2} - \mu \Delta S\right) dt + \left(\sigma S \frac{\partial V}{\partial S} - \sigma \Delta S\right) dW_t

Now choose:

Δ=∂V∂S\Delta = \frac{\partial V}{\partial S}

This makes the dWtdW_t coefficient vanish. The diffusion risk is gone. Over dtdt, the portfolio is deterministic:

dΠ=(∂V∂t+12σ2S2∂2V∂S2)dtd\Pi = \left(\frac{\partial V}{\partial t} + \frac{1}{2}\sigma^2 S^2 \frac{\partial^2 V}{\partial S^2}\right) dt

Because the portfolio is now riskless, it must earn the risk-free rate (otherwise arbitrage). If it earned more, you would borrow infinitely; less, you would short it:

dΠ=rΠ dt=r(V−∂V∂SS)dtd\Pi = r\Pi \, dt = r\left(V - \frac{\partial V}{\partial S} S\right) dt

Equate the two:

∂V∂t+12σ2S2∂2V∂S2+rS∂V∂S−rV=0\frac{\partial V}{\partial t} + \frac{1}{2}\sigma^2 S^2 \frac{\partial^2 V}{\partial S^2} + rS \frac{\partial V}{\partial S} - rV = 0

This is the Black-Scholes PDE. Note three things.

First, μ\mu is gone. Drift does not enter the option price. This is the central point of the model and the foundation of risk-neutral pricing. It does not matter whether the market expects the stock to rise 20% per year or fall 5%; the option’s value is the same.

Second, the PDE has only one state variable (SS) and three parameters (r,σ,Tr, \sigma, T). Anything you change about the market’s view on drift is irrelevant. Volatility is the only nonlinear input you have to nail down.

Third, this is a backward heat equation in reverse time. It is parabolic and becomes explosively unstable if run forward. We solve it backward, from the payoff at TT to the present.

Boundary Conditions

For a European call paying max⁡(ST−K,0)\max(S_T - K, 0), the terminal condition at t=Tt = T is:

V(S,T)=max⁡(S−K,0)V(S, T) = \max(S - K, 0)

Two spatial boundaries. As S→0S \to 0, the call becomes worthless:

V(0,t)=0V(0, t) = 0

As S→∞S \to \infty, the call behaves like the stock minus the discounted strike:

lim⁡S→∞V(S,t)=S−Ke−r(T−t)\lim_{S \to \infty} V(S, t) = S - K e^{-r(T-t)}

This is the deep-ITM limit where exercise is essentially certain. For a put, the boundaries flip (Wilmott, 2007, Vol. 1, Ch. 5).

The Change of Variables

To solve the PDE, you could fire a finite-difference solver at it. Black and Scholes chose the brutal path of analytic solution, and we still benefit. They used the substitution:

S=Kex,t=T−τ/12σ2S = K e^x, \quad t = T - \tau / \frac{1}{2}\sigma^2

which transforms the PDE into the canonical heat equation. More common in modern textbooks (Hull, 2018, Ch. 15.4) is to flatten first with:

τ=T−t,V=e−rτU\tau = T - t, \quad V = e^{-r\tau} U

Substituting, the discount factor’s rr-dependent terms cancel, and UU satisfies:

∂U∂τ=12σ2S2∂2U∂S2+rS∂U∂S\frac{\partial U}{\partial \tau} = \frac{1}{2}\sigma^2 S^2 \frac{\partial^2 U}{\partial S^2} + rS \frac{\partial U}{\partial S}

The terminal condition for UU is the same payoff as VV.

Now set x=ln⁡(S/K)x = \ln(S/K), so S=KexS = K e^x. The PDE becomes:

∂U∂τ=12σ2∂2U∂x2+(r−12σ2)∂U∂x\frac{\partial U}{\partial \tau} = \frac{1}{2}\sigma^2 \frac{\partial^2 U}{\partial x^2} + \left(r - \frac{1}{2}\sigma^2\right) \frac{\partial U}{\partial x}

This is the heat equation with a constant drift in the xx-direction. It has a known Green function, a Gaussian kernel, and integrating that kernel against the terminal payoff gives the solution.

The Characteristic Function Argument

The PDE on xx is symmetric in x→−xx \to -x if you tilt by r−12σ2r - \frac{1}{2}\sigma^2. The trick is to add a velocity −r+12σ2-r + \frac{1}{2}\sigma^2 to remove the drift, which means looking at x+(r−12σ2)τx + (r - \frac{1}{2}\sigma^2)\tau in a moving frame.

Define y=x+(r−12σ2)τy = x + (r - \frac{1}{2}\sigma^2)\tau, then ∂/∂τ\partial/\partial \tau in yy becomes:

∂U∂τ−(r−12σ2)∂U∂y=12σ2∂2U∂y2\frac{\partial U}{\partial \tau} - (r - \tfrac{1}{2}\sigma^2)\frac{\partial U}{\partial y} = \frac{1}{2}\sigma^2 \frac{\partial^2 U}{\partial y^2}

The bonus term from the chain rule cancels the first-order yy derivative in the transformed PDE, and we’re left with the standard heat equation:

∂U∂τ=12σ2∂2U∂y2\frac{\partial U}{\partial \tau} = \frac{1}{2}\sigma^2 \frac{\partial^2 U}{\partial y^2}

whose solution starting from terminal condition f(y)f(y) is convolution with a Gaussian:

U(y,τ)=1σ2πτ∫−∞∞f(y′)exp⁡(−(y−y′)22σ2τ)dy′U(y, \tau) = \frac{1}{\sigma \sqrt{2\pi \tau}} \int_{-\infty}^{\infty} f(y') \exp\left(-\frac{(y - y')^2}{2\sigma^2 \tau}\right) dy'

For a call, f(y)=max⁡(Key′−K,0)=Kmax⁡(ey′−1,0)f(y) = \max(K e^{y'} - K, 0) = K \max(e^{y'} - 1, 0), which equals zero for y′<0y' < 0 and K(ey′−1)K(e^{y'} - 1) for y′≥0y' \geq 0. Substituting and grinding through the algebra (it really is just grinding) gives (Hull, 2018, eq. 15.20):

V(S,t)=S N(d1)−Ke−r(T−t)N(d2)V(S, t) = S \, N(d_1) - K e^{-r(T-t)} N(d_2)

where

d1=ln⁡(S/K)+(r+12σ2)(T−t)σT−td_1 = \frac{\ln(S/K) + (r + \tfrac{1}{2}\sigma^2)(T-t)}{\sigma \sqrt{T-t}} d2=d1−σT−t=ln⁡(S/K)+(r−12σ2)(T−t)σT−td_2 = d_1 - \sigma \sqrt{T-t} = \frac{\ln(S/K) + (r - \tfrac{1}{2}\sigma^2)(T-t)}{\sigma \sqrt{T-t}}

and N(⋅)N(\cdot) is the standard normal CDF.

This is the formula that appears on most pricing screens. Merton and Scholes received the Nobel Prize for this work; Black had died before the award.

The Put via Put-Call Parity

For a European put on the same underlying and same strike:

P=Ke−r(T−t)N(−d2)−SN(−d1)P = K e^{-r(T-t)} N(-d_2) - S N(-d_1)

You can derive this directly or get it for free from put-call parity:

C−P=S−Ke−r(T−t)C - P = S - K e^{-r(T-t)}

which holds identically for European options because you can replicate a forward by buying a call and selling a put (Hull, 2018, Ch. 11).

Interpreting the formula

Look at the call price C=SN(d1)−Ke−r(T−t)N(d2)C = S N(d_1) - K e^{-r(T-t)} N(d_2).

The first term is the expected value of STS_T conditional on ST>KS_T > K, in risk-neutral terms. The second term is the strike you pay, also in risk-neutral terms. Intuitively, the call is a probability-weighted stock value minus a probability-weighted strike. This is the discounted expectation of the payoff under the risk-neutral measure:

C=e−r(T−t)EQ[max⁡(ST−K,0)]C = e^{-r(T-t)} \mathbb{E}^{\mathbb{Q}}\left[\max(S_T - K, 0)\right]

N(d1)N(d_1) and N(d2)N(d_2) are probabilities in the risk-neutral world. N(d2)N(d_2) is the probability that the call finishes ITM. N(d1)N(d_1) is the option’s delta, or hedge ratio.

This is the risk-neutral pricing interpretation and is mathematically equivalent to the PDE argument. Cox and Ross (1976) and Harrison and Kreps (1979) showed the general result: in a complete market, any derivative price equals the discounted expectation under the unique risk-neutral measure (Wilmott, 2007, Vol. 1, Ch. 7).

Numerical Sanity Check

A small implementation confirms that the math translates into code and that the price requires only one norm.cdf call once d1d_1 and d2d_2 are known.

from math import erf, log, sqrt
from scipy.stats import norm

def bs_call(S, K, r, sigma, T):
    if T <= 0:
        return max(S - K, 0.0)
    d1 = (log(S / K) + (r + 0.5 * sigma**2) * T) / (sigma * sqrt(T))
    d2 = d1 - sigma * sqrt(T)
    return S * norm.cdf(d1) - K * exp(-r * T) * norm.cdf(d2)

Try S=100S = 100, K=100K = 100, r=0.05r = 0.05, σ=0.20\sigma = 0.20, T=1T = 1. You should get C≈10.45C \approx 10.45. The corresponding delta is N(d1)≈0.64N(d_1) \approx 0.64. If your hedge book is short 10,450 contracts worth of calls, you are long 6,400 shares. Discrepancies from that ratio show up immediately as P&L moves that scale 1-for-1 with the stock, meaning you are under- or over-hedged.

Where the Derivation Breaks

The PDE holds as long as you can replicate continuously with no friction. When you violate one of those assumptions, the closed form stops holding exactly:

  • Discrete trading. Hedging at intervals leaves residual variance. Hull calls the discrete-hedge P&L the “volatility drag”: realized variance is slightly different from the pathwise variance of the stock, and hedging P&L depends on the time interval.
  • Transaction costs. Every rebalance costs money; the optimal hedge now involves a tradeoff between tracking error and cost (Luenberger, 2013, Ch. 14).
  • Jumps. When the stock can gap, your hedge fails between trades. Merton’s (1976) jump-diffusion handles this.
  • Stochastic volatility. When σ\sigma is itself random, you cannot fully hedge. Volatility becomes a second source of risk.

Each of these is a separate research paper, and most of them are on the syllabus for a quant interview.

How to Read the Formula Two Other Ways

Once you have the closed form, several equivalent views help build intuition.

The Straddle Decomposition

Adding a put and a call at the same strike recovers the famous straddle pricing formula for an ATM strike K=S0K = S_0 (or, more cleanly, K=S0erTK = S_0 e^{rT} adjusting for carry):

C+P≈S0⋅(2N(d1/2)−1)⋅2πσ2T/S02⋅S0C + P \approx S_0 \cdot \left(2 N(d_1/2) - 1\right) \cdot \sqrt{2\pi \sigma^2 T / S_0^2} \cdot S_0

Wait, that’s not quite right. The correct formula for an ATM straddle using put-call parity:

C+P=2S0N(d1/2)−2Ke−rTN(−d1/2)C + P = 2 S_0 N(d_1/2) - 2 K e^{-rT} N(-d_1/2)

For K=F0=S0erTK = F_0 = S_0 e^{rT}, this simplifies to 2S0e−rT(2N(σT/2)−1)2 S_0 e^{-rT} (2 N(\sigma\sqrt{T}/2) - 1), which for small σT\sigma\sqrt{T} is approximately S0σ2T/πS_0 \sigma \sqrt{2 T / \pi}. That’s the famous formula: ATM straddle price equals approximately 0.4⋅S0⋅σT0.4 \cdot S_0 \cdot \sigma \sqrt{T}. For S&P at 4500 with σ=0.20\sigma = 0.20 and T=1/12T = 1/12, that’s 4500 \cdot 0.20 \cdot \sqrt{2/12\pi} \cdot 0.4 \approx \83$, which matches the one-month ATM straddle price you see on the screen.

The Hedged-Payoff View

Consider a trader who is long a call and short Δ\Delta shares. By Black-Scholes, Δ=N(d1)\Delta = N(d_1). The position has a modified payoff, meaning the instantaneous P&L from holding the hedged position over a short period. The expected value of this modified payoff over [t,t+dt][t, t+dt] is:

Π(t+dt)−Π(t)=r(Π(t))dt−BS sensitivity terms\Pi(t + dt) - \Pi(t) = r(\Pi(t)) dt - \text{BS sensitivity terms}

Integrating over the option’s life gives the cost of the hedge, which equals the option premium. This is sometimes called the “Black-Scholes gain diagram” and is useful for thinking about where the option premium comes from. Most of the premium is collected early in the option’s life, when gamma is highest.

The Distribution View

The price is, again:

C=e−r(T−t)∫K∞(ST−K) p(ST) dSTC = e^{-r(T-t)} \int_K^\infty (S_T - K) \, p(S_T) \, dS_T

where p(ST)p(S_T) is the lognormal density with mean ln⁡S0+(r−12σ2)(T−t)\ln S_0 + (r - \tfrac{1}{2}\sigma^2)(T-t) and variance σ2(T−t)\sigma^2 (T-t). Computing the integral:

C=S0N(d1)−Ke−r(T−t)N(d2)C = S_0 N(d_1) - K e^{-r(T-t)} N(d_2)

Verifying Black-Scholes makes the broader point: the price depends only on the distribution of STS_T, not on the dynamics. This is why risk-neutral pricing works. The option price summarizes the market’s view of the future spot distribution. You can invert this in principle: observed option prices imply a risk-neutral distribution (Breeden-Litzenberger, 1978), which can be compared with your model-implied distribution.

A Slightly Deeper Look at the Discounted Expectation

The risk-neutral pricing formula:

C=e−rTEQ[max⁡(ST−K,0)]C = e^{-rT} \mathbb{E}^{\mathbb{Q}}[\max(S_T - K, 0)]

is more than just a way to write Black-Scholes. It is the operational version: if you can compute expected payoffs under the risk-neutral measure, you can price any European option (Hull, 2018, Ch. 15.6; Wilmott, 2007, Vol. 1, Ch. 7).

The risk-neutral measure Q\mathbb{Q} is defined by the Radon-Nikodym derivative:

dQdP=e−rTST/S0EP[e−rTST/S0]=exp⁡(−(μ−r)σWT−12(μ−r)2σ2T)\frac{d\mathbb{Q}}{d\mathbb{P}} = \frac{e^{-rT} S_T / S_0}{\mathbb{E}^{\mathbb{P}}[e^{-rT} S_T / S_0]} = \exp\left(-\frac{(\mu - r)}{\sigma} W_T - \frac{1}{2} \frac{(\mu-r)^2}{\sigma^2} T\right)

where WTW_T is the physical Brownian motion. Under Q\mathbb{Q}, the stock drift becomes rr rather than μ\mu. This is Girsanov’s theorem: measure change to a numeraire, applied to the stock.

Practically, this means two things. First, when you run Monte Carlo under the risk-neutral measure, using rr as the drift, you get the option price directly. You do not need to know μ\mu. Second, when you calibrate to historical stock returns to estimate μ\mu, that estimate is irrelevant for option pricing. You need historical σ\sigma and the current rr term structure.

The catch: μ\mu matters for hedging effectiveness. When you construct a delta-hedge, your realized P&L depends on the realized stock returns vs. the implied rr. So historical μ\mu enters the backtest but not the price.

Common Numerical Pitfalls

When you implement Black-Scholes, several numerical details cause trouble more often than they should.

d1 and d2 need to be computed as floats with care. Floating-point rounding in ln⁡(S/K)\ln(S/K) for S=KS = K exactly produces −0.0-0.0 and breaks some software. Defensive code:

d1 = math.log(S / K) + (r + 0.5 * sigma * sigma) * T
d1 /= sigma * math.sqrt(T)

Explicit max(S, 1e-12) at the start of the function avoids ln⁡(0)\ln(0) crashes. Use math.log(S / K) instead of math.log(S) - math.log(K) if you care about monotonicity in KK.

Near expiry. As T→0T \to 0, the formula approaches max⁡(S−Ke−rT,0)\max(S - K e^{-rT}, 0), but floating-point division can produce nonsense. Most production code guards with T<some threshold (1e-6)T < \text{some threshold (1e-6)} and returns intrinsic.

Far OTM puts or calls. For deep OTM options, N(d1)N(d_1) and N(d2)N(d_2) are tiny. Their difference can lose 6-7 digits of precision. Use log-space implementations:

log⁡N(−d)≈−d2/2−log⁡(d2π) for large d\log N(-d) \approx -d^2/2 - \log(d\sqrt{2\pi}) \text{ for large } d

Standard libraries like scipy handle this internally, but if you’re writing your own normal CDF from scratch, check the tail behavior against scipy.

A Useful Cross-Check: Put-Call Parity

For European options on the same underlying with the same KK and TT:

C−P=S−Ke−rTC - P = S - K e^{-rT}

The right-hand side doesn’t depend on volatility. This is a non-trivial fact. If your code produces prices with C−PC - P depending on σ\sigma, something is wrong.

For multiple strikes and the same TT, plot C(K)−P(K)C(K) - P(K) versus KK. It should be a linear function with slope −e−rT-e^{-rT} and intercept SS. A deviation from linearity is your visual diagnostic for a coding error.

A Brief Historical Note

In 1900, Louis Bachelier published Théorie de la Spéculation, a PhD thesis at the Sorbonne. It modeled the French bond market as Brownian motion, five years before Einstein’s famous paper on the same subject. Bachelier derived a formula for the price of options on French bonds. The Bachelier call formula is:

C=(S0−K) N ⁣(S0−KσT)+σT ϕ ⁣(S0−KσT)C = (S_0 - K)\, N\!\left(\frac{S_0 - K}{\sigma\sqrt{T}}\right) + \sigma\sqrt{T}\,\phi\!\left(\frac{S_0 - K}{\sigma\sqrt{T}}\right)

where ϕ(⋅)\phi(\cdot) is the standard normal PDF. Equivalently, with d=(S0−K)/(σT)d = (S_0 - K)/(\sigma\sqrt{T}):

C=(S0−K) N(d)+σT ϕ(d)C = (S_0 - K)\, N(d) + \sigma\sqrt{T}\, \phi(d)

The first term is the intrinsic-value-weighted moneyness probability; the second is the diffusion term that captures expected additional movement in the underlying between today and expiry. Without that diffusion term, the formula collapses to intrinsic value at expiry and produces nonsense. The credit is missing on every options textbook. Bachelier’s teacher Henri Poincaré was interested, but no one in finance picked it up.

Black and Scholes knew of Bachelier’s work. They improved it by using log-returns (which are stationary, not levels) and adding a discount factor. Merton’s contribution was to recognize that the result generalized to a much wider class of payoffs under no-arbitrage. Their trio won the 1997 Nobel Prize (Black having died in 1995).

The story is worth knowing because it’s the rare case where the academic version of a quantitative model came out after market practice. Bond traders and dealers were running option-like strategies on equities for decades before 1973. The CBOE opened in 1973 partly because the formula gave dealers a way to quote fair prices consistently.

What You Should Be Able to Derive From Scratch

After absorbing this article, you should be able to:

  1. From the replicating portfolio argument, derive the Black-Scholes PDE.
  2. Show the time-to-expiry direction in the heat equation transformation.
  3. Connect the PDE solution to the closed-form via the risk-neutral expectation.
  4. Verify the put-call parity and the relationship ΔC−ΔP=1\Delta_C - \Delta_P = 1.
  5. Justify the formula’s validity under the frictionless market assumption.

If you can’t do at least four of these on a scratch sheet, you should re-read the article before proceeding.

Why This Derivation Is the Right Place to Start

Every other model in this module, including local volatility, stochastic volatility, and jump-diffusion, is either a modification of the Black-Scholes PDE or a generalization of the risk-neutral pricing argument. The closed form is a special case of a broader class of results. Once you have the derivation above, later derivations look like variations on the same theme.

The main point is that the Black-Scholes formula is not a fact about markets. It is a logical consequence of a small set of assumptions: continuous trading, no transaction costs, no dividends, and a single risky asset following geometric Brownian motion. When people argue about whether the formula “is true,” they are usually arguing about whether those assumptions hold. They do not, and that is what the rest of this module addresses.

Reading list. Hull, Options, Futures, and Other Derivatives, 10th ed., Ch. 13-15 (2018). Wilmott, Paul Wilmott on Quantitative Finance, 2nd ed., Vol. 1, Ch. 5-8 (2007). Luenberger, Investment Science, 2nd ed., Ch. 12-14 (2013). Press et al., Numerical Recipes, 3rd ed., Ch. 20 (2007) for the PDE discretization that connects this to finite differences.