[7]:
from hestonpy.models.heston import Heston
import matplotlib.pyplot as plt
import numpy as np
Hedging with Heston#
We delta and vega hedge with an other call with 110% of strike and 120% of time to maturity
[8]:
# Parameters for the Heston model
S0 = 100.0 # Initial spot price
V0 = 0.06 # Initial volatility
r = 0.03 # Risk-free interest rate
params = {
'kappa': 1.0, # Mean reversion rate
'theta': 0.06, # Long-term volatility
'drift_emm': 0.00, # Drift term
'sigma': 0.3, # Volatility of volatility
'rho': -0.5, # Correlation between asset and volatility
}
heston = Heston(spot=S0, vol_initial=V0, r=r, **params)
strike = 100
strike_hedging = 110
maturity = 1
maturity_hedging = 1.2
nbr_points = 252
nbr_simulations = 1000
portfolio, S, V, C = heston.delta_vega_hedging(
strike,
strike_hedging,
maturity,
maturity_hedging,
nbr_points,
nbr_simulations
)
Computing option prices ...
Computing vegas ...
Computing deltas ...
100%|██████████| 251/251 [00:00<00:00, 9276.82it/s]
Replication errors#
Sanity check of the replication
[9]:
ST = S[:, -1]
VT = portfolio[:, -1]
plt.figure(figsize=(5, 5))
plt.title("Réplication du payoff")
plt.grid(linestyle="--", dashes=(5, 10), color="gray", linewidth=0.5)
plt.minorticks_on()
plt.xlabel(r"$S_T$")
plt.ylabel("payoff")
plt.scatter(ST, VT, s=0.8, color="red")
x = np.linspace(min(ST), max(ST))
payoff = np.maximum(0, x - strike)
plt.plot(x, payoff, color="blue")
plt.show()

Sanity check of the replication
[10]:
ST = S[:, -1]
VT = portfolio[:, -1]
from scipy.stats import norm
cash_flows = np.maximum(0, ST - strike)
hedging_errors = VT - cash_flows
hedging_errors = hedging_errors[np.abs(hedging_errors) < 5]
plt.figure(figsize=(15, 8))
plt.hist(hedging_errors, bins="fd", density=True, color="gray", alpha=0.8)
plt.axvline(np.mean(hedging_errors), color="black", label="mean", alpha=0.8)
x = np.linspace(start=min(hedging_errors), stop=max(hedging_errors), num=100)
plt.plot(
x,
norm.pdf(x, loc=np.mean(hedging_errors), scale=np.std(hedging_errors)),
label="normal density",
color="blue",
)
plt.xlabel(r"Hedging errors: $V_T - (S_T - K)^+$")
plt.grid(linestyle="--", dashes=(5, 10), color="gray", linewidth=0.5)
plt.minorticks_on()
plt.legend()
plt.tight_layout()
plt.show()

Evolution of the replication portfolio#
[11]:
time = np.linspace(start=0, stop=maturity, num=nbr_points + 1)
path = -10
fig, (ax1, ax2) = plt.subplots(2, figsize=(15, 8))
plt.suptitle("Portefeuille de réplication")
ax1.plot(time, C[path, :], label="target call")
ax1.plot(time, portfolio[path, :], label="portfolio")
ax1.grid(linestyle="--", dashes=(5, 10), color="gray", linewidth=0.5)
ax1.minorticks_on()
ax1.legend()
ax2.axhline(y=strike, label="Target strike", linestyle="dashed", color='black', linewidth=0.7)
ax2.axhline(y=strike_hedging, label="Hedging strike", linestyle="dashed", color='black', linewidth=0.7)
ax2.plot(time, S[path, :], label="Underlying")
ax2.grid(linestyle="--", dashes=(5, 10), color="gray", linewidth=0.5)
ax2.minorticks_on()
ax2.set_xlabel("Time")
ax2.legend()
plt.tight_layout()
plt.show()

More fancy examples
[13]:
nbr_simulations_to_plot = 5
time = np.linspace(start=0, stop=maturity, num=nbr_points + 1)
paths = range(nbr_simulations_to_plot)
for path in paths:
fig, (ax1, ax2, ax3) = plt.subplots(3, figsize=(15, 10))
plt.suptitle(f"Portefeuille de réplication - simulation {path}")
# Tracé avec des styles différents
ax1.plot(time, portfolio[path, :], label="Portfolio", color='blue', marker='+')
ax1.plot(time, C[path, :], label="Call", color='red', marker='+')
ax1.grid(linestyle="--", dashes=(5, 10), color="gray", linewidth=0.5)
ax1.minorticks_on()
ax1.legend()
# Tracé avec des styles différents
ax2.plot(time, S[path, :], label="Risky asset", color='red', marker='+')
ax2.grid(linestyle="--", dashes=(5, 10), color="gray", linewidth=0.5)
ax2.minorticks_on()
ax2.legend()
# Tracé du sous-jacent et des strikes
ax3.plot(time, V[path, :]*100, label="Variance", color='red', marker='+')
ax3.grid(linestyle="--", dashes=(5, 10), color="gray", linewidth=0.5)
ax3.minorticks_on()
ax3.set_xlabel("Time")
ax3.set_ylabel("%")
ax3.legend()
plt.tight_layout()
plt.show()




