Derivatives¶
This notebook walks through AbaQuant’s core derivatives-pricing toolkit: vanilla options (Black–Scholes and Black-76), Greeks, binomial trees, forward contracts, exotic options, and composable option strategies.
Sections:
Vanilla option pricing
Greek ladders (first- and second-order)
Binomial-tree models (European vs. American)
Forward contracts
Exotic options
Composable option strategies
Setup¶
import abaquant
print(f"AbaQuant version: {abaquant.__version__}")
AbaQuant version: 1.0.0rc1
from abaquant.derivatives.exotics import (
asset_or_nothing_options,
cash_or_nothing_options,
down_and_out_barrier_option,
exchange_options,
geometric_asian_options,
)
from abaquant.derivatives.forwards import forward_contract_value, forward_price, fx_forward_price
from abaquant.derivatives.strategies import OptionStrategy, strategy_profile
from abaquant.derivatives.trees import binomial_tree, crr_binomial_tree
from abaquant.derivatives.vanilla import (
black_76,
black_scholes,
calculate_greeks,
implied_volatility_bsm,
second_order_greeks,
)
1. Vanilla option pricing¶
black_scholes prices European options under the classic lognormal model.
black_76 prices options on forwards/futures. implied_volatility_bsm
inverts a market price to recover the volatility the market is implying.
call_price = black_scholes(100.0, 100.0, 0.05, 0.20, 1.0, is_call=True)
put_price = black_scholes(100.0, 100.0, 0.05, 0.20, 1.0, is_call=False)
future_option = black_76(102.0, 100.0, 0.05, 0.20, 1.0, is_call=True)
solved_volatility = implied_volatility_bsm(call_price, 100.0, 100.0, 0.05, 1.0)
print(f"European call price: {call_price:.4f}")
print(f"European put price: {put_price:.4f}")
print(f"Black-76 call price: {future_option:.4f}")
print(f"Implied volatility (BSM): {solved_volatility:.4f}")
European call price: 10.4506
European put price: 5.5735
Black-76 call price: 8.6414
Implied volatility (BSM): 0.2000
2. Greek ladders¶
First-order Greeks (delta, gamma, vega, theta, rho) describe local sensitivities. Second-order Greeks (vanna, vomma, …) capture how those sensitivities themselves change.
first_order = calculate_greeks(100.0, 100.0, 0.05, 0.20, 1.0, is_call=True)
second_order = second_order_greeks(100.0, 100.0, 0.05, 0.0, 0.20, 1.0, is_call=True)
print("First-order Greeks:")
for greek in ("delta", "gamma", "vega"):
print(f" {greek:8s}: {first_order[greek]:.6f}")
print("\nSecond-order Greeks:")
for greek in ("vanna", "vomma"):
print(f" {greek:8s}: {second_order[greek]:.6f}")
First-order Greeks:
delta : 0.636831
gamma : 0.018762
vega : 0.375240
Second-order Greeks:
vanna : -0.281430
vomma : 0.098501
3. Binomial-tree models¶
Trees are useful for American-exercise options and for pedagogical inspection of the underlying lattice. We compare European vs. American exercise on the same put, then price a call with the Cox–Ross–Rubinstein (CRR) convention.
european_price, _ = binomial_tree(100.0, 100.0, 1.0, 0.05, 0.20, 80, option_type="put")
american_price, _ = binomial_tree(
100.0, 100.0, 1.0, 0.05, 0.20, 80, option_type="put", american=True
)
crr_price, _, _ = crr_binomial_tree(100.0, 100.0, 0.05, 0.20, 1.0, 80, is_call=True)
print(f"European put (tree): {european_price:.4f}")
print(f"American put (tree): {american_price:.4f} (>= European due to early-exercise value)")
print(f"CRR call: {crr_price:.4f}")
European put (tree): 5.5486
American put (tree): 6.0801 (>= European due to early-exercise value)
CRR call: 10.4256
4. Forward contracts¶
Forward pricing under carry, an FX forward via interest-rate parity, and the mark-to-market value of an existing forward position.
equity_fwd = forward_price(100.0, 0.05, 1.0)
fx_fwd = fx_forward_price(18.0, 0.07, 0.04, 1.0)
long_fwd_value = forward_contract_value(105.0, 100.0, 0.05, 0.01, 0.5)
print(f"Equity forward price: {equity_fwd:.4f}")
print(f"FX forward price: {fx_fwd:.4f}")
print(f"Long forward contract value: {long_fwd_value:.4f}")
Equity forward price: 105.1271
FX forward price: 18.5482
Long forward contract value: 6.9453
5. Exotic options¶
A sample of closed-form exotic payoffs: digitals, geometric Asians, a down-and-out barrier, and an exchange (Margrabe-style) option.
exotic_prices = {
"cash_or_nothing_call": cash_or_nothing_options(100.0, 100.0, 10.0, 1.0, 0.05, 0.20),
"asset_or_nothing_call": asset_or_nothing_options(100.0, 100.0, 1.0, 0.05, 0.20),
"geometric_asian_call": geometric_asian_options(100.0, 100.0, 1.0, 0.05, 0.20),
"down_and_out_call": down_and_out_barrier_option(100.0, 100.0, 80.0, 1.0, 0.05, 0.20),
"exchange_option": exchange_options(100.0, 95.0, 0.01, 0.02, 0.20, 0.25, 0.4, 1.0),
}
for name, price in exotic_prices.items():
print(f"{name:24s}: {price:.4f}")
cash_or_nothing_call : 5.3232
asset_or_nothing_call : 63.6831
geometric_asian_call : 5.5468
down_and_out_call : 10.3513
exchange_option : 6.8970
6. Composable option strategies¶
OptionStrategy lets you build multi-leg strategies (spreads, straddles,
condors, …) and inspect payoff, profit, and break-even diagnostics.
strategy = OptionStrategy.bull_call_spread(
lower_strike=100.0,
upper_strike=115.0,
lower_premium=6.0,
upper_premium=2.0,
)
table = strategy.profile(points=6)
table[["spot_price", "gross_payoff", "net_profit"]].head()
| spot_price | gross_payoff | net_profit | |
|---|---|---|---|
| 0 | 0.0 | 0.0 | -4.0 |
| 1 | 46.0 | 0.0 | -4.0 |
| 2 | 92.0 | 0.0 | -4.0 |
| 3 | 138.0 | 15.0 | 11.0 |
| 4 | 184.0 | 15.0 | 11.0 |
print(f"Profit at spot=125: {strategy.payoff(125.0):.4f}")
print(f"Maximum profit: {strategy.max_profit():.4f}")
print(f"Maximum loss: {strategy.max_loss():.4f}")
print(f"Break-even point(s): {strategy.break_even_points()}")
Profit at spot=125: 11.0000
Maximum profit: 11.0000
Maximum loss: -4.0000
Break-even point(s): [104.0]
A legacy dictionary-based strategy helper is also available for quick one-off payoff tables:
legacy_table = strategy_profile(
spot=100.0,
legs=[
{"option_type": "call", "position": 1, "strike": 100.0, "premium": 6.0},
{"option_type": "call", "position": -1, "strike": 115.0, "premium": 2.0},
],
points=4,
)
legacy_table[["S_T", "Net Payoff"]]
| S_T | Net Payoff | |
|---|---|---|
| 0 | 50.000000 | -4.0 |
| 1 | 83.333333 | -4.0 |
| 2 | 116.666667 | 11.0 |
| 3 | 150.000000 | 11.0 |
Takeaway¶
This covers the core vanilla, tree-based, forward, exotic, and
strategy-building blocks in abaquant.derivatives. For advanced stochastic
models (Heston, SABR, Merton jump-diffusion, NIG, Variance-Gamma), see
notebook 03 — Derivatives: Advanced Models.