Skip to content
Sarthak Bagaria
All notes

Chapter 5 Black Scholes

In these notes we price a European option, and pay attention to which parts of the argument are doing work. The asset’s expected return disappears, and it disappears for a reason the lemma below makes precise. The formula’s two terms turn out to be the same probability measured under two different numeraires, which is visible in the derivation as a completed square before chapter 6 gives it a name. We then read the equation for what it says about a hedged position — that theta and gamma are one quantity seen twice — and collect the approximations a trader carries in place of the formula.

5.1 Black Scholes Option Pricing

Definition 5.1 (Black-Scholes market).

The Black-Scholes market has a constant risk-free rate r, so that the discount factor is Dt=ert, and one traded asset following a geometric Brownian motion,

dStSt=μdt+σdWt, (5.1)

with σ constant.

Lemma 5.2 (The drift is not a parameter).

Under the risk-neutral measure of chapter 4, μ=r.

Proof.

That measure is characterised by DtSt being a martingale, so its drift vanishes. By Itô’s product rule, using dDt=rDtdt and that D has no diffusion term,

d(DtSt)=rDtStdt+Dt(μStdt+σStdWt)=(μr)DtStdt+σDtStdWt,

and the drift is zero for all t only if μ=r. ∎

So the asset’s expected return, the one quantity a reader might expect to matter most, does not appear in any price. Chapter 6 explains what has happened: changing measure moves drifts and cannot touch volatilities, so μ was never an observable of the option in the first place. Under the risk-neutral measure (5.1) integrates to

ST=Stexp((r12σ2)τ+στZ),τ=Tt,ZN(0,1). (5.2)
Theorem 5.3 (Black and Scholes).

In the market of definition 5.1, a European call struck at K and expiring at T is worth

Vt=StN(d1)KerτN(d2), (5.3)

where N is the standard normal distribution function and

d1,2=1στ[lnStK+(r±12σ2)τ],so thatd1=d2+στ. (5.4)
Proof.

Since DtVt is a martingale, Vt=erτ𝔼[(STK)+|t]. Substituting (5.2), the option finishes in the money exactly when

Z>1στ[lnKSt(r12σ2)τ]=d2,

so with φ the standard normal density the expectation splits into two integrals over the same region:

Vt=Std2e12σ2τ+στzφ(z)𝑑zthe asset legKerτd2φ(z)𝑑zthe cash leg. (5.5)

The cash leg is immediate: d2φ=N(d2) by the symmetry of φ.

The asset leg needs one manipulation. Collect the exponentials and complete the square:

e12σ2τ+στzφ(z)=12πexp(12σ2τ+στz12z2)=12πexp(12(zστ)2)=φ(zστ).

The integrand is a normal density again, shifted by στ. Substituting y=zστ moves the limit with it,

d2φ(zστ)𝑑z=d2στφ(y)𝑑y=N(d2+στ)=N(d1)

by symmetry and (5.4), which is (5.3). ∎

Structure (Completing the square is a change of measure).

What happened is that a density multiplied by an exponential in its own variable came back as the same density about a different centre. That is exactly a Girsanov shift: multiplying by eστzσ2τ/2 — which is a mean-one positive random variable, so a legitimate Radon-Nikodym derivative — is changing measure, and under the new measure Z has mean στ instead of zero.

So (5.5) is not one expectation but two, taken under two different measures. The cash leg is priced in units of the money market account and N(d2) is the probability of exercise there. The asset leg is priced in units of the asset itself, and N(d1) is the probability of exercise under that measure. The two normal distribution functions are the same event — the option finishing in the money — measured by two different numeraires, which is why they differ by precisely the volatility term στ that separates d1 from d2. Chapter 6 derives the formula that way from the start and draws the two probabilities against each other; here the shift arrives unbidden, out of completing a square.

Formula (5.3) is a smooth function of the spot at every positive maturity, and the payoff it is a price for is not smooth at all. The two have to meet, since an option a moment before expiry is worth what it is about to pay, and watching them meet is the most direct account of what the extra value is.

60708090100110120130140010203040SpotValue of a call struck at 100
  • 2.00 years
  • payoff at expiry
6070809010011012013014000.20.40.60.81SpotDelta
6070809010011012013014000.050.10.150.2SpotGamma
60708090100110120130140102030405060SpotVega
2.00 years

A call struck at 100, at 20% volatility and zero rates. Drag towards expiry: the value falls onto the payoff and its kink appears, delta stiffens from a slope into a step, gamma concentrates over the strike while growing without bound, and vega — the whole value of being uncertain — goes to zero everywhere at once.

Figure 5.1: A call struck at 100 at twenty percent volatility and zero rates, with its first three sensitivities, all drawn at one maturity at a time. As expiry approaches the value falls onto (SK)+ and the curve above the payoff — the whole of the option’s time value — is squeezed out of it. The derivatives say the same thing more sharply. Delta stiffens from a slope into the step that a forward would have, so a long dated option hedges like a fraction of the stock and a short dated one like all or none of it. Gamma concentrates over the strike and grows without bound, which is why the axis has to be pinned to see anything at all. And vega goes to zero everywhere at once: with no time left there is nothing for volatility to act on, so nothing to be uncertain about and nothing to pay for.
Show the model behind this figure (1 function)
/// Price and sensitivities together, because they share `d1` and `d2` and
/// because a risk report wants all of them at once.
///
/// At zero time or zero volatility the option is worth its intrinsic value and
/// the sensitivities are the derivatives of that: delta is a step, gamma is
/// unbounded at the strike and zero elsewhere, and vega and theta vanish. The
/// step's value exactly at the strike is a convention --- the derivative does
/// not exist there --- and `0.5` is chosen because it is the limit approached
/// from either side of a symmetric perturbation.
pub fn greeks(s: f64, k: f64, sigma: f64, t: f64, r: f64, q: f64, side: Side) -> Greeks {
    let w = side.sign();
    let v = sigma * t.sqrt();
    let price = black_scholes(s, k, sigma, t, r, q, side);

    if v <= 0.0 || s <= 0.0 || k <= 0.0 {
        let in_the_money = w * (s - k);
        let delta = if in_the_money > 0.0 {
            w
        } else if in_the_money < 0.0 {
            0.0
        } else {
            0.5 * w
        };
        let gamma = if s == k { f64::INFINITY } else { 0.0 };
        return Greeks { price, delta, gamma, vega: 0.0, theta: 0.0 };
    }

    let df_r = (-r * t).exp();
    let df_q = (-q * t).exp();
    let f = s * ((r - q) * t).exp();
    let d1 = ((f / k).ln() + 0.5 * v * v) / v;
    let d2 = d1 - v;
    let n_d1 = norm_pdf(d1);

    Greeks {
        price,
        delta: w * df_q * norm_cdf(w * d1),
        gamma: df_q * n_d1 / (s * v),
        vega: s * df_q * n_d1 * t.sqrt(),
        // d/dt, hence the leading minus on the decay term.
        theta: -s * df_q * n_d1 * sigma / (2.0 * t.sqrt())
            - w * r * k * df_r * norm_cdf(w * d2)
            + w * q * s * df_q * norm_cdf(w * d1),
    }
}

Three things in that picture stand out, each a fact about options rather than about this formula. The kink in the payoff is the same non-smooth point that made the generator of chapter 3 awkward, and the diffusion is what smooths it — time to expiry and volatility enter only through στ, so shortening the maturity and lowering the volatility do the identical thing to the picture. Gamma growing without bound as vega vanishes is not a paradox but the same statement twice, and Theta Is Gamma below makes the relation exact. And a delta that approaches a step is a warning: it is the derivative of a function converging to one that has no derivative at the strike, which is where hedging a short dated option near its strike becomes genuinely hard rather than merely expensive.

5.2 What the Model Was Not Needed For

Theorem 5.4 (Put-call parity).

Let C and P be the prices of a European call and put on the same underlying, with the same strike K and the same expiry T. Then in any market without arbitrage,

CP=P(0,T)(FK), (5.6)

with F the forward price to T and P(0,T) the discount factor. Under the assumptions of this chapter, where the underlying pays nothing and rates are constant, F=S0erT and (5.6) reads CP=S0KerT.

Proof.

At expiry, for every value of ST,

(STK)+(KST)+=STK,

since exactly one of the two options finishes in the money and the other is worth nothing. So a long call and a short put have, in every state, the payoff of a forward struck at K. Two portfolios with identical payoffs in every state have identical prices, by the no-arbitrage argument of chapter 4, and the forward struck at K is worth P(0,T)(FK). ∎

Remark (Read what is absent).

The proof used no model. It did not ask how S gets to ST, whether the path is continuous, what the volatility is, or whether one exists. It is an identity between payoffs, and it therefore survives every criticism made of the Black-Scholes model in the chapters that follow — jumps, stochastic volatility, a smile, all of it. (5.6) holds in a market with any of those, because it never had an opinion about them.

This is the same distinction chapter 15 will build a whole chapter on. Some prices are fixed by static replication, and for those a model can only add an assumption to information that was already complete. Others are not, and those are what a model is for. Knowing which is which is most of knowing when to trust one.

Remark (Three things it is used for).
  • -

    A call and a put at the same strike have the same implied volatility. Since (5.6) holds for market prices and, being a model, also for Black-Scholes prices at any volatility, subtracting the two shows the volatility that reprices the call reprices the put. This is why chapter 9 can speak of the smile as a function of strike alone, rather than of strike and option type, and why a desk may quote whichever of the pair is out of the money and let parity supply the other.

  • -

    The forward can be read out of option prices. Rearranging, F=K+(CP)/P(0,T). The option market therefore carries its own opinion about the forward, and it need not agree with the one computed from a curve. Where they differ the difference is a borrow cost, a dividend assumption, or a stale quote.

  • -

    It is the first thing to check in an implementation. A pricer that violates parity is wrong in a way that needs no market data to detect, and the check costs one line. Both black76 and Model::price are tested against it.

Remark (When it appears to fail).

Quoted prices routinely violate (5.6) on a screen, and the violation is almost never an arbitrage. It is the forward: an equity with an uncertain dividend, a stock that is expensive to borrow, or a pair of quotes that were not observed at the same instant.

The right reading is that (5.6) has three market inputs and the least reliable of them is F. So rather than concluding the market is mispriced, one solves for the F that makes parity hold and asks whether that number is plausible. Used this way the relation is not a test the market can fail; it is a measuring instrument.

Exercise.

Verify that the formula derived above satisfies (5.6), using N(x)=1N(x) on both terms. Then deduce, without any further calculation, that the put’s delta is N(d1)1 and that a call and a put at the same strike have the same gamma and the same vega. (Hint: differentiate (5.6); the right hand side has no volatility in it, and its derivative in S0 is one.)

5.3 The Option’s Own Diffusion

The derivation above computed an expectation. There is a second route to the same answer that says more about what the option is, and it starts by asking what process the option price itself follows.

The option is worth V(t,St), a function of time and of a diffusion, and chapter 3 already says what the drift of such a thing is. Writing for the generator of the stock,

dV=(Vt+V)dt+σSVSdWt,

the extra V/t appearing because V depends on time directly as well as through S. So the option is itself an Itô diffusion, driven by the same Brownian motion as the stock — which is chapter 4’s replication argument appearing as a statement about coefficients rather than about portfolios.

Now impose no arbitrage. The option is a tradable, so by chapter 4 its discounted price is a martingale in the risk neutral measure, which is to say its drift is rV:

Vt+V=rV. (5.7)

That is the Black-Scholes equation, and how little was needed to get here deserves a pause: the drift of a function of a diffusion, and the statement that a traded thing drifts at the riskless rate. Written out, with the generator under the risk neutral dynamics,

Vt+rSVS+12σ2S22VS2=rV. (5.8)
Structure (The same equation for every model in these notes).

Equation (5.7) contains nothing specific to Black-Scholes. Substituting a different generator gives the pricing equation of a different model, and that is the only step: local volatility in chapter 9, the short rate models of chapter 8, the quasi-Gaussian models of chapter 12 all satisfy (5.7) with their own .

So none of those chapters derives a pricing equation again. They specify a generator, which is what specifying a model means.

This is the Black-Scholes partial differential equation, and the correspondence just used — that the expectation of a payoff under a diffusion solves a PDE of this shape, and conversely — is the Feynman-Kac theorem. It is the bridge the whole subject walks back and forth across: an expectation is something to simulate, a PDE is something to solve on a grid, and Feynman-Kac says they are the same object seen from two sides. Chapter 9’s Dupire formula is derived from the forward version of the same correspondence.

5.4 Theta Is Gamma

Equation (5.8) looks like a technical detour until it is read as a statement about a trading position, at which point it becomes the most useful thing in this chapter.

Take r=0, which costs nothing and removes the financing terms. Writing Θ=V/t and Γ=2V/S2 in the trader’s notation, (5.8) reduces to

Θ=12σ2S2Γ. (5.9)

These are not two independent quantities that happen to be related. They are the same number, with a sign. A position with positive gamma has negative theta, in exact proportion, and the constant of proportionality is the variance.

To see why that matters, hold the option, hedge it, and account for a single day.

Calculation 5.5 (The daily profit and loss of a hedged option).

Hold one option and short Δ shares. Over a short interval, expanding the option’s value to second order,

dΠ =dVΔdS
=(Θdt+ΔdS+12Γ(dS)2)ΔdS
=Θdt+12Γ(dS)2,

the first-order terms cancelling, which is what the hedge was for. Substituting (5.9),

dΠ=12ΓS2[(dSS)2σ2dt]. (5.10)

Read the bracket. The first term is the move the market actually made, squared. The second is the move the option was priced for. A hedged option earns the difference between them, scaled by gamma.

So an option is not a bet on direction — the hedge removed that — and it is not really a bet on volatility either. It is a bet on realised variance against implied variance, settled a day at a time. Buy an option, hedge it, and you make money on every day the market moves more than the price assumed and lose on every day it moves less.

Remark (What the premium is).

Equation (5.10) also closes a question the replication argument of chapter 4 left open. Rebalancing a hedge buys after a rise and sells after a fall, which loses money on every round trip; that loss is the 12Γ(dS)2 term, and its expected size over the life of the option is

𝔼[0T12ΓS2σ2𝑑t],

which by (5.9) is exactly the accumulated theta — that is, the premium. The option premium is not a fee for optionality in the abstract. It is the amount the seller expects to lose rehedging, paid up front.

Which is also why the seller cares about the frequency of large moves rather than only their variance. The premium compensates for the average of (dS)2 and for nothing else, so a distribution with the same average and fatter tails hands over the same premium against a worse experience — and since that is a claim about two distributions rather than about one model, the next calculation shows both.

Calculation 5.6 (The same premium, two worlds).

Sell the same one year at-the-money call in two markets whose total variance is identical, so the Black-Scholes price is identical and the seller takes in the same 7.97 either way. In the first all of that variance is diffusive. In the second half of it arrives as compensated jumps at a rate of two a year. Hedge both two hundred and fifty times at the same Black-Scholes delta.111pathwise::hedge_under_jumps.

All diffusion Half in jumps
Mean profit and loss 0.00 +0.12
Standard deviation 0.44 2.70
Worst one per cent, averaged 1.50 12.54
Worst outcome seen 4.31 32.86
Fraction of paths that made money 49.9% 63.8%

The premium was fair in both — the mean is zero to within the simulation error, which is what (5.10) guarantees once the variance is matched. Everything else differs. The tail is eight times worse, and the position wins more often: a seller in the jump world is right on nearly two thirds of paths and loses thirty-three on the one that goes wrong.

20406080-12-10-8-6-4-2024Percentile of outcomesHedged profit and loss
  • all diffusion
  • half the variance in jumps
Figure 5.2: Hedged profit and loss at each percentile, selling the same option for the same premium into two markets with the same total variance. The diffusive curve is nearly flat — almost every outcome is close to zero, which is what a working hedge looks like. The jump curve is above it across most of the range and falls off a cliff at the left. Same average of (dS)2, same price, and an entirely different thing to live through, which is why a seller cares about the shape of the distribution and not only its second moment.
Show the model behind this figure (1 function)
hedge_under_jumpsquant/src/pathwise.rs
/// Hedge a short call under a jump diffusion whose total variance is `sigma^2`.
///
/// `jump_share` is the fraction of the variance carried by the jumps, so zero
/// recovers ordinary geometric Brownian motion and the two cases run through one
/// piece of code. Jumps are lognormal with zero mean return and are compensated,
/// so the underlying stays a martingale and the comparison is not confounded by
/// a drift.
pub fn hedge_under_jumps(
    s0: f64,
    k: f64,
    sigma: f64,
    t: f64,
    jump_share: f64,
    lambda: f64,
    steps: usize,
    paths: usize,
    seed: u64,
) -> HedgeShape {
    let premium = black76(s0, k, sigma, t, Side::Call);
    let dt = t / steps as f64;

    // Split the variance. A jump has lognormal return exp(y) - 1 with y centred
    // so that E[exp(y)] = 1; its second moment is then exp(nu^2) - 1, and
    // matching lambda (exp(nu^2) - 1) to the jump share of the variance fixes
    // nu.
    let jump_variance = sigma * sigma * jump_share;
    let diffusive = (sigma * sigma - jump_variance).sqrt();
    let nu = if jump_share > 0.0 {
        (1.0 + jump_variance / lambda).ln().sqrt()
    } else {
        0.0
    };

    let mut rng = Rng::new(seed);
    let mut results = Vec::with_capacity(paths);

    for _ in 0..paths {
        let mut s = s0;
        let mut hedge_pnl = 0.0;

        for i in 0..steps {
            let remaining = t - i as f64 * dt;
            let delta = call_delta(s, k, sigma, remaining);

            // Diffusive step, compensated for the jump drift so the whole thing
            // is a martingale.
            let z = rng.next_normal();
            let mut next = s
                * ((-0.5 * diffusive * diffusive) * dt + diffusive * dt.sqrt() * z).exp();

            // At most one jump per step, which is the standard thinning and is
            // accurate when lambda * dt is small.
            if jump_share > 0.0 && rng.next_uniform() < lambda * dt {
                let y = -0.5 * nu * nu + nu * rng.next_normal();
                next *= y.exp();
            }

            hedge_pnl += delta * (next - s);
            s = next;
        }

        results.push(premium + hedge_pnl - (s - k).max(0.0));
    }

    results.sort_by(|a, b| a.partial_cmp(b).unwrap());
    let n = results.len();
    let mean = results.iter().sum::<f64>() / n as f64;
    let var = results.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / n as f64;
    let tail = (n / 100).max(1);

    // One point per half per cent, which is enough to show the tail without
    // carrying forty thousand numbers into a chart.
    let quantiles = (1..200)
        .map(|i| {
            let q = i as f64 / 200.0;
            (q, results[((q * n as f64) as usize).min(n - 1)])
        })
        .collect();

    HedgeShape {
        mean,
        sd: var.sqrt(),
        expected_shortfall: results[..tail].iter().sum::<f64>() / tail as f64,
        worst: results[0],
        win_rate: results.iter().filter(|x| **x > 0.0).count() as f64 / n as f64,
        quantiles,
    }
}
Remark (What that pattern is).

The last row is the one to remember, because the shape it describes recurs throughout these notes. A position that makes a little money most of the time and loses a great deal rarely is not a good position that occasionally has bad luck; it is a short option, whether or not anybody wrote one down. Chapter 22 finds the same profile in six trades that have nothing else in common, and chapter 24 is about measuring it, since a mean and a standard deviation describe the left column adequately and the right column not at all.

5.5 Numbers Carried in the Head

The formula of §5.1 is not something anyone evaluates mentally, and traders do not try. What they carry instead is a handful of approximations, all of which come from the same place: at the money, the normal density is flat near zero, so N(x)12+n(0)x with n(0)=1/2π0.4.

Calculation 5.7 (The at-the-money option price).

With r=q=0 and K=F, we have d1,2=±12σT, so

C =F[N(d1)N(d2)]
F[(12+n(0)σT2)(12n(0)σT2)]
=Fn(0)σT 0.4FσT.

The error is under half a percent for ordinary parameters and only reaches one percent at volatilities above fifty. Differentiating the same expression in σ gives the vega, and the rest follow:

at-the-money price 0.4FσT
vega 0.4FT per unit of volatility
delta about 12
gamma 0.4/(FσT)
daily break-even move σ/252σ/16

The last line is the one used most. Since 252=15.87, a volatility quoted annually divides by roughly sixteen to give the daily move it implies. Twenty vol is a one and a quarter percent day; thirty-two vol is a two percent day. By (5.10) that is exactly the break-even: a day that moves less than σ/16 loses money for the holder of a hedged option, and a day that moves more makes it.

Example 5.1 (A trade, decided in one’s head).

An index is at 4,000 and its three month at-the-money options are quoted at 16 volatility. Then

  • -

    the option costs about 0.4×4,000×0.16×0.25=128 index points, a little over three percent of spot;

  • -

    its vega is about 0.4×4,000×0.5=800 points per unit of volatility, so eight points per volatility point;

  • -

    and it breaks even on a daily move of 16/16=1%, which is 40 points.

So the decision to buy it is a view that the index will move more than forty points a day, on average, over the next three months — which is a question about the world rather than about the model, and can be answered from a chart. The whole apparatus of this chapter has been reduced to a comparison a trader can make between two sentences of a phone call.

5.6 Why the Formula Is a Price

We wrote down a payoff, took an expectation under a particular measure, and called the answer a price. Why should anyone pay it?

The answer is the argument of chapter 4, carried into continuous time: because the option can be manufactured. If holding Δt shares and adjusting continuously reproduces the payoff exactly, then the option and that strategy are the same object, and two things that pay identically must cost identically or there is an arbitrage. The formula is not a forecast of what the option will be worth. It is the cost of building one.

Two features of the result follow from this, and both surprise people meeting them for the first time.

Remark (The drift is absent, and that is the point).

The real world drift μ appears nowhere in the formula. Two investors who disagree completely about whether the stock will rise must still agree on the option’s price — because neither of them is being asked to forecast anything. They are being asked what it costs to build a payoff, and the hedge removes the drift from the answer just as it removes it from the portfolio.

This is the continuous time version of the observation in chapter 4 that the historic probabilities did not appear in the binomial price. It is the same fact, and it has the same cause.

Remark (Continuously is not a word about the world).

Replication is exact only if the position is adjusted continuously, and nobody does that. Real hedging happens at discrete times, so real replication is imperfect, and the difference is a genuine risk carried by anyone who sells an option.

How imperfect, and in what way, is a question the formula cannot answer but a simulation can.

234567891000.511.522.53Rebalances over the option's life (log₂)Standard deviation of the hedging error
  • Hedging error
  • Proportional to 1/√n
-4-2024-14-12-10-8-6-4-20Profit and loss at expiry, in standard deviationsLog density
  • symmetric reference
  • 8 rebalances
  • 128 rebalances
Figure 5.3: Selling a one year at-the-money call for its Black-Scholes price and hedging it n times before expiry. Above: the spread of the outcomes falls in proportion to 1/n — the reference curve is anchored at the coarsest point rather than fitted, so its agreement further along is a prediction. Below: the shape of the profit and loss, standardised so that only the shape is being compared, and drawn against a symmetric reference on a log scale — the asymmetry lives in the last tenth of a per cent, where a linear density is visually zero. At eight rebalances the left arm reaches five standard deviations while the right stops at three; by a hundred and twenty-eight the two are close to level again, which says the skew is the cost of trading discretely rather than a permanent feature of the position.
Show the model behind this figure (2 functions)
/// Sell a call, hedge it `steps` times, and see what is left.
///
/// The strategy is the one the no-arbitrage chapter's replication argument describes: hold
/// `delta` shares, funded from the premium, and adjust at each rebalancing date.
/// With zero rates the accounting is a single sum — the premium taken in, plus
/// the gains on the shares held over each interval, less the payoff owed.
///
/// `drift` is the *real world* drift of the stock, and it is a parameter on
/// purpose. The Black-Scholes price does not contain it, which is the single
/// most surprising claim in the no-arbitrage chapter, and the way to see that
/// the claim is true rather than merely derived is to change the drift and
/// watch the hedged result not move.
pub fn delta_hedge(
    s0: f64,
    k: f64,
    sigma: f64,
    t: f64,
    drift: f64,
    steps: usize,
    seed: u64,
) -> HedgeResult {
    let premium = black76(s0, k, sigma, t, Side::Call);
    let dt = t / steps as f64;
    let mut rng = Rng::new(seed);

    let mut s = s0;
    let mut hedge_pnl = 0.0;

    for i in 0..steps {
        let remaining = t - i as f64 * dt;
        let delta = call_delta(s, k, sigma, remaining);

        // One step of geometric Brownian motion, exactly rather than by Euler:
        // the discretisation error being measured is the hedging error, and it
        // would be contaminated by an approximation to the path itself.
        let z = rng.next_normal();
        let next = s * ((drift - 0.5 * sigma * sigma) * dt + sigma * dt.sqrt() * z).exp();

        hedge_pnl += delta * (next - s);
        s = next;
    }

    let payoff = (s - k).max(0.0);
    HedgeResult {
        pnl: premium + hedge_pnl - payoff,
        unhedged_pnl: premium - payoff,
    }
}
hedge_statisticsquant/src/pathwise.rs
/// Run many hedges and report the spread of the outcomes.
///
/// Returns the mean and the standard deviation of the profit and loss. The mean
/// says whether the premium was right; the standard deviation says how well the
/// hedge worked.
pub fn hedge_statistics(
    s0: f64,
    k: f64,
    sigma: f64,
    t: f64,
    drift: f64,
    steps: usize,
    paths: usize,
    seed: u64,
) -> (f64, f64) {
    let results: Vec<f64> = (0..paths)
        .map(|i| delta_hedge(s0, k, sigma, t, drift, steps, seed.wrapping_add(i as u64 * 7919)).pnl)
        .collect();
    let mean = results.iter().sum::<f64>() / paths as f64;
    let var = results.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / paths as f64;
    (mean, var.sqrt())
}

Read the two panels together, because they say different things.

The upper one is reassuring. The error does go to zero, and at the classical rate: quadruple the number of rebalances and the spread halves. Daily hedging of a one year option leaves a standard deviation of a few tenths of a percent of spot, against a premium of about eight percent. Replication is not a fiction.

The lower one is the warning, and it has to be read carefully, because the asymmetry is a property of the tail and not of the body. The mean is zero — the premium is right — and within one and a half standard deviations the two sides carry very nearly equal mass. The difference sits at the thousandth quantile. Hedging eight times, the worst outcomes reach four and a half standard deviations below the mean while the best stop short of three, against a symmetric reference that would go the same distance either way. That is why the panel is drawn on a log scale: on a linear one the region where the two sides differ is indistinguishable from zero.

So a desk that sells options and hedges them discretely collects a little most of the time and occasionally takes a large loss. But notice what else the panel shows, because it qualifies the warning: the asymmetry shrinks as the rebalancing gets finer, from a skewness of 0.42 at eight rebalances to 0.18 at a hundred and twenty-eight. This left tail is the price of trading discretely, and trading less discretely reduces it.

What does not shrink is the left tail of Calculation 5.6, because a jump is a jump however often the hedge is adjusted. The two are different warnings, and should be kept apart: this one is about how often you trade, that one about what the world does between your trades. Only the second is a reason to care about the frequency of large moves more than a formula containing only σ would suggest.

References

  • -

    Black, F., & Scholes, M. (1973). The pricing of options and corporate liabilities. Journal of Political Economy, 81(3), 637–654.

  • -

    Merton, R. C. (1973). Theory of rational option pricing. Bell Journal of Economics and Management Science, 4(1), 141–183.

  • -

    Karatzas, I., & Shreve, S. E. (1991). Brownian Motion and Stochastic Calculus, 2nd ed. Springer.