Option Pricing¶
This tutorial shows how to price a single European option using the OptionPricer.
When calculating the option price from a option pricer, the result is a ModelOptionPrice containing the price, delta, and gamma in forward space as well as the implied Black volatility and its sensitivities delta, gamma, vega, etc.
Model sensitivities such as delta and gamma are calculated using the model dynamics, and will differ from the Black-Scholes deltas and gammas. The implied Black vol is the volatility that, when plugged into the Black formula, gives the same price as the model price. The Black deltas and gammas are calculated by plugging the implied vol into the Black formula.
Validation with Black-Scholes¶
The first example shows how to price an option using the Black-Scholes model and validate the results against the analytical Black formula. The implied volatility should be the same as the model volatility, and the deltas and gammas should be the same as well (within numerical precision).
from quantflow.options.inputs import OptionType
from quantflow.options.pricer import OptionPricer
from quantflow.sp.wiener import WienerProcess
# Wiener process with constant volatility
# This produces the same sensitivities as the Black-Scholes model
pricer = OptionPricer(model=WienerProcess(sigma=0.3))
# Price an ATM call option at time to maturity 1.0
price = pricer.price(
option_type=OptionType.call,
strike=100.0,
forward=100.0,
ttm=1.0,
)
print(price.model_dump_json(indent=2))
{
"strike": "100.0",
"option_type": "call",
"forward": "100.0",
"log_strike": 0.0,
"moneyness": 0.0,
"ttm": 1.0,
"price": 0.1192353847395493,
"delta": 0.5596050696630988,
"gamma": 1.314708420617837,
"black": {
"iv": 0.29999999999762783,
"price": 0.1192353847395493,
"delta": 0.5596176923697747,
"gamma": 1.314931103036928,
"vega": 0.3944793309079591,
"volga": -0.029585949817862993,
"vanna": 0.19723966545397956,
"theta": -0.05917189963572598
}
}
Heston with Jumps¶
The underlying model is HestonJ, a Heston stochastic volatility model extended with jumps drawn from a DoubleExponential distribution.
from quantflow.options.inputs import OptionType
from quantflow.options.pricer import OptionPricer
from quantflow.sp.heston import HestonJ
from quantflow.utils.distributions import DoubleExponential
pricer = OptionPricer(
model=HestonJ.create(
DoubleExponential,
vol=0.5,
kappa=2,
rho=-0.2,
sigma=0.8,
jump_fraction=0.5,
jump_asymmetry=0.2,
)
)
# Price an ATM call option at time to maturity 1.0
price = pricer.price(
option_type=OptionType.call,
strike=100.0,
forward=100.0,
ttm=1.0,
)
print(price.model_dump_json(indent=2))
{
"strike": "100.0",
"option_type": "call",
"forward": "100.0",
"log_strike": 0.0,
"moneyness": 0.0,
"ttm": 1.0,
"price": 0.19225250948685713,
"delta": 0.6005032446437887,
"gamma": 0.8150053886598254,
"black": {
"iv": 0.4866658752351474,
"price": 0.19225250948685713,
"delta": 0.5961262547434286,
"gamma": 0.7958325231787754,
"vega": 0.3873045314333945,
"volga": -0.0471219746931429,
"vanna": 0.19365226571669725,
"theta": -0.0942439493862858
}
}