Estoy intentando implementar un método Bisection para el cálculo de la volatilidad implícita. Utilizo un algoritmo de Haug (página 455).
def GBlackScholesImpVolBisection(CallPutFlag, S, X, T, r, cm):
vLow = 0.01
vHigh = 100
eps = 1e-7
cLow = BlackScholes(CallPutFlag, S, X, T, r, vLow)
cHigh = BlackScholes(CallPutFlag, S, X, T, r, vHigh)
counter = 0
vi = vLow + (cm - cLow) * (vHigh - vLow)/(cHigh - cLow)
while abs(cm - BlackScholes(CallPutFlag, S, X, T, r, vi)) > eps:
counter = counter + 1
if counter == 500:
GBlackScholesImpVolBisection = 'NA'
return GBlackScholesImpVolBisection
if BlackScholes(CallPutFlag, S, X, T, r, vi) < cm:
vLow = vi
else:
vHigh = vi
cLow = BlackScholes(CallPutFlag, S, X, T, r, vLow)
cHigh = BlackScholes(CallPutFlag, S, X, T, r, vHigh)
vi = vLow + (cm - cLow) * (vHigh - vLow) / (cHigh - cLow)
GBlackScholesImpVolBisection = vi
return GBlackScholesImpVolBisection
Básicamente, funciona bien para las opciones de compra, pero da un error (división por cero) si utilizo opciones de venta. He intentado con diferentes estimaciones bajas y altas pero nada ayuda.
Mi función BlackScholes tiene el siguiente aspecto
def BlackScholes(CallPutFlag, S, X, T, r, sigma):
d1 = (math.log(S/X) + (r + sigma**2 / 2) * T) / (sigma * math.sqrt(T))
d2 = d1 - sigma * math.sqrt(T)
if CallPutFlag == "C":
price = S * stats.norm.cdf(d1) - X * math.exp(-r * T) * stats.norm.cdf(d2)
elif CallPutFlag == "P":
price = X * math.exp(-r * T) * stats.norm.cdf(-d2) - S * stats.norm.cdf(-d1)
return price
Y las variables que utilizo son
S = 91.1 # Stock price
r = 7.2/100 # Risk-free interest rate
X = 60 # strike
T = 70/365 # Time to expiration in years
spot_price = 90.2