3e0f289d51
- Bumped version numbers across Cargo.toml, Cargo.lock, pyproject.toml, and conda/meta.yaml to 1.1.3. - Added new features including American option pricing, digital options, extended Greeks, and historical volatility estimators. - Enhanced documentation and tests for new functionalities. - Updated CHANGELOG.md to reflect changes for version 1.1.3.
7.4 KiB
7.4 KiB
Derivatives Analytics
ferro-ta ships a Rust-backed derivatives analytics layer focused on
research, simulation, and risk analysis. All functions are implemented in
Rust core and exposed to Python (via PyO3) and WebAssembly (via wasm-bindgen).
Modules
ferro_ta.analysis.options
| Category | Functions |
|---|---|
| Pricing | black_scholes_price, black_76_price, option_price |
| Greeks | greeks, extended_greeks |
| Implied vol | implied_volatility, iv_rank, iv_percentile, iv_zscore |
| Digital options | digital_option_price, digital_option_greeks |
| American options | american_option_price, early_exercise_premium |
| Smile / surface | smile_metrics, term_structure_slope, expected_move |
| Chain helpers | label_moneyness, select_strike |
| Realised vol | close_to_close_vol, parkinson_vol, garman_klass_vol, rogers_satchell_vol, yang_zhang_vol |
| Vol cone | vol_cone |
| Diagnostics | put_call_parity_deviation |
ferro_ta.analysis.futures
- Synthetic forwards and parity diagnostics
- Basis, annualized basis, implied carry, carry spread
- Continuous contract stitching: weighted, back-adjusted, ratio-adjusted
- Curve analytics: calendar spreads, slope, contango summary
ferro_ta.analysis.options_strategy
Typed strategy schemas: expiry selectors, strike selectors, multi-leg presets
(STRADDLE, STRANGLE, IRON_CONDOR, BULL_CALL_SPREAD, BEAR_PUT_SPREAD),
risk controls, cost assumptions, and simulation limits.
ferro_ta.analysis.derivatives_payoff
Multi-leg payoff and Greeks aggregation supporting option, future, and stock instrument types.
| Function | Description |
|---|---|
option_leg_payoff |
Expiry P/L for a single option leg |
futures_leg_payoff |
Linear P/L for a futures leg |
stock_leg_payoff |
Linear P/L for a stock/equity leg |
strategy_payoff |
Aggregate expiry payoff across all legs |
strategy_value |
Pre-expiry BSM mid-price value of a multi-leg strategy |
aggregate_greeks |
Portfolio-level Greeks across option, futures, and stock legs |
Model conventions
| Parameter | Convention |
|---|---|
model="bsm" |
Underlying is spot; carry = continuous dividend yield |
model="black76" |
Underlying is the forward price |
volatility / rate / carry |
Decimal annual (e.g. 0.20 = 20 %, 0.05 = 5 %) |
time_to_expiry |
Years (e.g. 0.25 = 3 months) |
Quick examples
BSM pricing and Greeks
from ferro_ta.analysis.options import greeks, implied_volatility, option_price
price = option_price(100.0, 100.0, 0.05, 1.0, 0.20, option_type="call")
iv = implied_volatility(price, 100.0, 100.0, 0.05, 1.0, option_type="call")
g = greeks(100.0, 100.0, 0.05, 1.0, 0.20, option_type="call")
print(price, iv, g.delta, g.gamma)
Extended (second-order) Greeks
from ferro_ta.analysis.options import extended_greeks
eg = extended_greeks(100.0, 100.0, 0.05, 1.0, 0.20, option_type="call")
print(eg.vanna, eg.volga, eg.charm, eg.speed, eg.color)
Digital options
from ferro_ta.analysis.options import digital_option_price, digital_option_greeks
# Cash-or-nothing call at ATM ≈ e^{-rT} * N(d2) ≈ 0.53
price = digital_option_price(100.0, 100.0, 0.05, 1.0, 0.20,
option_type="call", digital_type="cash_or_nothing")
g = digital_option_greeks(100.0, 100.0, 0.05, 1.0, 0.20,
option_type="call", digital_type="cash_or_nothing")
print(price, g.delta, g.gamma, g.vega)
American options (BAW approximation)
from ferro_ta.analysis.options import american_option_price, early_exercise_premium
# American put — may have meaningful early exercise premium
american = american_option_price(100.0, 100.0, 0.05, 1.0, 0.20, option_type="put")
premium = early_exercise_premium(100.0, 100.0, 0.05, 1.0, 0.20, option_type="put")
print(american, premium)
Historical volatility estimators
import numpy as np
from ferro_ta.analysis.options import (
close_to_close_vol, garman_klass_vol, parkinson_vol,
rogers_satchell_vol, yang_zhang_vol,
)
# Assume daily OHLC arrays of length N
open_p, high_p, low_p, close_p = ... # numpy arrays
ctc = close_to_close_vol(close_p, window=20) # close-only
park = parkinson_vol(high_p, low_p, window=20) # high-low
gk = garman_klass_vol(open_p, high_p, low_p, close_p, window=20)
rs = rogers_satchell_vol(open_p, high_p, low_p, close_p, window=20)
yz = yang_zhang_vol(open_p, high_p, low_p, close_p, window=20)
Volatility cone
from ferro_ta.analysis.options import vol_cone
cone = vol_cone(close_p, windows=(21, 42, 63, 126, 252))
# Overlay current IV against the cone to gauge richness/cheapness
for w, med in zip(cone.windows, cone.median):
print(f"window={int(w):3d} median_rv={med:.1%}")
Put-call parity check
from ferro_ta.analysis.options import option_price, put_call_parity_deviation
call = option_price(100.0, 100.0, 0.05, 1.0, 0.20, option_type="call")
put = option_price(100.0, 100.0, 0.05, 1.0, 0.20, option_type="put")
dev = put_call_parity_deviation(call, put, 100.0, 100.0, 0.05, 1.0)
# dev ≈ 0.0 for BSM-consistent prices; non-zero signals stale/mismatched quotes
Expected move
from ferro_ta.analysis.options import expected_move
lower, upper = expected_move(100.0, 0.20, days_to_expiry=30)
print(f"Expected ±1σ range: [{100+lower:.2f}, {100+upper:.2f}]")
Multi-leg strategies with stock
import numpy as np
from ferro_ta.analysis.derivatives_payoff import PayoffLeg, strategy_payoff, strategy_value
# Covered Call: long 100 shares + short 1 OTM call
spot_grid = np.linspace(80, 130, 100)
legs = [
PayoffLeg("stock", "long", entry_price=100.0),
PayoffLeg("option", "short", option_type="call",
strike=110.0, premium=3.0, volatility=0.20, time_to_expiry=0.25),
]
# Expiry P/L
payoff = strategy_payoff(spot_grid, legs=legs)
# Pre-expiry BSM value (T=3 months remaining)
value = strategy_value(spot_grid, legs=legs, time_to_expiry=0.25, volatility=0.20)
Futures analytics
from ferro_ta.analysis.futures import basis, curve_summary
print(basis(100.0, 103.0))
print(curve_summary(100.0, [0.1, 0.5, 1.0], [101.0, 102.0, 104.0]))
Instrument types in PayoffLeg / StrategyLeg
instrument |
Required fields | Payoff |
|---|---|---|
"option" |
option_type, strike, expiry_selector, strike_selector |
max(φ(S−K), 0) − premium |
"future" |
entry_price |
S − entry_price |
"stock" |
entry_price |
S − entry_price (identical to future, no margin) |
Volatility estimator efficiency comparison
| Estimator | Relative efficiency vs close-to-close | Handles overnight gaps |
|---|---|---|
| Close-to-close | 1× (baseline) | N/A (uses close only) |
| Parkinson | ~5× | No |
| Garman-Klass | ~7.4× | No |
| Rogers-Satchell | ~8× | No |
| Yang-Zhang | ~14× | Yes |
Use Yang-Zhang when you have overnight gaps (futures, crypto). Use Parkinson or Garman-Klass for continuous trading sessions.
Notes
- All existing function names (
iv_rank,iv_percentile,iv_zscore,greeks,option_price, etc.) are preserved — fully backward compatible. - The derivatives layer is analytics-only: no broker connectivity, order routing, or execution workflow.
- WASM: all functions in this layer are also exported as WebAssembly bindings
(see
wasm/src/lib.rs).