investfly.models.marketdata.OptionPricer
Black-Scholes option pricer used by Investfly automated options strategies.
Why this exists in the SDK:
- Strategy code (live + backtest) needs a deterministic synthetic option premium when no real option chain quote is available. Real chains are still used when present; this is the fallback.
- Backtest historically replays underlying OHLCV but does not yet replay full option chains. We use Black-Scholes with computed/historical IV proxies to settle option premia in backtest in a deterministic, reproducible way.
- Decision: use realized-volatility from underlying daily returns as the default IV proxy when no historical IV column is available. Annualize from daily standard deviation by sqrt(252).
- Risk-free rate is a static default (0.04) for MVP; can be replaced by config later.
- No dividend yield handling for MVP (treat as 0); expand later for option-on-stock with non-zero dividend yield.
This pricer intentionally has no I/O dependencies so it can be reused inside the SDK, the Python runtime, the backtest engine, and unit tests.
Black-Scholes Greeks bundle returned alongside the theoretical premium.
Theoretical price + Greeks for a single contract.
Black-Scholes pricer for European-style stock/ETF options.
Annualized realized volatility of daily log returns.
Falls back to MIN_IMPLIED_VOL when the input is too short or has zero variance. Inputs are oldest-to-newest closing prices (matching Bar order convention).
Time-to-expiry in calendar years, with a minimum of 1/365 to keep BS well-defined.
Black-Scholes price + Greeks for a European option.
Greeks scaling:
- delta in [-1, 1] per share (multiply by 100 for per-contract risk).
- theta is per-year; divide by 365 for per-day theta.
- vega is per 1.00 of vol (multiply by 0.01 for per-1%-vol).
- rho is per 1.00 of rate (multiply by 0.01 for per-1%-rate). These conventions match common quant texts; UI/runtime can rescale as needed.
Find the strike whose Black-Scholes delta is closest to the target.
Search is a coarse grid scan with a refinement step. Strike grid is anchored at the
nearest multiple of strikeStep around spot and bounded at +-3 sigma * sqrt(T) from
spot, which is wide enough for typical 30-60 DTE selections and avoids unstable
far-OTM delta extrapolation.