Exercise · m08_binomial.py
One-period replication and the Cox-Ross-Rubinstein tree
not run yet
Not saved: sign up to keep your code"""M08 exercise: one-period replication and the Cox-Ross-Rubinstein tree (notes §8.3-§8.4).
Run: cd exercises && .venv/bin/python -m pytest modules/M08-option-pricing/tests/test_m08_binomial.py
numpy is allowed. Vectorise the backward induction over nodes at each time step; n = 2000 must run fast.
"""
from __future__ import annotations
import math
import numpy as np
def one_period_replicate(S0: float, u: float, d: float, r: float, dt: float, V_up: float, V_down: float) -> tuple[float, float, float]:
"""Replicate a claim paying V_up if S goes to u*S0 and V_down if it goes to d*S0 (notes Prop. 8.3.2).
Solve Delta*u*S0 + B*e^{r dt} = V_up, Delta*d*S0 + B*e^{r dt} = V_down for the share holding
Delta and the bond holding B (rupees invested at the risk-free rate today). Return (Delta, B, V0)
with V0 = Delta*S0 + B.
Raise ValueError unless d < e^{r dt} < u (otherwise there is an arbitrage, notes Lemma 8.3.1).
Check (Hull): S0=20, u=1.1, d=0.9, r=12%, dt=0.25, call K=21 -> Delta=0.25, V0=0.633.
"""
raise NotImplementedError
def risk_neutral_prob(u: float, d: float, r: float, dt: float, q: float = 0.0) -> float:
"""p = (e^{(r-q) dt} - d) / (u - d), notes eq. (8.10). Raise ValueError unless d < e^{(r-q)dt} < u."""
raise NotImplementedError
def crr_params(sigma: float, r: float, dt: float, q: float = 0.0) -> tuple[float, float, float]:
"""CRR parametrisation: u = e^{sigma sqrt(dt)}, d = 1/u, p from risk_neutral_prob. Return (u, d, p)."""
raise NotImplementedError
def crr_price(S: float, K: float, T: float, r: float, sigma: float, n: int, kind: str = "call",
american: bool = False, q: float = 0.0) -> float:
"""Price a European or American call/put on an n-step CRR tree (notes Algorithm 8.4.1).
Terminal nodes S u^j d^{n-j}, j = 0..n. Step back with V = e^{-r dt}[p V_up + (1-p) V_down].
If american, at each node take max(continuation, intrinsic).
References: crr_price(50, 50, 5/12, 0.10, 0.40, 5, 'put', american=True) = 4.488459 (Hull 4.49);
European 4.319019; ATM S=K=100, T=1, r=5%, sigma=20% call: n=10 -> 10.253409,
n=100 -> 10.430612, n=1000 -> 10.448584 (BS 10.4505835722).
"""
raise NotImplementedError
def early_exercise_premium(S: float, K: float, T: float, r: float, sigma: float, n: int,
kind: str = "put", q: float = 0.0) -> float:
"""American minus European CRR price with the same tree. Zero for calls when q = 0 (notes Prop. 8.2.4)."""
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.