CONTENTS

Solution: Gamma P&L and Realised-vs-Implied Volatility

Simulation

import numpy as np from scipy.stats import norm def bs_call(S, K, T, r, sigma): if T <= 1e-10: 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 <= 1e-10: 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_gamma_scalping(M, N, S0, K, T, r, sigma_imp, sigma_R, seed=0): rng = np.random.default_rng(seed) dt = T / N Z = rng.standard_normal((M, N)) # Paths move with REALISED vol sigma_R under real-world drift r log_ret = (r - 0.5*sigma_R**2)*dt + sigma_R*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) # Buy 1 call at implied vol price C0 = bs_call(S0, K, T, r, sigma_imp) Delta0 = delta_call(S0, K, T, r, sigma_imp) cash = -C0 + Delta0*S0 * np.ones(M) # long call, short Delta shares shares = -Delta0 * np.ones(M) # negative = short shares to delta-hedge long call for i in range(1, N + 1): tau = T - i*dt S_t = S_paths[:, i] cash *= np.exp(r*dt) new_shares = -delta_call(S_t, K, tau, r, sigma_imp) cash -= (new_shares - shares) * S_t shares = new_shares S_T = S_paths[:, -1] payoff = np.maximum(S_T - K, 0) pnl = cash + shares*S_T + payoff return pnl S0, K, T, r = 100, 100, 0.5, 0.05 sigma_imp = 0.20 # Part 1: different realised vols for sigma_R in [0.15, 0.20, 0.30]: pnl = simulate_gamma_scalping(5_000, 500, S0, K, T, r, sigma_imp, sigma_R) print(f"sigma_R={sigma_R}: mean={pnl.mean():.4f}, std={pnl.std():.4f}") # sigma_R=0.15: mean=-1.4254, std=0.6830 (realised < implied: LOSS) # sigma_R=0.20: mean=-0.0037, std=0.3165 (equal: ~0 P&L) # sigma_R=0.30: mean=+2.8975, std=1.7344 (realised > implied: PROFIT)

Part 2 — Symmetric case (σR=σimp\sigma_R = \sigma_{\text{imp}})

Mean 0\approx 0: delta-hedging at the correct vol produces zero expected P&L.

Std 0.32\approx 0.32: residual P&L is non-zero due to discrete hedging — the 1/N1/\sqrt N hedging error. This is the irreducible "friction" of discrete time.

Part 3 — Expected profit at σR=0.30,σimp=0.20\sigma_R = 0.30, \sigma_{\text{imp}}=0.20

Theoretical gamma-scalping formula (using t=0t = 0 approximations):

E[P&L]12Γ0S02(σR2σimp2)T\mathbb{E}[\text{P\&L}] \approx \tfrac{1}{2}\Gamma_0 S_0^2 (\sigma_R^2 - \sigma_{\text{imp}}^2) T =0.50.02731002(0.3020.202)0.5=0.50.0273100000.050.53.41.= 0.5\cdot 0.0273\cdot 100^2\cdot (0.30^2 - 0.20^2)\cdot 0.5 = 0.5\cdot 0.0273\cdot 10000\cdot 0.05\cdot 0.5 \approx 3.41.

Simulated mean: 2.90\approx 2.90. Theoretical: 3.413.41. The simulation is lower because the formula uses t=0t = 0 gamma and spot; in reality, both change over the path (gamma drops for paths that move far from KK, rises for paths that stay near KK). A more refined estimate integrates ΓtSt2\Gamma_t S_t^2 along each path, which recovers the simulated value.

Takeaways

  • Long-gamma P&L tracks realised-minus-implied variance. When realised vol exceeds implied, delta-hedged long options make money; when realised is below implied, they lose. This is the fundamental P&L of a vol trader.
  • The formula E[P&L]12ΓS2(σR2σimp2)T\mathbb{E}[\text{P\&L}] \approx \tfrac{1}{2}\Gamma S^2(\sigma_R^2 - \sigma_{\text{imp}}^2)T is the workhorse for back-of-envelope vol-trading economics. It quantifies how much you can make from a correct volatility call.
  • Variance risk premium. Historically, implied vol has exceeded realised by ~3-5% — meaning that long-options strategies are expected to lose money on average, and short-options strategies (selling premium) are expected to profit. This is the "selling insurance" of the options market.
  • Discrete hedging error = O(1/N)O(1/\sqrt N). The simulation at σR=σimp\sigma_R = \sigma_{\text{imp}} confirms that std 1/N\propto 1/\sqrt N. Zero-expected-P&L is an asymptotic statement; any finite-NN hedge has residual noise.
Solution — Gamma P&L and Realised-vs-Implied Volatility | q4quant.studio