Exercise · m09a_implied_move.py
The straddle-implied move, event variance from the term structure, IV rank and IV percentile
not run yet
Not saved: sign up to keep your code"""M09A exercise 2: the straddle-implied move, event variance from the term structure,
IV rank and IV percentile (notes §9A.7-9A.10).
Conventions: Black-76 on the forward F, continuously compounded rate r, tau in years,
sigma annualised. Total implied variance of an expiry is sigma^2 * tau.
Provided: b76(F, K, tau, r, sigma, kind="call"), the Black-76 price of a European call or
put on a forward F (toolkit.options.black76_price, which you wrote in M08; intrinsic value
discounted at tau <= 0).
Run: cd exercises && .venv/bin/python -m pytest modules/M09A-indian-options-desk/tests/test_m09a_implied_move.py
"""
from __future__ import annotations
import math
import numpy as np
import pandas as pd
from scipy.optimize import brentq
from scipy.stats import norm
from toolkit.options import black76_price as b76 # noqa: F401 (provided, M08)
SQRT_2_OVER_PI = math.sqrt(2.0 / math.pi)
# ------------------------------------------------------------------ exercises
def straddle_exact(F: float, K: float, tau: float, r: float, sigma: float) -> float:
"""Black-76 call + put at strike K."""
raise NotImplementedError
def atm_straddle_closed_form(F: float, tau: float, r: float, sigma: float) -> float:
"""Exact ATM-forward straddle (K = F), notes (9A.7):
2 e^{-r tau} F (2 N(sigma sqrt(tau) / 2) - 1)."""
raise NotImplementedError
def atm_straddle_approx(F: float, tau: float, r: float, sigma: float) -> float:
"""Linear approximation, notes (9A.8): e^{-r tau} F sigma sqrt(tau) sqrt(2/pi)."""
raise NotImplementedError
def expected_abs_move(S: float, sigma: float, tau: float) -> float:
"""E|S_T - S| when S_T - S ~ N(0, (S sigma)^2 tau): S sigma sqrt(tau) sqrt(2/pi)."""
raise NotImplementedError
def prob_move_within(m: float, S: float, sigma: float, tau: float) -> float:
"""P(|S_T - S| < m) in the same normal model: 2 N(m / (S sigma sqrt(tau))) - 1."""
raise NotImplementedError
def straddle_implied_vol(straddle: float, F: float, K: float, tau: float, r: float) -> float:
"""The sigma with straddle_exact(F, K, tau, r, sigma) == straddle, found by Brent's method
on [1e-4, 5]. Raise ValueError if straddle is not strictly between the prices at the
two ends of the bracket."""
raise NotImplementedError
def event_variance(sigma1: float, tau1: float, sigma2: float, tau2: float) -> tuple[float, float]:
"""Two expiries 0 < tau1 < tau2 that both contain one scheduled event. Model:
sigma_i^2 tau_i = sigma_d^2 tau_i + e (i = 1, 2).
Return (e, sigma_d), notes (9A.13):
e = tau1 tau2 (sigma1^2 - sigma2^2) / (tau2 - tau1),
sigma_d = sqrt((sigma2^2 tau2 - sigma1^2 tau1) / (tau2 - tau1)) (NaN if the radicand <= 0).
e may be negative. Raise ValueError unless 0 < tau1 < tau2."""
raise NotImplementedError
def event_variance_before_after(sigma_b: float, tau_b: float, sigma_a: float, tau_a: float,
sigma_d: float) -> float:
"""One expiry before the event (tau_b) and one after (tau_a), ordinary volatility sigma_d
between them, notes (9A.14):
e = sigma_a^2 tau_a - sigma_b^2 tau_b - sigma_d^2 (tau_a - tau_b).
Raise ValueError unless 0 <= tau_b < tau_a."""
raise NotImplementedError
def event_move(e: float) -> dict:
"""dict(sd=sqrt(e), mean_abs=sqrt(e) * sqrt(2/pi)); ValueError if e <= 0."""
raise NotImplementedError
def iv_rank(iv: pd.Series, window: int = 252) -> pd.Series:
"""IV rank, notes (9A.10): (IV_t - min) / (max - min), min and max over the trailing
`window` observations INCLUDING t. NaN for the first window-1 points and when max == min."""
raise NotImplementedError
def iv_percentile(iv: pd.Series, window: int = 252) -> pd.Series:
"""IV percentile, notes (9A.11): the fraction of the window-1 observations before t
(t-window+1 .. t-1) that are strictly below IV_t. NaN for the first window-1 points."""
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.