Black Scholes
1. Model Assumptions
Price dynamic (real-world):
Risk-neutral measure:
Key fairy-tale assumptions: frictionless markets, continuous trading, constant and , no jumps, no arbitrage.
2. Ito's Lemma ⇒ Black–Scholes PDE
Since and :
Delta-hedge away risk and earn :
3. Closed-Form Call/Put
where is the standard normal CDF.
4. Greeks (Analytical)
5. NumPy Implementation
python
# black_scholes_numpy.pyimport numpy as npfrom scipy.stats import norm
def d1_d2(S, K, r, sigma, T): """Return d1, d2 for arrays or scalars.""" t_sqrt = np.sqrt(T) d1 = (np.log(S / K) + (r + 0.5 * sigma**2) * T) / (sigma * t_sqrt) d2 = d1 - sigma * t_sqrt return d1, d2
def call_price(S, K, r, sigma, T): d1, d2 = d1_d2(S, K, r, sigma, T) return S * norm.cdf(d1) - K * np.exp(-r * T) * norm.cdf(d2)
def put_price(S, K, r, sigma, T): d1, d2 = d1_d2(S, K, r, sigma, T) return K * np.exp(-r * T) * norm.cdf(-d2) - S * norm.cdf(-d1)
def delta_call(S, K, r, sigma, T): d1, _ = d1_d2(S, K, r, sigma, T) return norm.cdf(d1)
def gamma(S, K, r, sigma, T): d1, _ = d1_d2(S, K, r, sigma, T) return norm.pdf(d1) / (S * sigma * np.sqrt(T))
def vega(S, K, r, sigma, T): d1, _ = d1_d2(S, K, r, sigma, T) return S * norm.pdf(d1) * np.sqrt(T)
6. JAX Autodiff Variant
python
# black_scholes_jax.pyimport jax.numpy as jnpfrom jax import grad, jitfrom jax.scipy.stats.norm import cdf, pdf
@jitdef d1_d2_jax(S, K, r, sigma, T): t_sqrt = jnp.sqrt(T) d1 = (jnp.log(S / K) + (r + 0.5 * sigma**2) * T) / (sigma * t_sqrt) d2 = d1 - sigma * t_sqrt return d1, d2
@jitdef call_price_jax(S, K, r, sigma, T): d1, d2 = d1_d2_jax(S, K, r, sigma, T) return S * cdf(d1) - K * jnp.exp(-r * T) * cdf(d2)
delta_jax = jit(grad(call_price_jax, argnums=0))vega_jax = jit(grad(call_price_jax, argnums=3))
7. Local Volatility (Dupire-esque)
Approx via implied vol surface :
8. Quick Feedback Widget (Optional React)
tsx
export function Feedback() { const [done, setDone] = useState(false) const send = (val: 'yes' | 'no') => { // POST to API setDone(true) } if (done) return <p>Thanks!</p> return ( <div style={{ marginTop: 32 }}> <p>Was this clear?</p> <button onClick={() => send('yes')}>Yes</button> <button onClick={() => send('no')}>No</button> </div> )}
9. Next Steps
- Calibrate to market data.
- Extend to stochastic vol (Heston), jumps (Merton), or mixed models.
- Study discrete hedging errors & transaction costs.
Implementation Note: The NumPy implementation above is production-ready for most use cases. The JAX variant offers automatic differentiation for Greeks and can be significantly faster on GPUs for large-scale computations.
0 views