Option Pricing
quantmod provides three option pricing engines under quantmod.models:
- GBS (Generalized Black-Scholes) — analytical pricing for European options across four models
- Binomial Tree — flexible tree model supporting American and European exercise
- Monte Carlo — simulation-based pricing for European, Asian, Barrier, and American options
1. Generalized Black-Scholes (GBS)
The BlackScholes, Merton, Black76, and GarmanKohlhagen classes share a unified interface and return an OptionGreeks dataclass containing call/put prices and all first-order Greeks.
Black-Scholes — non-dividend paying stock
from quantmod.models import OptionInputs, BlackScholes
inputs = OptionInputs(spot=100, strike=100, rate=0.05, ttm=1.0, volatility=0.20)
bs = BlackScholes(inputs)
print(bs.results())
──────────────────────────────────────────────────────
Black-Scholes
──────────────────────────────────────────────────────
d1 = 0.350000 d2 = 0.150000
──────────────────────────────────────────────────────
Call Put
Price 10.4506 5.5735
Delta 0.636831 -0.363169
Gamma 0.018762 0.018762
Vega (per 1%) 0.375240 0.375240
Theta (per day) -0.017573 -0.004542
Rho (per 1%) 0.532325 -0.418905
──────────────────────────────────────────────────────
Implied Vol : 0.200000 (20.000%)
──────────────────────────────────────────────────────
Implied Volatility
Pass a market price via callprice or putprice to back out implied volatility:
inputs = OptionInputs(spot=100, strike=100, rate=0.05, ttm=1.0,
volatility=0.20, callprice=12.0)
bs = BlackScholes(inputs)
print(f"Implied Vol: {bs.impvol:.4f}")
Merton — continuous dividend yield
from quantmod.models import Merton
mt = Merton(OptionInputs(spot=100, strike=100, rate=0.05, ttm=1.0,
volatility=0.20, dividend_yield=0.03))
print(mt.results())
Black-76 — futures and forwards
from quantmod.models import Black76
# spot is interpreted as the futures price F
b76 = Black76(OptionInputs(spot=100, strike=100, rate=0.05, ttm=1.0, volatility=0.20))
print(b76.results())
Garman-Kohlhagen — FX options
from quantmod.models import GarmanKohlhagen
gk = GarmanKohlhagen(OptionInputs(
spot=1.10, strike=1.10, rate=0.03, ttm=0.25,
volatility=0.08, foreign_rate=0.01,
))
print(gk.results())
price_option convenience factory
Select the model by string for quick one-liners:
from quantmod.models import price_option
# "bs" | "merton" | "b76" | "gk"
res = price_option("merton", spot=100, strike=100, rate=0.05, ttm=1.0,
volatility=0.20, dividend_yield=0.03)
print(res.call_price, res.put_price)
2. Binomial Tree
BinomialOptionPricing supports American and European exercise and can visualise the full tree.
from quantmod.models import OptionInputs, BinomialOptionPricing, OptionType, ExerciseStyle
inputs = OptionInputs(spot=100, strike=100, rate=0.05, ttm=1.0, volatility=0.20)
binomial = BinomialOptionPricing(
inputs=inputs,
nsteps=4,
option_type=OptionType.PUT,
exercise_style=ExerciseStyle.AMERICAN,
output="delta",
)
print(f"Option {binomial.output} tree:")
print(binomial.binomialoption)
# Visualise the tree
binomial.plot_tree()
The output parameter controls what is displayed in the tree nodes:
| Value | Description |
|---|---|
"price" |
Underlying asset prices |
"payoff" |
Intrinsic payoff at each node |
"value" |
Option value (backward induction) |
"delta" |
Delta at each node |
3. Monte Carlo
MonteCarloOptionPricing supports multiple exercise styles and two sampling methods.
European option — pseudo-random with antithetic variates
from quantmod.models import OptionInputs, MonteCarloOptionPricing, OptionType
inputs = OptionInputs(spot=100, strike=100, rate=0.05, ttm=1.0, volatility=0.20)
mc = MonteCarloOptionPricing(
inputs,
n_simulations=100_000,
option_type=OptionType.CALL,
seed=42,
)
print(mc.results())
──────────────────────────────────────────────────
Monte Carlo Option Price
──────────────────────────────────────────────────
Price : 10.452341
Std Error : 0.033241
95% CI : [10.387189, 10.517492]
Simulations : 100,000
Sampler : pseudo
──────────────────────────────────────────────────
European option — Sobol quasi-random (faster convergence)
mc = MonteCarloOptionPricing(
inputs,
n_simulations=8_192, # rounded up to nearest power of 2 automatically
option_type=OptionType.CALL,
sampler="sobol",
)
print(mc.results())
Asian option
from quantmod.models import ExerciseStyle
mc = MonteCarloOptionPricing(
inputs,
n_simulations=50_000,
option_type=OptionType.CALL,
exercise_style=ExerciseStyle.ASIAN,
seed=42,
)
print(f"Asian call price: {mc.results().price:.4f}")
Barrier options — all four types
from quantmod.models import BarrierType
# Up-and-Out: option expires worthless if spot breaches barrier from below
mc = MonteCarloOptionPricing(
inputs,
n_simulations=50_000,
n_steps=252,
option_type=OptionType.CALL,
exercise_style=ExerciseStyle.BARRIER,
barrier_level=120.0,
barrier_rebate=0.0,
barrier_type=BarrierType.UP_AND_OUT,
sampler="sobol",
)
print(mc.results())
| Barrier type | Knock condition | Payoff when triggered |
|---|---|---|
UP_AND_OUT |
max path ≥ barrier | rebate (knocked out) |
UP_AND_IN |
max path ≥ barrier | vanilla (activated) |
DOWN_AND_OUT |
min path ≤ barrier | rebate (knocked out) |
DOWN_AND_IN |
min path ≤ barrier | vanilla (activated) |