Estoy resolviendo el siguiente problema como parte de Modelos de tipos de interés clase en Coursera
Estoy teniendo dificultades para utilizar el solucionador de root no lineal para invertir la fórmula de Black para el precio de Cap con el fin de obtener una volatilidad implícita de Black que se utilizará más para fines de calibración. Mi código de Python se adjunta a continuación.
import numpy as np
import math
import scipy
from scipy import optimize
from scipy import stats
Time = [0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4]
ForwardRates = [0.06, 0.08, 0.09, 0.10, 0.10, 0.10, 0.09, 0.09]
CapPrices = [0.20, 0.80, 1.20, 1.60]
SimpleRates = []
DiscountFactors = []
SimpleRates.append(ForwardRates[0])
DiscountFactors.append(1/(1+Time[0]*SimpleRates[0]))
for i in range(1, len(Time)):
SimpleRates.append(((1+0.5*ForwardRates[i])*(1+Time[i-1]*SimpleRates[i-1])-1)/Time[i])
DiscountFactors.append(1/(1+Time[i]*SimpleRates[i]))
SwapRates = []
for k in range(1, len(Time)):
s = sum(DiscountFactors[i] for i in range(1, k + 1))
SwapRates.append((DiscountFactors[0] - DiscountFactors[k])/(0.5*s))
def d1(i, sigma):
return (np.log(ForwardRates[i]/SwapRates[i])+0.5*math.pow(sigma, 2)*Time[i-1])/(sigma*math.sqrt(Time[i-1]))
def d2(i, sigma):
return (np.log(ForwardRates[i]/SwapRates[i])+math.pow(sigma, 2)*Time[i-1])/(sigma*math.sqrt(Time[i-1])) - sigma*math.sqrt(Time[i-1])
def caplet(begin, end, sigma):
return 0.5*DiscountFactors[end]*(ForwardRates[end]*scipy.stats.norm.cdf(d1(end, sigma))-SwapRates[end]*scipy.stats.norm.cdf(d2(end, sigma)))
def cap(end, sigma):
price = 0
for j in range(1, end + 1):
price += caplet(j - 1, j, sigma)
return price
s = scipy.optimize.bisect(lambda sigma: cap(1, sigma) - CapPrices[0], 0.0005, 0.5)
Me da error que f(a) y f(b) deben tener signos diferentes independientemente de mi elección de intervalo. ¿Qué método de resolución de raíces debo utilizar en Python para evitarlo? ¿Hay algo más que esté haciendo mal?