Files
ferro-ta/docs/derivatives-analytics.md
Pratik Bhadane 3e0f289d51 chore: update ferro-ta version to 1.1.3 (#8)
- 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.
2026-04-02 16:38:32 +05:30

7.4 KiB
Raw Permalink Blame History

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(φ(SK), 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).