CONTENTS

Solution: Computing Delta for a Vanilla Call and Put

Computations

import numpy as np from scipy.stats import norm def bs_call(S, K, T, r, sigma, q=0): d1 = (np.log(S/K) + (r - q + 0.5*sigma**2)*T) / (sigma*np.sqrt(T)) d2 = d1 - sigma*np.sqrt(T) return S*np.exp(-q*T)*norm.cdf(d1) - K*np.exp(-r*T)*norm.cdf(d2) def delta_call(S, K, T, r, sigma, q=0): d1 = (np.log(S/K) + (r - q + 0.5*sigma**2)*T) / (sigma*np.sqrt(T)) return np.exp(-q*T) * norm.cdf(d1) def delta_put(S, K, T, r, sigma, q=0): return delta_call(S, K, T, r, sigma, q) - np.exp(-q*T) S, K, T, r, q = 100, 100, 0.5, 0.05, 0 # Part 1 for sigma in [0.1, 0.2, 0.4]: dc = delta_call(S, K, T, r, sigma) dp = delta_put(S, K, T, r, sigma) print(f"sigma={sigma}: delta_call={dc:.4f}, delta_put={dp:.4f}") # sigma=0.1: delta_call=0.6617, delta_put=-0.3383 # sigma=0.2: delta_call=0.5977, delta_put=-0.4023 # sigma=0.4: delta_call=0.5495, delta_put=-0.4505 # Part 2 sigma = 0.2 for S in [80, 100, 120]: dc = delta_call(S, K, T, r, sigma) print(f"S={S}: delta_call={dc:.4f}") # S=80: delta_call=0.1126 (deep OTM) # S=100: delta_call=0.5977 (ATM) # S=120: delta_call=0.9390 (deep ITM) # Part 3: parity check for sigma in [0.1, 0.2, 0.4]: diff = delta_call(100, K, T, r, sigma) - delta_put(100, K, T, r, sigma) print(f"sigma={sigma}: call_delta - put_delta = {diff:.6f}") # all = 1.000000 # Part 4: FD check sigma = 0.2 S = 100 h = 0.01 fd = (bs_call(S+h, K, T, r, sigma) - bs_call(S-h, K, T, r, sigma)) / (2*h) print(f"closed-form delta: {delta_call(S, K, T, r, sigma):.6f}") print(f"FD delta: {fd:.6f}") # closed-form delta: 0.597682 # FD delta: 0.597682

Interpretation

  • Delta increases as option moves ITM. At S=80S = 80 (OTM), Δ=0.11\Delta = 0.11 — far from stock-like. At S=120S = 120 (ITM), Δ=0.94\Delta = 0.94 — almost like holding stock.
  • Delta is less sensitive to σ\sigma for ATM options. At S=KS = K with varying vol, delta stays near 0.50.5-0.660.66, decreasing slightly as vol rises (ATM delta 0.5\to 0.5 asymptotically as σ\sigma \to \infty).
  • Put-call parity forces ΔcΔp=1\Delta_c - \Delta_p = 1 (for q=0q = 0). This is exact, independent of σ\sigma or SS.
  • Finite-difference agrees to 6 decimal places — closed-form and numerical differentiation both converge to the same answer.

Takeaways

  • Delta is a moneyness gauge. It's a monotone map from spot to [0,1][0, 1] (for calls). Traders internalise "25-delta put" as "roughly 25% probability of exercise" — a useful shorthand even if not exact.
  • Volatility flattens delta. Higher σ\sigma pushes deep-OTM deltas up and deep-ITM deltas down (options become less certain to exercise). ATM delta drifts toward 0.50.5.
  • Parity is robust. It holds exactly regardless of volatility or model — as long as no-arbitrage holds.
  • Closed-form vs. numerical. Finite differences are numerically equivalent to analytical deltas, and are the workhorse when working with models that lack closed-form Greeks (e.g. Heston, SABR).