CONTENTS

Solution: Computing Vega Across Strikes and Expiries

Computation

import numpy as np from scipy.stats import norm def bs_call(S, K, T, r, sigma): 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 vega_bs(S, K, T, r, sigma): d1 = (np.log(S/K) + (r + 0.5*sigma**2)*T) / (sigma*np.sqrt(T)) return S * norm.pdf(d1) * np.sqrt(T) def gamma_bs(S, K, T, r, sigma): d1 = (np.log(S/K) + (r + 0.5*sigma**2)*T) / (sigma*np.sqrt(T)) return norm.pdf(d1) / (S*sigma*np.sqrt(T)) S, T, r, sigma = 100, 0.5, 0.05, 0.2 # Part 1: vega vs strike for K in [80, 90, 100, 110, 120]: v = vega_bs(S, K, T, r, sigma) print(f"K={K}: vega={v:.4f} (per 1%: {v/100:.4f})") # K=80: vega=5.58 (per 1%: 0.0558) # K=90: vega=19.28 (per 1%: 0.1928) # K=100: vega=27.34 (per 1%: 0.2734) # K=110: vega=22.48 (per 1%: 0.2248) # K=120: vega=11.10 (per 1%: 0.1110) # Vega peaks ATM, falls off symmetrically in log-strike space. # Part 2: vega vs expiry K = 100 for T in [2.0, 1.0, 0.5, 0.1]: v = vega_bs(S, K, T, r, sigma) print(f"T={T}: vega={v:.2f}") # T=2.0: vega=53.60 # T=1.0: vega=38.07 # T=0.5: vega=27.34 # T=0.1: vega=12.55 # Approximate sqrt(T) scaling: 53.60/38.07 ≈ 1.408 vs sqrt(2) = 1.414 ✓ # 38.07/27.34 ≈ 1.393 vs sqrt(2) ≈ 1.414 (small deviations due to d1 dependence on T) # Part 3: gamma-vega identity S, K, T, sigma = 100, 100, 0.5, 0.2 v = vega_bs(S, K, T, r, sigma) g = gamma_bs(S, K, T, r, sigma) rhs = sigma * S**2 * T * g print(f"vega: {v:.4f}") print(f"sigma*S^2*T*gamma: {rhs:.4f}") # vega: 27.3383 # sigma*S^2*T*gamma: 27.3383 ✓ Equal to 4 decimal places # Part 4: FD check h = 0.001 fd = (bs_call(S, K, T, r, sigma+h) - bs_call(S, K, T, r, sigma-h)) / (2*h) print(f"closed-form vega: {v:.6f}") print(f"FD vega: {fd:.6f}") # closed-form vega: 27.338336 # FD vega: 27.338336

Interpretation

  • Vega peaks ATM. Like gamma, vega is maximised near the strike where the option has the most "optionality."
  • Vega grows as T\sqrt T. This makes long-dated options far more vol-sensitive than short-dated ones. A 2-year ATM option has ~4× the vega of a 0.1-year ATM option of the same strike and spot.
  • Gamma–vega identity V=σS2TΓ\mathcal{V} = \sigma S^2 T\Gamma is exact (verifiable symbolically). It's a useful back-of-envelope tool for vol traders: you can estimate vega knowing gamma, and vice versa.
  • Finite-difference vega agrees to 6 decimals — both methods converge to the same BS vega.

Takeaways

  • Vega is the flagship risk of a vol book. Every options trader watches vega across strikes (skew exposure) and maturities (term exposure).
  • Long-dated options dominate vega risk in a diversified book. If you have $1M vega of 1-month options and $1M vega of 2-year options, the 2-year options account for ~5-6× more P&L per point of vol move.
  • Skew and term-structure complicate vega. The flat-vega computed above assumes a parallel shift in implied vol; real vol surfaces can twist and steepen, requiring skew-vega and term-vega decompositions.
  • Numerical vega always works. For any model where you can price an option, you can compute vega by finite-differencing in σ\sigma — essential for models like Heston or SABR where closed-form Greeks are complex.
Solution — Computing Vega Across Strikes and Expiries | q4quant.studio