Estoy teniendo algunos problemas para obtener la solución "correcta" de una función en la que estoy tratando de utilizar scipy.optimize.minimize
.
En el código siguiente, creo una función bs_nor()
y establecer una función objetivo, objfunc_vol
. Declaro la suposición inicial x0 = 0.01
y las otras constantes dentro del argumento ( args = ()
).
Yo uso scipy minimize
donde quiero recuperar el vol implícito dado por sigma
y los demás parámetros, args
son constantes.
import xlrd
import numpy as np
import math
import pandas as pd
import matplotlib.pyplot as plt
import scipy as sp
import scipy.stats as stats
from scipy.optimize import minimize
from IPython.display import display
class option:
def bs_nor(F = 1.0, K = 1.05, time = 1.0, sigma = 0.015, bs_type = 'call'):
d1 = (F-K)/(sigma * np.sqrt(time))
if (bs_type == 'call') or (bs_type == 'c') or (bs_type == 'Call'):
opt = (F-K) * stats.norm.cdf(d1, 0.0, 1.0) + sigma * np.sqrt(time/(2.0*math.pi)) * np.exp(-0.5 * d1**2)
else:
opt = (K-F) * stas.norm.cdf(-d1, 0.0, 1.0) + sigma * np.sqrt(time/(2.0*math.pi)) * np.exp(-0.5 * d1**2)
return np.array([opt, d1, stats.norm.cdf(d1, 0.0, 1.0)])
def objfunc_vol(param = np.array([0.15]), F = 1.0, K = 1.0, time = 1.0, mode = 'normal', quote = 0.5):
sigma = param[0]
if (mode == 'normal') or (mode == 'norm') or (mode == 'n') :
prx = option.bs_nor(F, K, time, sigma, bs_type = 'call')[0]
else:
prx = option.bs_log(F, K, time, sigma, bs_type = 'call')[0]
diff = prx - quote
return diff
options={'maxiter': 200}
x0 = 0.0255
res_vol = minimize(option.objfunc_vol, x0, args = (0.03057, -0.02, 1.0 ,'normal', 0.05079), method ='SLSQP', options = options)
print(res_vol)
option.bs_nor(F = 0.03057, K = -0.02, time = 1.0, sigma = 0.025507, bs_type = 'call')[0]
Sé que la solución debería ser 0,0255, dadas las constantes que introduzco. Sin embargo, scipy optimize no parece darme la respuesta correcta. Me da -1,15528343e+08 en lugar de 0,0255.
¿Qué estoy especificando mal?
fun: -46089140.7916228
jac: array([ 0.])
message: 'Optimization terminated successfully.'
nfev: 42
nit: 14
njev: 14
status: 0
success: True
x: array([ -1.15528343e+08])
0.050796884487313197
1 votos
Compruebe su función objetivo (nota: no "función objeto"). Usted está minimizando
prx - quote
en lugar deabs(prx - quote)
o(prx - quote)**2
. Alternativamente, no minimice esta función pero ejecute una búsqueda de raíces - por ejemplobrentq
descipy.optimize
.0 votos
Tienes razón @LocalVolatility; ahora me siento tonto. Funciona después de que acabe de poner abs(prx - quote). Una continuación, ... ¿por qué recomiendas usar brent para scipy.optimize en lugar de minimize? ¿No son similares de todos modos? La razón por la que utilicé esta configuración es porque tengo un marco codificado existente para calibrar los parámetros de SABR.
0 votos
Nos pasa a todos. Puedes responder a tu propia pregunta para cerrarla o, alternativamente, borrarla.
1 votos
En cuanto a la búsqueda de raíces frente a la minimización, una búsqueda de raíces puede expresarse como una minimización, pero generalmente no a la inversa. La búsqueda de raíces, por ejemplo, sabe que ha puesto entre paréntesis root cuando dos valores tienen signos diferentes. La minimización generalmente no puede utilizar el valor del verdadero mínimo, ya que suele ser desconocido. ¿Quizás una buena pregunta de seguimiento ?