Skip to content

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)

American option — Longstaff-Schwartz

mc = MonteCarloOptionPricing(
    inputs,
    n_simulations=50_000,
    n_steps=100,
    option_type=OptionType.PUT,
    exercise_style=ExerciseStyle.AMERICAN,
    seed=42,
)
print(f"American put: {mc.results().price:.4f}")