Small, dependency-light Python utilities for European option pricing and risk under the Black–Scholes–Merton (BSM) model.
black_scholes.py— price a European call or put.greeks.py— compute Delta, Gamma, Vega, Theta, Rho.implied_vol.py— back out implied volatility from a market price with a stable Newton–Bisection hybrid.
Just copy the three files into your project or install the repo as a package (editable mode shown):
pip install -e .from black_scholes import black_scholes
from greeks import greeks
from implied_vol import implied_vol
S, K, T, r, sigma = 100.0, 100.0, 0.5, 0.02, 0.25
price_call = black_scholes(S, K, T, r, sigma, option_type="call")
risk = greeks(S, K, T, r, sigma, option_type="call")
iv = implied_vol(price_call, S, K, T, r, option_type="call") # ~ sigma back
print(price_call) # e.g. 7.02…
print(risk) # {'delta': …, 'gamma': …, 'vega': …, 'theta': …, 'rho': …}
print(iv) # ~0.25Parameters
S(float) — Spot price of the underlying.K(float) — Strike.T(float) — Time to maturity in years (e.g., 30 calendar days ≈30/365).r(float) — Continuously compounded risk-free rate (annual).sigma(float) — Volatility (annualized standard deviation of log returns).option_type(Literal["call","put"]) — Which payoff to price.
Edge handling
T <= 0: returns intrinsic valuemax(S−K,0)(call) ormax(K−S,0)(put).sigma == 0: discounts the strike and returns forward intrinsic value.
Returns a dict with keys: delta, gamma, vega, theta, rho.
Edge handling
T <= 0: finite-maturity limits (e.g., Delta ∈ {−1, −0.5, 0, 0.5, 1} at the boundary).sigma == 0: Greeks collapse appropriately; Vega/Gamma → 0.
Parameters
price_target(float) — Market option price to invert.S, K, T, r, option_type— as above.initial(float, default 0.2) — Initial guess for Newton step.tol(float, default 1e−8) — Absolute price tolerance for convergence.max_iter(int, default 100) — Max Newton iterations before fallback.lower(float, default 1e−12),upper(float, default 5.0) — Search bracket.
Behavior
-
Validates no-arbitrage range:
- Call:
price ∈ [max(S−Ke^{−rT},0), S] - Put:
price ∈ [max(Ke^{−rT}−S,0), Ke^{−rT}]RaisesValueErrorif outside.
- Call:
-
Root-finding: Newton’s method when stable (positive Vega, proposal inside bracket), otherwise bisection. Expands
upperif necessary to straddle the root.
from black_scholes import black_scholes
from greeks import greeks
price_put = black_scholes(95, 100, 0.25, 0.03, 0.30, "put")
risk_put = greeks(95, 100, 0.25, 0.03, 0.30, "put")from implied_vol import implied_vol
iv = implied_vol(price_target=7.25, S=100, K=100, T=0.5, r=0.02, option_type="call")-
Spot-check against known BSM values (e.g., via quantlib/NumPy implementations or online calculators).
-
Try extreme cases:
T=0,sigma=0- Deep OTM/ITM (
S/Kvery small/large) - Very small
T(hours/days)