The first time you see the Black-Scholes derivation, one thing should bother you: the stock’s expected return vanishes. You start with a stock you believe will return 12% a year, you turn the crank, and the answer depends on the risk-free rate instead. Your view on the stock — the thing you’d think matters most — never appears in the price.

Most courses wave at this and move on. “We work under the risk-neutral measure.” Fine, but why is there a second measure at all, and what happened to the first one? This post answers that without a single sigma-algebra. By the end you’ll have priced the same option twice — once under each measure — and watched them agree to the fourth decimal.

The puzzle, stated properly

Two traders look at the same stock. One is bullish and expects 12% a year. The other is bearish and expects 3%. They disagree completely about where the stock is going.

They will still quote the same price for a European call on it.

That sounds wrong. If I think the stock is going up more than you do, surely I should pay more for the right to buy it? And yet if you quote a different call price from mine, one of us can be arbitraged by the other. The market does not care about our forecasts.

The resolution is the whole subject in one line: an option’s price is not set by where the stock is expected to go. It’s set by what it costs to hedge it.

Why your forecast can’t be in the price

Here’s the argument that kills the drift, and it’s worth doing slowly because everything else follows from it.

Suppose I sell you a call and immediately start delta-hedging: I hold \Delta shares, rebalancing as the stock moves. If I hedge continuously and the stock follows the dynamics we assumed, my hedged position has no exposure to the stock’s direction at all. Whatever happens, the payoff I owe you is covered by the portfolio I built.

So what did the option cost me? Exactly what it cost me to run that hedge — nothing more. And the cost of running the hedge depends on the stock’s volatility (how much I have to rebalance) and the financing rate (what I pay to hold shares), not on where the stock ends up.

That’s why \mu disappears. It isn’t a trick or a modelling convenience. It’s the mathematical shadow of the fact that a hedged book doesn’t care about direction.

Two measures, one reality

Now the part that trips people up. We say there are two probability measures:

  • P — the real-world (or “physical”) measure. What you actually believe. The stock drifts at \mu.
  • Q — the risk-neutral measure. An artificial re-weighting under which the stock drifts at r.

The critical thing, and the source of most confusion: Q is not a forecast. Nobody believes the stock will return the risk-free rate. Q is a computational device — a way of re-weighting outcomes so that the discounted price of every tradeable asset becomes a fair game.

Think of it like betting odds. A bookmaker’s odds on a horse are not the bookmaker’s honest probability that the horse wins. They’re the numbers that make the book balance. Same idea: Q contains the probabilities that make hedging costs come out right, not the probabilities you’d bet on.

What “fair game” means, concretely

Here’s the defining property of Q, and you can check it numerically in ten lines.

Under Q, the discounted stock price is a martingale — its expected future value, discounted back, equals today’s price:

    \[\mathbb{E}^{\mathbb{Q}} \left[ e^{-rT} S_T \right] = S_0\]

Under P, this fails, because the stock is expected to beat the risk-free rate. Let’s see both:

import numpy as np

S0, r, sigma, T = 100.0, 0.05, 0.20, 1.0
mu = 0.12          # what we actually believe
n_sims = 1_000_000

np.random.seed(0)
Z = np.random.standard_normal(n_sims)

# Discounted stock under P (drift = mu)
ST_P = S0 * np.exp((mu - 0.5*sigma**2)*T + sigma*np.sqrt(T)*Z)
disc_P = np.exp(-r*T) * ST_P

# Discounted stock under Q (drift = r)
ST_Q = S0 * np.exp((r - 0.5*sigma**2)*T + sigma*np.sqrt(T)*Z)
disc_Q = np.exp(-r*T) * ST_Q

print(f"S0             = {S0:.4f}")
print(f"E_P[e^-rT S_T] = {disc_P.mean():.4f}")
print(f"E_Q[e^-rT S_T] = {disc_Q.mean():.4f}")

Which gives:

S0             = 100.0000
E_P[e^-rT S_T] = 107.2827
E_Q[e^-rT S_T] = 100.0298

Under P, the discounted stock drifts up — you expect to make money holding it, which is exactly why you hold it. Under Q, it sits still. That is the entire content of “risk-neutral”: a measure under which holding risk earns you nothing extra, so discounted prices don’t drift.

Changing measure is re-weighting, not rewriting

Here’s the mental model that makes Girsanov obvious.

You do not throw away the real-world scenarios and generate new ones. The set of possible paths is identical under P and Q. What changes is how much each path counts.

Paths where the stock does well get down-weighted. Paths where it does badly get up-weighted. Do this by exactly the right amount and the drift shifts from \mu to r — without a single new path being drawn.

The weight attached to each path is called the Radon-Nikodym derivative, written dQ/dP. For our lognormal stock it takes a specific and rather friendly form:

    \[L = \exp \left( -\theta W_T - \frac{1}{2}\theta^2 T \right), \quad \theta = \frac{\mu - r}{\sigma}\]

That \theta has a name worth remembering: the market price of risk. It’s the excess return per unit of volatility — how much extra you’re compensated for carrying one unit of risk. Notice what it does: if \mu = r (the stock is already expected to earn the risk-free rate), then \theta = 0, L = 1, and nothing gets re-weighted. P and Q are already the same measure. The re-weighting is precisely the size of the risk premium you’re stripping out.

Pricing the same option twice

Now the payoff for all that setup. We’ll price a European call two ways:

  1. Simulate under Q (drift r), average the payoff — the standard approach.
  2. Simulate under P (drift \mu = 12\%), then re-weight each path by L.

If the theory holds, these must agree — and both must match Black-Scholes.

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.12
n_sims = 1_000_000

np.random.seed(42)
Z = np.random.standard_normal(n_sims)

# --- Path A: simulate under Q, average the payoff ---
ST_Q = S0 * np.exp((r - 0.5*sigma**2)*T + sigma*np.sqrt(T)*Z)
price_Q = np.exp(-r*T) * np.maximum(ST_Q - K, 0.0).mean()

# --- Path B: simulate under P, then reweight ---
ST_P = S0 * np.exp((mu - 0.5*sigma**2)*T + sigma*np.sqrt(T)*Z)

theta = (mu - r) / sigma                  # market price of risk
W_T   = np.sqrt(T) * Z                    # the Brownian increment
L     = np.exp(-theta*W_T - 0.5*theta**2*T)   # dQ/dP

price_P = np.exp(-r*T) * (L * np.maximum(ST_P - K, 0.0)).mean()

# --- Benchmark ---
d1 = (np.log(S0/K) + (r + 0.5*sigma**2)*T) / (sigma*np.sqrt(T))
d2 = d1 - sigma*np.sqrt(T)
bs = S0*norm.cdf(d1) - K*np.exp(-r*T)*norm.cdf(d2)

print(f"Simulated under Q:             {price_Q:.4f}")
print(f"Simulated under P, reweighted: {price_P:.4f}")
print(f"Black-Scholes:                 {bs:.4f}")
print(f"Mean of L (should be 1):       {L.mean():.4f}")

Output:

Simulated under Q:             10.4342
Simulated under P, reweighted: 10.4379
Black-Scholes:                 10.4506
Mean of L (should be 1):       1.0006

Both routes land on the closed form. We simulated a stock we believe returns 12% a year, and by re-weighting the paths we recovered exactly the price of a stock drifting at 5%. The bullish view went in and came out the other side without touching the price.

That last line is the sanity check worth internalising: \mathbb{E}^{\mathbb{P}}[L] = 1. The weights redistribute probability mass — they don’t create or destroy it. If your L doesn’t average to 1, your change of measure is broken and every price built on it is wrong.

What Girsanov actually says

With the above in hand, the theorem is almost anticlimactic. Girsanov says: re-weight by that L, and the process

    \[W_t^{\mathbb{Q}} = W_t^{\mathbb{P}} + \theta t\]

is a standard Brownian motion under the new measure. Adding a deterministic drift to a Brownian motion and re-weighting appropriately gives you back a driftless Brownian motion.

Substitute that into the stock’s dynamics and the \mu collapses into r. That’s it. That’s the whole move.

There is fine print — the re-weighting has to be legitimate, which is what conditions like Novikov are for, and they matter more than they look when \theta is itself stochastic. But the mechanism is the one you just ran in twenty lines.

Where this bites in practice

This isn’t decoration. Getting the measure wrong is a live source of errors on a desk:

  • Risk lives under P, pricing lives under Q. Your VaR and your expected exposure are real-world questions — they ask what will actually happen. Your marks are Q questions. Mixing them up produces numbers that are confidently meaningless.
  • Change the numeraire, change the measure. Discounting by a T-bond instead of the money-market account gives you the forward measure, and drifts shift accordingly. Half the tricks in rates pricing are choosing the numeraire that makes an awkward drift vanish.
  • Calibrated parameters are Q parameters. The volatility you back out from option prices is not the volatility you’d estimate from a return series. They answer different questions. Feeding one into the other’s model is a classic way to be wrong.
  • Default intensities too. The hazard rate implied by CDS spreads is a Q intensity — it embeds a risk premium. It is systematically higher than the historical default rate, and treating it as a forecast will badly overstate expected losses.

The one-line summary

The real-world drift doesn’t matter for pricing because a hedged position doesn’t care about direction. Q is the re-weighting that makes that fact arithmetic: under it, discounted tradeables are fair games, so today’s price is just a discounted expectation. You keep the same paths — you change what they’re worth.

If you want to see this built rather than described — replication and no-arbitrage first, then the measure change, then a validated pricer with error bars and a full test suite — that’s the spine of Risk-Neutral Valuation, worked line by line.

In the meantime: take the code above, change \mu to something absurd — 50%, or negative — and watch the price refuse to move. That stubbornness is the whole idea.


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.