Skip to main content

finance_solution/derivatives/
mod.rs

1//! # Derivatives math (options & related)
2//!
3//! Pure **pricing, Greeks, and implied volatility** for engines that also run
4//! [`crate::stocks::ta`] on the underlier. This module does **not** subscribe to
5//! option chains, manage multi-leg books, or know about OSI / exchange symbols.
6//!
7//! ---
8//!
9//! ## How a quant uses these metrics (trading perspective)
10//!
11//! | Metric | Trading question | Desk habit |
12//! |--------|------------------|------------|
13//! | **Price** | Fair value vs mid / edge? | Compare model to NBBO; mark inventory |
14//! | **Δ Delta** | How much underlier exposure per option? | Hedge: sell ≈ Δ shares per long call |
15//! | **Γ Gamma** | How fast does the hedge go wrong? | Scalp gamma; size limits into events |
16//! | **ν Vega** | What if IV moves a point? | Vol trades, earnings, event premium |
17//! | **Θ Theta** | What does the book bleed overnight? | Carry P&L, calendar spreads |
18//! | **ρ Rho** | Rate risk? | Usually second-order for short-dated equity |
19//! | **Vanna / Volga / Charm** | Surface & Δ-drift risk | Sticky-strike stories; overnight re-hedge |
20//! | **IV** | What vol is the market implying? | Surfaces, relative value, skew stories |
21//! | **Intrinsic / time value** | How much is “optionality”? | Early exercise intuition (European here) |
22//! | **Parity residual** | Is the quote book consistent? | Sanity / arb alert (within fees) |
23//!
24//! **Typical workflow on a name (e.g. AAPL):**
25//!
26//! 1. Trade the **underlier path** with TA (`StochState`, `EmaState`, …) on 1m/5s bars.  
27//! 2. For each option of interest, maintain **IV from mid** and **Greeks at live spot**.  
28//! 3. Risk: sum Δ/Γ/ν over positions; hedge underlier when net Δ exceeds a band.  
29//! 4. Research: reprice a chain on a vol surface assumption; compare to TA regime (e.g. high RVOL + high IV).
30//!
31//! This crate supplies steps 1–3 **math only**. Order routing, position servers, and
32//! “should I sell the 0.30Δ call?” stay in *your* strategy code.
33//!
34//! ---
35//!
36//! ## How an engineer wires this (engineering perspective)
37//!
38//! ```text
39//! Market data (async / websockets)          finance-solution (sync, pure)
40//! ───────────────────────────────          ─────────────────────────────
41//! 1m bars for underlier          ──push──► StochState / EmaState / …
42//! option quote (bid/ask/mid)     ──IV───► BsmState::set_vol_from_price
43//! underlier tick                 ──spot─► for c in chain { c.set_spot(s); greeks() }
44//! futures mark                   ──F────► Black76State::set_forward
45//! FX spot                        ──S────► GkState::set_spot
46//! ```
47//!
48//! **Recommended shape (mirrors TA):**
49//!
50//! | Layer | Type | When |
51//! |-------|------|------|
52//! | Config | [`BsmParams`] / [`Black76Params`] / [`GkParams`] (`Copy`) | Contract + market inputs |
53//! | Validated | [`ValidatedBsm::new`] / … | One-shot research / backtest bar |
54//! | Live | [`BsmState`] / [`Black76State`] / [`GkState`] | Per-contract object in `HashMap` |
55//! | Teaching | [`bsm_solution`] / [`black76_solution`] / [`gk_solution`] | Formulas + `print_table` |
56//!
57//! **Concurrency:** keep math **sync**. Your runtime may `rayon` over strikes or
58//! `tokio` only to **receive** data — there is no I/O inside these functions.
59//!
60//! ---
61//!
62//! ## Models
63//!
64//! | Model | Underlier | Status |
65//! |-------|-----------|--------|
66//! | Black–Scholes–Merton | Spot `S`, continuous yield `q` | **available** (+ cross Greeks) |
67//! | Black ’76 | Forward / futures `F` | **available** |
68//! | Garman–Kohlhagen | FX spot, \(r_d\), \(r_f\) | **available** |
69//! | CRR binomial | European / American tree | **available** |
70//!
71//! Equity **single-name** Europeans with continuous yield ≈ BSM.  
72//! **Options on futures** / many index products → Black ’76.  
73//! **FX vanillas** → Garman–Kohlhagen.  
74//! **American** early exercise / American IV → CRR ([`crr_price`], [`american_implied_vol`]).  
75//! **Crypto perps** need funding / mark conventions outside this module.
76//!
77//! ## Units (read carefully)
78//!
79//! | Input | Unit |
80//! |-------|------|
81//! | Spot / forward / strike | same money units |
82//! | `time_years` | **years** (`30.0/365.25` for ~30 calendar days) |
83//! | rates | continuous, absolute (`0.05` = 5%) |
84//! | `vol` | annualized absolute (`0.20` = 20%) |
85//! | Vega | per **+1.0** in σ (use `vega_per_vol_point` for per 1%) |
86//! | Theta / charm | per **year** (use `*_per_calendar_day` helpers) |
87//!
88//! ## Quick start
89//!
90//! ```
91//! use finance_solution::derivatives::{
92//!     OptionType, BsmParams, ValidatedBsm, bsm_price, bsm_greeks, bsm_cross_greeks,
93//!     bsm_implied_vol, Black76Params, black76_price, GkParams, gk_price,
94//! };
95//!
96//! let p = BsmParams::atm_one_year(100.0, 0.05, 0.20);
97//! let model = ValidatedBsm::new(p).unwrap();
98//! let call = model.price(OptionType::Call).unwrap();
99//! let g = model.greeks(OptionType::Call).unwrap();
100//! let x = bsm_cross_greeks(p, OptionType::Call).unwrap();
101//! assert!(call > 0.0 && g.delta > 0.0 && x.volga.is_finite());
102//!
103//! let iv = bsm_implied_vol(p, OptionType::Call, call).unwrap();
104//! assert!((iv - 0.20).abs() < 1e-4);
105//!
106//! // Futures-style
107//! let f = Black76Params::atm_one_year(100.0, 0.05, 0.20);
108//! let _ = black76_price(f, OptionType::Call).unwrap();
109//!
110//! // FX-style
111//! let fx = GkParams::atm_one_year(1.10, 0.05, 0.03, 0.12);
112//! let _ = gk_price(fx, OptionType::Call).unwrap();
113//! ```
114//!
115//! Live underlier ticks: [`BsmState`] / [`Black76State`] / [`GkState`].  
116//! Teaching: [`bsm_solution`], [`black76_solution`], [`gk_solution`], [`crr_solution`].  
117//! American: [`crr_price`] + [`american_implied_vol`].
118
119pub mod black76;
120pub mod black_scholes;
121pub mod crr;
122pub mod garman_kohlhagen;
123pub mod implied_vol;
124pub mod norm;
125pub mod state;
126pub mod types;
127
128#[doc(inline)]
129pub use black76::*;
130#[doc(inline)]
131pub use black_scholes::*;
132#[doc(inline)]
133pub use crr::*;
134#[doc(inline)]
135pub use garman_kohlhagen::*;
136#[doc(inline)]
137pub use implied_vol::*;
138#[doc(inline)]
139pub use state::*;
140#[doc(inline)]
141pub use types::*;