Analysis Modules
ferro_ta.analysis.options — Rust-backed derivatives analytics for options.
This module preserves the legacy IV-series helpers and expands them with pricing, Greeks, implied-volatility inversion, smile analytics, and strike selection helpers suitable for research and simulation workflows.
- class ferro_ta.analysis.options.ExtendedGreeks(vanna, volga, charm, speed, color)[source]
Bases:
objectContainer for second-order and cross Greeks.
- Parameters:
- class ferro_ta.analysis.options.OptionGreeks(delta, gamma, vega, theta, rho)[source]
Bases:
objectContainer for first-order Greeks.
- Parameters:
- class ferro_ta.analysis.options.SmileMetrics(atm_iv, risk_reversal_25d, butterfly_25d, skew_slope, convexity)[source]
Bases:
objectSummary metrics for a single smile slice.
- Parameters:
- class ferro_ta.analysis.options.VolCone(windows, min, p25, median, p75, max)[source]
Bases:
objectHistorical realized vol distribution across window lengths.
- Parameters:
- ferro_ta.analysis.options.american_option_price(underlying, strike, rate, time_to_expiry, volatility, *, option_type='call', carry=0.0)[source]
American option price using the Barone-Adesi-Whaley (1987) approximation.
Accurate to within a few basis points for standard equity/index parameters. O(1) per evaluation — suitable for batch pricing or calibration.
- Parameters:
underlying (ArrayLike | float) – Current underlying (spot) price.
strike (ArrayLike | float) – Option strike price.
rate (ArrayLike | float) – Risk-free rate (annualised, decimal).
time_to_expiry (ArrayLike | float) – Time to expiry in years.
volatility (ArrayLike | float) – Implied volatility (annualised, decimal).
option_type (str) –
"call"(default) or"put".carry (ArrayLike | float) – Continuous carry / dividend yield (annualised, decimal). Default 0. For calls with
carry = 0(no dividends) early exercise is never optimal and the result equals the European BSM price.
- Returns:
American option price ≥ European BSM price.
- Return type:
float or NDArray[float64]
Notes
The BAW approximation uses a quadratic equation to find the critical exercise boundary S* via Newton-Raphson iteration, then adds the early exercise premium on top of the European price.
Reference: Barone-Adesi, G. & Whaley, R.E. (1987). “Efficient Analytic Approximation of American Option Values.” Journal of Finance, 42(2), 301–320.
See also
early_exercise_premiumDifference between American and European prices.
- ferro_ta.analysis.options.black_76_price(forward, strike, rate, time_to_expiry, volatility, *, option_type='call')[source]
Price options under Black-76.
- ferro_ta.analysis.options.black_scholes_price(spot, strike, rate, time_to_expiry, volatility, *, option_type='call', dividend_yield=0.0)[source]
Price options under Black-Scholes-Merton.
- ferro_ta.analysis.options.close_to_close_vol(close, window=20, trading_days_per_year=252.0)[source]
Rolling close-to-close realized volatility (annualised).
Baseline estimator — uses only closing prices. Less efficient than OHLC estimators but requires only daily close data.
- Parameters:
- Returns:
Same length as close. First
windowvalues are NaN.- Return type:
NDArray[float64]
Notes
Formula:
σ = √( Σᵢ ln²(Cᵢ/Cᵢ₋₁) / window × trading_days_per_year )
No Bessel correction is applied (population variance, not sample variance).
- ferro_ta.analysis.options.digital_option_greeks(underlying, strike, rate, time_to_expiry, volatility, *, option_type='call', digital_type='cash_or_nothing', carry=0.0)[source]
Delta, gamma, and vega for a digital option via numerical bumping.
Uses central finite differences (spot bump ε = spot × 10⁻³ for delta/gamma; vol bump ε = 10⁻³ for vega). Theta and rho are set to NaN.
- Parameters:
underlying (ArrayLike | float) – Same as
digital_option_price().strike (ArrayLike | float) – Same as
digital_option_price().rate (ArrayLike | float) – Same as
digital_option_price().time_to_expiry (ArrayLike | float) – Same as
digital_option_price().volatility (ArrayLike | float) – Same as
digital_option_price().option_type (str) – Same as
digital_option_price().carry (ArrayLike | float) – Same as
digital_option_price().digital_type (str) –
"cash_or_nothing"(default) or"asset_or_nothing".
- Returns:
Named tuple; only
delta,gamma,vegaare finite.thetaandrhoare NaN.- Return type:
- ferro_ta.analysis.options.digital_option_price(underlying, strike, rate, time_to_expiry, volatility, *, option_type='call', digital_type='cash_or_nothing', carry=0.0)[source]
Price a digital (binary) option under BSM.
- Parameters:
underlying (ArrayLike | float) – Current underlying (spot) price.
strike (ArrayLike | float) – Option strike price.
rate (ArrayLike | float) – Risk-free rate (annualised, decimal).
time_to_expiry (ArrayLike | float) – Time to expiry in years.
volatility (ArrayLike | float) – Implied volatility (annualised, decimal).
option_type (str) –
"call"(default) or"put".digital_type (str) –
"cash_or_nothing"(default) — pays 1 unit of cash if ITM at expiry; or"asset_or_nothing"— pays the underlying asset price.carry (ArrayLike | float) – Continuous carry / dividend yield (annualised, decimal). Default 0.
- Returns:
Option price. Returns a scalar when all inputs are scalars, or an array when any input is an array.
- Return type:
float or NDArray[float64]
Notes
Closed-form BSM formulas:
Cash-or-nothing call: e^{−rT} · N(d₂) Cash-or-nothing put: e^{−rT} · N(−d₂) Asset-or-nothing call: S · e^{−qT} · N(d₁) Asset-or-nothing put: S · e^{−qT} · N(−d₁)Put-call parity for cash-or-nothing: call + put = e^{−rT}. Put-call parity for asset-or-nothing: call + put = S · e^{−qT}.
Invalid inputs (non-positive spot/strike, negative time or vol) return NaN.
Early exercise premium: American price − European BSM price.
Represents the additional value an American option holder gains from the right to exercise before expiry. Always ≥ 0.
- Parameters:
underlying (ArrayLike | float) – Same as
american_option_price().strike (ArrayLike | float) – Same as
american_option_price().rate (ArrayLike | float) – Same as
american_option_price().time_to_expiry (ArrayLike | float) – Same as
american_option_price().volatility (ArrayLike | float) – Same as
american_option_price().option_type (str) – Same as
american_option_price().carry (ArrayLike | float) – Same as
american_option_price().
- Returns:
Premium ≥ 0. Typically 0 for calls with no dividends.
- Return type:
float or NDArray[float64]
Notes
For equity calls with zero carry (no dividends), early exercise is never optimal so the premium is ≈ 0. For puts (or calls on dividend-paying underlyings), the premium increases with in-the-moneyness, rate, and time to expiry.
- ferro_ta.analysis.options.expected_move(spot, iv, days_to_expiry, trading_days_per_year=252.0)[source]
Expected ±1σ move over days_to_expiry calendar days.
Uses the log-normal approximation:
upper_move = spot × e^{+σ√(days/trading_days)} − spot lower_move = spot × e^{−σ√(days/trading_days)} − spot- Parameters:
- Returns:
(lower_move, upper_move)— signed absolute price changes fromspot.lower_move < 0,upper_move > 0.- Return type:
Notes
Because of log-normal skew,
|upper_move| > |lower_move|.Examples
>>> from ferro_ta.analysis.options import expected_move >>> lower, upper = expected_move(100.0, 0.20, 30) >>> round(upper, 2) 7.14
- ferro_ta.analysis.options.extended_greeks(underlying, strike, rate, time_to_expiry, volatility, *, option_type='call', model='bsm', carry=0.0)[source]
Return vanna, volga, charm, speed, and color (second-order / cross Greeks).
All Greeks are computed via closed-form BSM formulas. Black-76 is not yet supported and returns NaN for all five values.
- Parameters:
underlying (ArrayLike | float) – Current underlying (spot) price.
strike (ArrayLike | float) – Option strike price.
rate (ArrayLike | float) – Risk-free rate (annualised, decimal — e.g.
0.05for 5 %).time_to_expiry (ArrayLike | float) – Time to expiry in years.
volatility (ArrayLike | float) – Implied volatility (annualised, decimal).
option_type (str) –
"call"(default) or"put".model (str) –
"bsm"(default)."black76"returns NaN for all fields.carry (ArrayLike | float) – Continuous carry / dividend yield (annualised, decimal). Default 0.
- Returns:
Named tuple with fields:
vanna — ∂Δ/∂σ: sensitivity of delta to a change in vol.
volga — ∂²V/∂σ² (vomma): sensitivity of vega to a change in vol.
charm — ∂Δ/∂t: daily rate of change in delta (theta of delta).
speed — ∂Γ/∂S: rate of change in gamma with respect to spot.
color — ∂Γ/∂t: daily rate of change in gamma.
- Return type:
Notes
Inputs may be scalars or broadcastable arrays. When arrays are supplied each field of the returned
ExtendedGreeksis anNDArray.Closed-form expressions (BSM, zero-carry):
vanna = -e^{-qT} · φ(d₁) · d₂ / σ volga = S · e^{-qT} · φ(d₁) · √T · d₁ · d₂ / σ charm = -e^{-qT} · φ(d₁) · [2(r-q)T - d₂·σ·√T] / (2T·σ·√T) speed = -Γ/S · (d₁/(σ√T) + 1) color = -Γ · [r-q + d₁·σ/(2√T) + (2(r-q)T - d₂·σ√T)·d₁/(2T·σ√T)]
- ferro_ta.analysis.options.garman_klass_vol(open, high, low, close, window=20, trading_days_per_year=252.0)[source]
Rolling Garman-Klass OHLC realized volatility estimator (annualised).
Extends Parkinson by incorporating the open-close return. ~7.4× more efficient than close-to-close. Does not handle overnight gaps.
- Parameters:
open (ArrayLike) – Arrays of daily OHLC prices (same length, ≥ window).
high (ArrayLike) – Arrays of daily OHLC prices (same length, ≥ window).
low (ArrayLike) – Arrays of daily OHLC prices (same length, ≥ window).
close (ArrayLike) – Arrays of daily OHLC prices (same length, ≥ window).
window (int) – Rolling look-back period in bars (default 20).
trading_days_per_year (float) – Annualisation factor (default 252).
- Returns:
Same length as close. First
window - 1values are NaN.- Return type:
NDArray[float64]
Notes
Per-bar contribution:
GK = 0.5·ln²(H/L) − (2·ln2 − 1)·ln²(C/O)
Reference: Garman, M.B. & Klass, M.J. (1980). “On the Estimation of Security Price Volatilities from Historical Data.” Journal of Business, 53(1).
- ferro_ta.analysis.options.greeks(underlying, strike, rate, time_to_expiry, volatility, *, option_type='call', model='bsm', carry=0.0)[source]
Return delta, gamma, vega, theta, and rho.
- ferro_ta.analysis.options.implied_volatility(price, underlying, strike, rate, time_to_expiry, *, option_type='call', model='bsm', carry=0.0, initial_guess=0.2, tolerance=1e-08, max_iterations=100)[source]
Invert option prices to implied volatility.
- Parameters:
- Return type:
- ferro_ta.analysis.options.iv_percentile(iv_series, window=252)[source]
Compute rolling IV percentile in Rust while preserving the legacy API.
- ferro_ta.analysis.options.iv_rank(iv_series, window=252)[source]
Compute rolling IV rank in Rust while preserving the legacy API.
- ferro_ta.analysis.options.iv_zscore(iv_series, window=252)[source]
Compute rolling IV z-score in Rust while preserving the legacy API.
- ferro_ta.analysis.options.label_moneyness(strikes, reference_price, *, option_type='call')[source]
Label strikes as
ITM,ATM, orOTM.
- ferro_ta.analysis.options.option_price(underlying, strike, rate, time_to_expiry, volatility, *, option_type='call', model='bsm', carry=0.0)[source]
Model-dispatched option price helper.
- ferro_ta.analysis.options.parkinson_vol(high, low, window=20, trading_days_per_year=252.0)[source]
Rolling Parkinson high-low realized volatility estimator (annualised).
~5× more efficient than close-to-close for diffusion processes. Does not account for drift or overnight gaps.
- Parameters:
- Returns:
Same length as high. First
window - 1values are NaN.- Return type:
NDArray[float64]
Notes
Formula per window:
σ² = (1 / (4·ln2·window)) · Σ ln²(Hᵢ/Lᵢ) × trading_days_per_year
Reference: Parkinson, M. (1980). “The Extreme Value Method for Estimating the Variance of the Rate of Return.” Journal of Business, 53(1).
- ferro_ta.analysis.options.put_call_parity_deviation(call_price, put_price, spot, strike, rate, time_to_expiry, *, carry=0.0)[source]
Put-call parity deviation:
C − P − (S·e^{−q·T} − K·e^{−r·T}).At no-arbitrage the deviation is exactly 0. A non-zero result indicates mispricing, a data error, or a stale quote.
- Parameters:
call_price (float) – Market or model price of the call option.
put_price (float) – Market or model price of the put option.
spot (float) – Current underlying price.
strike (float) – Common strike price of the call and put.
rate (float) – Risk-free rate (annualised, decimal).
time_to_expiry (float) – Time to expiry in years.
carry (float) – Continuous dividend yield / carry rate (annualised, decimal).
- Returns:
Signed deviation. Positive → call is overpriced relative to put; negative → put is overpriced relative to call.
- Return type:
Examples
>>> from ferro_ta.analysis.options import option_price, put_call_parity_deviation >>> call = option_price(100, 100, 0.05, 1.0, 0.2, option_type="call") >>> put = option_price(100, 100, 0.05, 1.0, 0.2, option_type="put") >>> put_call_parity_deviation(call, put, 100, 100, 0.05, 1.0) # ≈ 0.0
- ferro_ta.analysis.options.rogers_satchell_vol(open, high, low, close, window=20, trading_days_per_year=252.0)[source]
Rolling Rogers-Satchell OHLC realized volatility estimator (annualised).
Drift-invariant: unbiased for assets with non-zero expected return. Does not handle overnight gaps.
- Parameters:
open (ArrayLike) – Arrays of daily OHLC prices (same length, ≥ window).
high (ArrayLike) – Arrays of daily OHLC prices (same length, ≥ window).
low (ArrayLike) – Arrays of daily OHLC prices (same length, ≥ window).
close (ArrayLike) – Arrays of daily OHLC prices (same length, ≥ window).
window (int) – Rolling look-back period in bars (default 20).
trading_days_per_year (float) – Annualisation factor (default 252).
- Returns:
Same length as close. First
window - 1values are NaN.- Return type:
NDArray[float64]
Notes
Per-bar contribution (u = ln(H/O), d = ln(L/O), c = ln(C/O)):
RS = u·(u − c) + d·(d − c)
Reference: Rogers, L.C.G. & Satchell, S.E. (1991). “Estimating Variance from High, Low and Closing Prices.” Annals of Applied Probability, 1(4).
- ferro_ta.analysis.options.select_strike(strikes, reference_price, *, option_type='call', selector='ATM', delta_target=None, volatilities=None, time_to_expiry=None, model='bsm', rate=0.0, carry=0.0)[source]
Select a strike by ATM/ITM/OTM offset or delta target.
- ferro_ta.analysis.options.smile_metrics(strikes, vols, reference_price, time_to_expiry, *, model='bsm', rate=0.0, carry=0.0)[source]
Compute ATM IV, 25-delta RR/BF, skew slope, and convexity.
- ferro_ta.analysis.options.term_structure_slope(tenors, atm_ivs)[source]
Slope of ATM IV against tenor.
- Parameters:
tenors (ArrayLike)
atm_ivs (ArrayLike)
- Return type:
- ferro_ta.analysis.options.vol_cone(close, *, windows=(21, 42, 63, 126, 252), trading_days_per_year=252.0)[source]
Historical realised vol distribution across window lengths (volatility cone).
For each window, computes the full history of rolling close-to-close realised vol, then returns the min / p25 / median / p75 / max distribution. Contextualises current implied vol: “Is 30 % IV cheap or expensive?”
- Parameters:
- Returns:
Dataclass with arrays
windows,min,p25,median,p75,max— one value per element of windows.- Return type:
Notes
Uses close-to-close vol internally. Overlay the current IV on the cone to see whether it is historically cheap or expensive for each tenor.
Examples
>>> import numpy as np >>> from ferro_ta.analysis.options import vol_cone >>> rng = np.random.default_rng(0) >>> close = 100 * np.cumprod(np.exp(rng.normal(0, 0.01, 500))) >>> cone = vol_cone(close, windows=(21, 63, 252)) >>> cone.median # annualised median realised vol per window
- ferro_ta.analysis.options.yang_zhang_vol(open, high, low, close, window=20, trading_days_per_year=252.0)[source]
Rolling Yang-Zhang OHLC realized volatility estimator (annualised).
The most efficient standard estimator (~14× vs close-to-close). Handles overnight gaps by combining overnight, intraday open-close, and Rogers-Satchell variance components with an optimal weight k.
- Parameters:
open (ArrayLike) – Arrays of daily OHLC prices (same length, ≥ window + 1).
high (ArrayLike) – Arrays of daily OHLC prices (same length, ≥ window + 1).
low (ArrayLike) – Arrays of daily OHLC prices (same length, ≥ window + 1).
close (ArrayLike) – Arrays of daily OHLC prices (same length, ≥ window + 1).
window (int) – Rolling look-back period in bars (default 20).
trading_days_per_year (float) – Annualisation factor (default 252).
- Returns:
Same length as close. First
windowvalues are NaN.- Return type:
NDArray[float64]
Notes
Mixed estimator:
σ²_YZ = σ²_overnight + k·σ²_open_close + (1−k)·σ²_RS
where k = 0.34 / (1.34 + (window+1)/(window-1)).
Reference: Yang, D. & Zhang, Q. (2000). “Drift-Independent Volatility Estimation Based on High, Low, Open, and Close Prices.” Journal of Business, 73(3).
ferro_ta.analysis.futures — Futures and forward-curve analytics.
- class ferro_ta.analysis.futures.CurveSummary(front_basis: 'float', average_basis: 'float', slope: 'float', is_contango: 'bool')[source]
Bases:
object
- ferro_ta.analysis.futures.back_adjusted_continuous_contract(front, next_contract, next_weights)[source]
- ferro_ta.analysis.futures.curve_slope(tenors, futures_prices)[source]
- Parameters:
tenors (ArrayLike)
futures_prices (ArrayLike)
- Return type:
- ferro_ta.analysis.futures.curve_summary(spot, tenors, futures_prices)[source]
- Parameters:
spot (float)
tenors (ArrayLike)
futures_prices (ArrayLike)
- Return type:
- ferro_ta.analysis.futures.parity_gap(call_price, put_price, spot, strike, rate, time_to_expiry, *, carry=0.0)[source]
- ferro_ta.analysis.futures.ratio_adjusted_continuous_contract(front, next_contract, next_weights)[source]
- ferro_ta.analysis.futures.synthetic_forward(call_price, put_price, strike, rate, time_to_expiry)[source]
- ferro_ta.analysis.futures.synthetic_spot(call_price, put_price, strike, rate, time_to_expiry, *, carry=0.0)[source]
ferro_ta.analysis.options_strategy — Typed strategy parameter schemas.
- class ferro_ta.analysis.options_strategy.DerivativesStrategy(name: 'str', preset: 'LegPreset | str' = <LegPreset.CUSTOM: 'custom'>, legs: 'tuple[StrategyLeg, ...]'=<factory>, risk_controls: 'RiskControl' = <factory>, risk_mode: 'RiskMode | str' = <RiskMode.COMBINED_PNL: 'combined_pnl'>, commission: 'float' = 0.0, slippage: 'float' = 0.0, spread_assumption: 'float' = 0.0, limits: 'SimulationLimits' = <factory>)[source]
Bases:
object- Parameters:
name (str)
legs (tuple[StrategyLeg, ...])
risk_controls (RiskControl)
commission (float)
slippage (float)
spread_assumption (float)
limits (SimulationLimits)
- legs: tuple[StrategyLeg, ...]
- limits: SimulationLimits
- risk_controls: RiskControl
- class ferro_ta.analysis.options_strategy.ExpirySelector(kind: 'ExpirySelectorKind | str', explicit_date: 'date | None' = None)[source]
Bases:
object- Parameters:
kind (ExpirySelectorKind | str)
explicit_date (date | None)
- kind: ExpirySelectorKind | str
- class ferro_ta.analysis.options_strategy.ExpirySelectorKind(*values)[source]
-
- CURRENT_MONTH = 'current_month'
- CURRENT_WEEK = 'current_week'
- EXPLICIT_DATE = 'explicit_date'
- NEXT_MONTH = 'next_month'
- NEXT_WEEK = 'next_week'
- class ferro_ta.analysis.options_strategy.LegPreset(*values)[source]
-
- BEAR_PUT_SPREAD = 'bear_put_spread'
- BULL_CALL_SPREAD = 'bull_call_spread'
- CUSTOM = 'custom'
- IRON_CONDOR = 'iron_condor'
- STRADDLE = 'straddle'
- STRANGLE = 'strangle'
- class ferro_ta.analysis.options_strategy.RiskControl(stop_loss_type: 'str | None' = None, stop_loss_value: 'float | None' = None, target_type: 'str | None' = None, target_value: 'float | None' = None, trailstop_type: 'str | None' = None, trailstop_value: 'float | None' = None, breakeven_trigger: 'float | None' = None)[source]
Bases:
object- Parameters:
- class ferro_ta.analysis.options_strategy.RiskMode(*values)[source]
-
- COMBINED_PNL = 'combined_pnl'
- PER_LEG = 'per_leg'
- class ferro_ta.analysis.options_strategy.SimulationLimits(max_premium_outlay: 'float | None' = None, max_loss_per_trade: 'float | None' = None, daily_max_drawdown: 'float | None' = None, cooldown_bars: 'int' = 0, reentry_allowed: 'bool' = True)[source]
Bases:
object- Parameters:
- class ferro_ta.analysis.options_strategy.StrategyLeg(underlying: 'str', expiry_selector: 'ExpirySelector | None', strike_selector: 'StrikeSelector | None', option_type: 'str | None', side: 'str' = 'long', quantity: 'int' = 1, instrument: 'str' = 'option', premium_limit: 'float | None' = None)[source]
Bases:
object- Parameters:
underlying (str)
expiry_selector (ExpirySelector | None)
strike_selector (StrikeSelector | None)
option_type (str | None)
side (str)
quantity (int)
instrument (str)
premium_limit (float | None)
- expiry_selector: ExpirySelector | None
- strike_selector: StrikeSelector | None
- class ferro_ta.analysis.options_strategy.StrikeSelector(kind: 'StrikeSelectorKind | str', steps: 'int' = 0, delta: 'float | None' = None, explicit_strike: 'float | None' = None)[source]
Bases:
object- Parameters:
kind (StrikeSelectorKind | str)
steps (int)
delta (float | None)
explicit_strike (float | None)
- kind: StrikeSelectorKind | str
- class ferro_ta.analysis.options_strategy.StrikeSelectorKind(*values)[source]
-
- ATM = 'atm'
- DELTA = 'delta'
- EXPLICIT = 'explicit'
- ITM = 'itm'
- OTM = 'otm'
- ferro_ta.analysis.options_strategy.build_strategy_preset(preset, *, name, underlying, expiry_selector, base_strike_selector=None, risk_controls=None, risk_mode=RiskMode.COMBINED_PNL, commission=0.0, slippage=0.0, spread_assumption=0.0, limits=None)[source]
Build a common research preset using typed leg definitions.
- Parameters:
name (str)
underlying (str)
expiry_selector (ExpirySelector)
base_strike_selector (StrikeSelector | None)
risk_controls (RiskControl | None)
commission (float)
slippage (float)
spread_assumption (float)
limits (SimulationLimits | None)
- Return type:
ferro_ta.analysis.derivatives_payoff — Multi-leg payoff and Greeks aggregation.
- class ferro_ta.analysis.derivatives_payoff.PayoffLeg(instrument: 'str', side: 'str', quantity: 'float' = 1.0, option_type: 'str | None' = None, strike: 'float | None' = None, premium: 'float' = 0.0, entry_price: 'float | None' = None, volatility: 'float | None' = None, time_to_expiry: 'float | None' = None, rate: 'float' = 0.0, carry: 'float' = 0.0, multiplier: 'float' = 1.0)[source]
Bases:
object- Parameters:
- ferro_ta.analysis.derivatives_payoff.aggregate_greeks(spot, *, legs=None, strategy=None)[source]
Aggregate Greeks across option and futures legs.
- Parameters:
- Return type:
- ferro_ta.analysis.derivatives_payoff.futures_leg_payoff(spot_grid, *, entry_price, side='long', quantity=1.0, multiplier=1.0)[source]
P/L profile for a futures leg.
- ferro_ta.analysis.derivatives_payoff.option_leg_payoff(spot_grid, *, strike, premium=0.0, option_type='call', side='long', quantity=1.0, multiplier=1.0)[source]
Expiry payoff for a single option leg.
- ferro_ta.analysis.derivatives_payoff.stock_leg_payoff(spot_grid, *, entry_price, side='long', quantity=1.0, multiplier=1.0)[source]
P/L profile for a single stock (equity) leg over a spot grid.
Payoff is linear:
P/L = sign(side) × quantity × multiplier × (spot − entry_price)
Mathematically equivalent to a futures leg — no optionality. Use this leg type when modelling strategies that hold the underlying equity: Covered Call, Protective Put, Collar, Covered Strangle, etc.
- Parameters:
spot_grid (ArrayLike) – 1-D array of spot prices at which to evaluate the P/L.
entry_price (float) – Purchase (or short-sale) price of the stock.
side (str) –
"long"(default) or"short".quantity (float) – Number of shares / contracts (default 1).
multiplier (float) – Contract multiplier (default 1.0).
- Returns:
P/L at each grid point, same shape as spot_grid.
- Return type:
NDArray[float64]
- ferro_ta.analysis.derivatives_payoff.strategy_payoff(spot_grid, *, legs=None, strategy=None)[source]
Aggregate expiry payoff across option and futures legs.
- ferro_ta.analysis.derivatives_payoff.strategy_value(spot_grid, *, legs, time_to_expiry, volatility, rate=0.0, carry=0.0)[source]
Current BSM mid-price value of a multi-leg strategy over a spot grid.
Unlike
strategy_payoff()(which computes intrinsic value at expiry), this uses live BSM pricing for option legs so the result reflects the pre-expiry value including time value.- Parameters:
spot_grid (ArrayLike) – Array of spot prices to evaluate.
legs (Sequence[PayoffLeg | Mapping[str, Any]]) – Sequence of
PayoffLeg(or dicts). Option legs must havestrikeandpremiumset; future/stock legs must haveentry_priceset.time_to_expiry (float) – Shared time-to-expiry (years) applied to all option legs.
volatility (float) – Shared implied vol applied to all option legs.
rate (float) – Risk-free rate applied to all legs.
carry (float) – Carry / dividend yield applied to all option legs.
- Return type: