With syntetic market price#
Here with an Heston model.
[ ]:
from hestonpy.models.heston import Heston
from hestonpy.models.calibration.volatilitySmile import VolatilitySmile
import numpy as np
r = 0.00
Some parameters
[3]:
spot = 100
time_to_maturity = 1
true_params = {
"vol_initial": 0.06,
"kappa": 1.25,
"theta": 0.06,
"sigma": 0.6,
"rho": -0.5,
"drift_emm": 0.00,
}
vol = np.sqrt(0.04)
heston = Heston(spot=spot, r=r, **true_params)
price_function = heston.call_price
strikes = np.linspace(70, 140, 10)
Without noise#
[4]:
market_prices = price_function(**true_params, strike=strikes, time_to_maturity=time_to_maturity, s=spot)
volSmile = VolatilitySmile(
strikes=strikes,
time_to_maturity=time_to_maturity,
atm=spot,
market_prices=market_prices,
r=r
)
volSmile.plot()

Local optimization#
[5]:
calibrated_params = volSmile.calibration(
price_function=price_function,
initial_guess = [1.0, 0.03, 0.4, -0.5],
guess_correlation_sign='negative',
speed='local',
)
calibrated_heston = Heston(spot=spot, r=r, **calibrated_params)
volSmile.plot(calibrated_prices=heston.call_price(strike=strikes, time_to_maturity=time_to_maturity))
calibrated_params
Calibrated parameters: v0=0.046 | kappa=0.985 | theta=0.085 | sigma=0.580 | rho=-0.506

[5]:
{'vol_initial': np.float64(0.04589503493265889),
'kappa': np.float64(0.9849851420478373),
'theta': np.float64(0.08456116488309652),
'sigma': np.float64(0.580145120734101),
'rho': np.float64(-0.5063722128514593),
'drift_emm': 0}
[6]:
true_params
[6]:
{'vol_initial': 0.06,
'kappa': 1.25,
'theta': 0.06,
'sigma': 0.6,
'rho': -0.5,
'drift_emm': 0.0}
Global optimization#
[7]:
calibrated_params = volSmile.calibration(
price_function=price_function,
initial_guess = [1.0, 0.03, 0.4, -0.5],
guess_correlation_sign='negative',
speed='global',
)
calibrated_heston = Heston(spot=spot, r=r, **calibrated_params)
volSmile.plot(calibrated_prices=heston.call_price(strike=strikes, time_to_maturity=time_to_maturity))
calibrated_params
at minimum 0.000002 accepted 1
Parameters: kappa=0.985 | theta=0.085 | sigma=0.580 | rho=-0.506
at minimum 0.000309 accepted 1
Parameters: kappa=0.021 | theta=1.289 | sigma=0.390 | rho=-0.519
at minimum 0.000310 accepted 1
Parameters: kappa=0.020 | theta=1.367 | sigma=0.390 | rho=-0.519
at minimum 0.000317 accepted 1
Parameters: kappa=0.011 | theta=2.352 | sigma=0.388 | rho=-0.520
at minimum 0.000314 accepted 1
Parameters: kappa=0.015 | theta=1.816 | sigma=0.389 | rho=-0.520
at minimum 0.000309 accepted 1
Parameters: kappa=0.021 | theta=1.322 | sigma=0.390 | rho=-0.519
['success condition satisfied'] True
Calibrated parameters: v0=0.046 | kappa=0.985 | theta=0.085 | sigma=0.580 | rho=-0.506

[7]:
{'vol_initial': np.float64(0.04589503493265889),
'kappa': np.float64(0.9849851420478373),
'theta': np.float64(0.08456116488309652),
'sigma': np.float64(0.580145120734101),
'rho': np.float64(-0.5063722128514593),
'drift_emm': 0}
[8]:
true_params
[8]:
{'vol_initial': 0.06,
'kappa': 1.25,
'theta': 0.06,
'sigma': 0.6,
'rho': -0.5,
'drift_emm': 0.0}
With noise#
[9]:
market_prices = market_prices * (1 + np.random.normal(scale=0.01, size=len(market_prices))) # a little of market noise
volSmile = VolatilitySmile(
strikes=strikes,
time_to_maturity=time_to_maturity,
atm=spot,
market_prices=market_prices,
r=r
)
volSmile.plot()

Local optimization#
[10]:
calibrated_params = volSmile.calibration(
price_function=price_function,
initial_guess = [1.0, 0.03, 0.4, -0.5],
guess_correlation_sign='negative',
speed='local',
)
calibrated_heston = Heston(spot=spot, r=r, **calibrated_params)
volSmile.plot(calibrated_prices=heston.call_price(strike=strikes, time_to_maturity=time_to_maturity))
calibrated_params
Calibrated parameters: v0=0.047 | kappa=1.637 | theta=0.078 | sigma=0.813 | rho=-0.505

[10]:
{'vol_initial': np.float64(0.04748090898419823),
'kappa': np.float64(1.6367968439862783),
'theta': np.float64(0.07784948797483981),
'sigma': np.float64(0.8134296600989249),
'rho': np.float64(-0.5052904061780317),
'drift_emm': 0}
Global optimization#
[11]:
calibrated_params = volSmile.calibration(
price_function=price_function,
initial_guess = [1.0, 0.03, 0.4, -0.5],
guess_correlation_sign='negative',
speed='global',
)
calibrated_heston = Heston(spot=spot, r=r, **calibrated_params)
volSmile.plot(calibrated_prices=heston.call_price(strike=strikes, time_to_maturity=time_to_maturity))
calibrated_params
at minimum 0.031536 accepted 1
Parameters: kappa=1.637 | theta=0.078 | sigma=0.813 | rho=-0.505
at minimum 0.035471 accepted 1
Parameters: kappa=0.011 | theta=2.569 | sigma=0.425 | rho=-0.525
at minimum 0.035471 accepted 1
Parameters: kappa=0.011 | theta=2.564 | sigma=0.425 | rho=-0.525
at minimum 0.035472 accepted 1
Parameters: kappa=0.010 | theta=2.618 | sigma=0.425 | rho=-0.525
['success condition satisfied'] True
Calibrated parameters: v0=0.047 | kappa=1.637 | theta=0.078 | sigma=0.813 | rho=-0.505

[11]:
{'vol_initial': np.float64(0.04748090898419823),
'kappa': np.float64(1.6367968439862783),
'theta': np.float64(0.07784948797483981),
'sigma': np.float64(0.8134296600989249),
'rho': np.float64(-0.5052904061780317),
'drift_emm': 0}