CONTENTS

Solution: Delta Hedging P&L Simulation

Simulation

import numpy as np from scipy.stats import norm def bs_call(S, K, T, r, sigma): if T <= 0: return np.maximum(S - K, 0) d1 = (np.log(S/K) + (r + 0.5*sigma**2)*T) / (sigma*np.sqrt(T)) d2 = d1 - sigma*np.sqrt(T) return S*norm.cdf(d1) - K*np.exp(-r*T)*norm.cdf(d2) def delta_call(S, K, T, r, sigma): if T <= 0: return 1.0 * (S > K) d1 = (np.log(S/K) + (r + 0.5*sigma**2)*T) / (sigma*np.sqrt(T)) return norm.cdf(d1) def simulate_hedge_pnl(M, N, S0, K, T, r, sigma, seed=0): rng = np.random.default_rng(seed) dt = T / N times = np.linspace(0, T, N + 1) # Simulate GBM paths Z = rng.standard_normal((M, N)) log_ret = (r - 0.5*sigma**2)*dt + sigma*np.sqrt(dt)*Z log_paths = np.hstack([np.zeros((M, 1)), np.cumsum(log_ret, axis=1)]) S_paths = S0 * np.exp(log_paths) # shape (M, N+1) # Initial option price and delta C0 = bs_call(S0, K, T, r, sigma) Delta0 = delta_call(S0, K, T, r, sigma) # At t=0: sell 1 call, buy Delta0 stock, cash = C0 - Delta0*S0 cash = C0 - Delta0*S0 * np.ones(M) shares = Delta0 * np.ones(M) for i in range(1, N + 1): tau = T - times[i] S_t = S_paths[:, i] # Accrue interest on cash from t_{i-1} to t_i cash *= np.exp(r*dt) # Update delta at new time new_delta = delta_call(S_t, K, tau, r, sigma) # Rebalance: buy/sell (new_delta - shares) at S_t cash -= (new_delta - shares) * S_t shares = new_delta # Close the option payoff S_T = S_paths[:, -1] payoff = np.maximum(S_T - K, 0) pnl = cash + shares*S_T - payoff return pnl # Part 2 S0, K, T, r, sigma = 100, 100, 0.5, 0.05, 0.2 for N in [10, 50, 250]: pnl = simulate_hedge_pnl(10_000, N, S0, K, T, r, sigma) print(f"N={N}: mean={pnl.mean():.4f}, std={pnl.std():.4f}") # N=10: mean=-0.0133, std=1.2893 # N=50: mean=-0.0027, std=0.5752 # N=250: mean=-0.0006, std=0.2566

Part 3 — Convergence

Theoretical scaling: std(P&L)1/N\text{std}(\text{P\&L}) \propto 1/\sqrt N.

Checking ratios: 1.29/0.582.241.29/0.58 \approx 2.24, should be 50/10=52.24\sqrt{50/10} = \sqrt 5 \approx 2.24. ✓ 0.58/0.262.240.58/0.26 \approx 2.24, should be 250/50=52.24\sqrt{250/50} = \sqrt 5 \approx 2.24. ✓

Part 4 — Residual P&L source: gamma

At each rebalancing, the first-order hedge catches ΔdS\Delta\,dS but misses 12Γ(dS)2\tfrac{1}{2}\Gamma(dS)^2. Over NN steps, the accumulated gamma-P&L has:

  • Expected value 0\approx 0 under Q\mathbb{Q} (this is what makes Black-Scholes work).
  • Standard deviation 1/N\propto 1/\sqrt N (the (dS)2(dS)^2 fluctuations scale as dtdt, and there are NN of them).
In continuous hedging (NN \to \infty), std0\text{std} \to 0 and hedging is perfect. Real-world discreteness (hedging hourly or daily, not continuously) leaves the hedger exposed to gamma risk — the second-order curvature.

Takeaways

  • Delta-hedged options have approximately zero expected P&L under Black-Scholes. The mean P&L 0\approx 0 for all NN — the option's premium is "paid" by expected hedging costs.
  • Residual P&L has standard deviation 1/N\sim 1/\sqrt N. The gamma risk shrinks as you rebalance more frequently; finer discretisation \Rightarrow closer to perfect replication.
  • Transaction costs break this. Real-world hedging has bid-ask spread and commissions; rebalancing more frequently quickly becomes expensive. The optimum balances gamma risk vs. transaction cost — a well-known "hedging bandwidth" problem.
  • Discrete-time delta hedging is the bridge between theory and practice. Black-Scholes is a continuous-time idealisation; this exercise demonstrates that the idealised zero-variance replication is a limit attained only in the NN \to \infty continuum.
Solution — Delta Hedging P&L Simulation | q4quant.studio