Markets: A Rigorous Course

Exercise · m09_delta_hedge.py

P&L of a delta-hedged option

Conventions: European options, no dividends, continuously compounded rate r, time in years. The trader SELLS one option at the implied volatility sigma_i, delta-hedges it at discrete dates, and the underlying follows GBM with drift mu and realised volatility sigma_r. P&L is per unit option (multiply by the lot size, e.g. 65 for Nifty, for rupees per lot).

Provided (you wrote them in M08): bs_price, bs_delta and bs_gamma from toolkit.options. They are vectorised in S and tau; at tau = 0 the price is intrinsic value, delta the step function (call 0/1, put -1/0) and gamma 0. Signatures: bs_price(S, K, tau, r, sigma, kind="call"), bs_delta(...same...), bs_gamma(S, K, tau, r, sigma)

Run: cd exercises && .venv/bin/python -m pytest modules/M09-volatility-trading/tests/test_m09_delta_hedge.py

Tests (7)

  • test_gbm_paths_shape_and_moments
  • test_zero_pnl_when_realised_equals_implied
  • test_hedging_noise_shrinks_like_one_over_sqrt_n
  • test_mean_pnl_matches_closed_form
  • test_closed_form_equals_bs_difference_when_mu_equals_r
  • test_gamma_theta_approximation_tracks_actual_pnl
  • test_hedging_at_realised_locks_in_bs_difference

Theory: M09 notes. Run with Ctrl/⌘+Enter.

not run yet

Not saved: sign up to keep your code
"""M09 exercise 2: P&L of a delta-hedged option (notes §9.3).

Conventions: European options, no dividends, continuously compounded rate r,
time in years. The trader SELLS one option at the implied volatility sigma_i,
delta-hedges it at discrete dates, and the underlying follows GBM with drift mu
and realised volatility sigma_r. P&L is per unit option (multiply by the lot
size, e.g. 65 for Nifty, for rupees per lot).

Provided (you wrote them in M08): bs_price, bs_delta and bs_gamma from toolkit.options.
They are vectorised in S and tau; at tau = 0 the price is intrinsic value, delta the
step function (call 0/1, put -1/0) and gamma 0. Signatures:
    bs_price(S, K, tau, r, sigma, kind="call"), bs_delta(...same...), bs_gamma(S, K, tau, r, sigma)

Run:  cd exercises && .venv/bin/python -m pytest modules/M09-volatility-trading/tests/test_m09_delta_hedge.py
"""

from __future__ import annotations

import math

import numpy as np
from scipy.stats import norm

from toolkit.options import bs_delta, bs_gamma, bs_price  # noqa: F401  (provided, M08)


# ------------------------------------------------------------------ exercises

def simulate_gbm_paths(S0, mu, sigma, T, n_steps, n_paths, seed=0):
    """Exact GBM paths S_k = S0 exp((mu - sigma^2/2) t_k + sigma W_{t_k}), t_k = k T / n_steps.

    Use np.random.default_rng(seed).standard_normal((n_paths, n_steps)).
    Returns an array of shape (n_paths, n_steps + 1); column 0 equals S0.
    """
    raise NotImplementedError


def hedged_short_option_pnl(paths, K, T, r, sigma_i, sigma_hedge, kind="call"):
    """Terminal P&L of: sell one option at BS(sigma_i), delta-hedge with BS delta at sigma_hedge.

    At t_0 the trader receives V_0 = BS(S_0, K, T, r, sigma_i), buys Delta_0 units of the
    underlying (Delta computed with sigma_hedge), and holds the rest in cash at rate r.
    At each t_k (k = 1..N-1) she rebalances to Delta_k = BS delta at (S_k, T - t_k,
    sigma_hedge); cash grows by exp(r dt) each step. At T she pays the option payoff
    and sells the hedge.

    Returns an array (n_paths,) of P&L at T (NOT discounted).
    Notes Prop. 9.3 and eq. (9.13).
    """
    raise NotImplementedError


def gamma_theta_pnl(paths, K, T, r, sigma_i):
    """Discrete gamma-theta approximation to the LONG hedged option P&L, discounted to t=0:

        sum_{k=0}^{N-1} e^{-r t_k} * 0.5 * Gamma_i(t_k, S_k) * S_k^2 * [ (dS_k / S_k)^2 - sigma_i^2 dt ]

    with dS_k = S_{k+1} - S_k and Gamma_i the BS gamma at sigma_i and tau = T - t_k.
    Identical for calls and puts. Notes eq. (9.12). Returns array (n_paths,).
    """
    raise NotImplementedError


def expected_hedged_pnl(S0, K, T, r, mu, sigma_i, sigma_r, n_quad=2000):
    """Exact expected discounted P&L of a LONG option bought at sigma_i and continuously
    hedged at sigma_i, when S is GBM(mu, sigma_r). Notes Prop. 9.4:

        E[PnL] = (sigma_r^2 - sigma_i^2) * int_0^T 0.5 K e^{-rT} phi(a(t)) / sqrt(v(t)) dt,
        v(t) = sigma_i^2 (T - t) + sigma_r^2 t,
        a(t) = [ln(S0/K) + (mu - sigma_r^2/2) t + (r - sigma_i^2/2)(T - t)] / sqrt(v(t)).

    Evaluate the integral with the midpoint rule on n_quad points. Same for calls and puts.
    """
    raise NotImplementedError

No runs yet

The stub's functions raise NotImplementedError until you write them. Fill in one, press Run tests, and watch its tests turn green.

Reference solution

Available after your first run, with an account approved for code runs.

Create a free account

Reading is open to everyone. An account keeps your progress, answers, notes and code drafts, and gives you the study plan, the journals and the simulator. Running code needs an account approved for it.