Last active
September 27, 2023 10:11
-
-
Save 0xJchen/79142dd6e85feccd3fc4a6a25e303b00 to your computer and use it in GitHub Desktop.
chatgpt-sabr
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
from scipy.optimize import minimize | |
from math import log, sqrt | |
import matplotlib.pyplot as plt | |
def sabr_iv(alpha, beta, rho, nu, F, K, T): | |
""" | |
Returns the implied volatility using the SABR model formula. | |
""" | |
X = K | |
if F == K: | |
numer1 = (((1 - beta)**2)/24)*alpha*alpha/(F**(2 - 2*beta)) | |
numer2 = 0.25*rho*beta*nu*alpha/(F**(1 - beta)) | |
numer3 = ((2 - 3*rho*rho)/24)*nu*nu | |
vol_atm = alpha*(1 + (numer1 + numer2 + numer3)*T)/(F**(1-beta)) | |
return vol_atm | |
else: | |
z = nu/alpha*(F*X)**(0.5*(1-beta))*log(F/X) | |
zhi = log((sqrt(1-2*rho*z+z*z)+z-rho)/(1-rho)) | |
numer1 = (((1 - beta)**2)/24)*((alpha*alpha)/((F*X)**(1 - beta))) | |
numer2 = 0.25*rho*beta*nu*alpha/((F*X)**((1 - beta)/2)) | |
numer3 = ((2 - 3*rho*rho)/24)*nu*nu | |
denom1 = (1 + (((1 - beta)**2)/24)*log(F/X)**2 + (((1 - beta)**4)/1920)*(log(F/X)**4)) | |
return alpha*(1 + (numer1 + numer2 + numer3)*T)*z/(zhi*(F*X)**((1-beta)/2)*denom1) | |
def sabr_error(params, F, K, T, mkt_vol, beta): | |
""" | |
Error function to minimize. The difference between SABR implied vol and market vol. | |
""" | |
alpha, rho, nu = params | |
# beta = 0.8 # Assuming a fixed beta, but you can calibrate it as well. | |
model_vol = sabr_iv(alpha, beta, rho, nu, F, K, T) | |
error = (model_vol - mkt_vol)**2 | |
return error | |
# Calibration function | |
def calibrate_sabr(F, K, T, mkt_vol, beta=0.8): | |
""" | |
Calibrate the SABR model and return the optimal parameters. | |
""" | |
initial_guess = [0.2, 0.2, 0.2] | |
bounds = [(0.001, 5), (-0.999, 0.999), (0.001, 5)] | |
result = minimize(sabr_error, initial_guess, args=(F, K, T, mkt_vol, beta), bounds=bounds, method='L-BFGS-B') | |
return result.x | |
# Example calibration | |
F = 1600 | |
K = 1600 | |
T = 0.25 | |
mkt_vol = 0.4 | |
alpha, rho, nu = calibrate_sabr(F, K, T, mkt_vol) | |
print(f"Alpha: {alpha}, Rho: {rho}, Nu: {nu}") | |
def compute_iv_sabr(alpha, beta, rho, nu, F_new, K_new, T): | |
""" | |
Compute the implied volatility using the SABR model for a new asset. | |
""" | |
return sabr_iv(alpha, beta, rho, nu, F_new, K_new, T) | |
# Calibrated parameters | |
alpha_calibrated = 1.74 | |
rho_calibrated = 0.2 | |
nu_calibrated = 0.22 | |
beta = 0.6 # Assuming a fixed beta, but you can change it. | |
# New asset details | |
F_new = 3 # New forward price | |
K_news = np.linspace(1,5,num=1000) # New strike price | |
T = 0.25 # Time to maturity | |
ivs=[] | |
# Compute implied volatility for the new asset | |
for K_new in K_news: | |
ivs.append(compute_iv_sabr(alpha_calibrated, beta, rho_calibrated, nu_calibrated, F_new, K_new, T)) | |
# iv_new = compute_iv_sabr(alpha_calibrated, beta, rho_calibrated, nu_calibrated, F_new, K_new, T) | |
# print(f"Implied Volatility for new asset: {iv_new}") | |
plt.plot(K_news,ivs) | |
plt.show() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment