简体   繁体   English

Python scipy.optimize.minimize提供ZeroDivisionError

[英]Python scipy.optimize.minimize gives ZeroDivisionError

I am trying to implement SABR (Stochastic alpha, beta, rho) in Python to calculate implied volatility. 我正在尝试在Python中实现SABR(随机alpha,beta,rho)以计算隐含波动率。 This link here explains SABR very accurately and concisely starting on slide 17: http://lesniewski.us/papers/presentations/MIT_March2014.pdf 此链接从幻灯片17开始非常准确,简洁地解释了SABR: http : //lesniewski.us/papers/presentations/MIT_March2014.pdf

The method seems easy enough, but the problem I am having is that I am getting a ZeroDivisonError every time I run the program. 该方法似乎很容易,但是我遇到的问题是每次运行程序时都会收到ZeroDivisonError。 I believe this may be because I am choosing my initial alpha, rho, and sigma0 incorrectly during calibration. 我相信这可能是因为在校准过程中我错误地选择了初始的alpha,rho和sigma0。 However, I cannot find online how to choose the initial values to guarantee that a minimum will be found. 但是,我无法在线找到如何选择初始值以保证找到最小值。

Here is my code: 这是我的代码:

# args = [alpha, rho, sigma0]
# The other parameters (T, K, F0, beta, rho, marketVol) are globals
def calcImpliedVol(args):
    alpha = args[0] 
    rho = args[1]
    sigma0 = args[2]

    # From MIT powerpoint, slide 21
    Fmid = (F0 + K) / 2.0
    gamma1 = 1.0 * beta / Fmid
    gamma2 = 1.0 * beta * (beta - 1) / Fmid**2
    xi = 1.0 * alpha / (sigma0 * (1 - beta)) * (F0**(1-beta) - K**(1-beta))
    e = T * alpha**2 # From MIT powerpoint, slide 19

    # From MIT powerpoint, slide 21
    impliedVol = \
        1.0 * alpha * log(F0/K) / D(rho, xi) * \
        (1 + ((2 * gamma2 - gamma1**2 + 1 / Fmid**2)/24.0 * (sigma0 * Fmid**beta / alpha)**2 + \
        (rho * gamma1 / 4.0) * (sigma0 * Fmid**beta / alpha) + ((2 - 3 * rho**2) / 24.0)) * e) - \
        marketVol

    # Returns lambda function in terms of alpha, rho, sigma0
    return impliedVol;

# From MIT powerpoint, slide 21
def D(rho, xi):
    result = log((sqrt(1 - 2 * rho * xi + xi**2) + xi - rho) / (1-rho))
    return result

# Find optimal alpha, rho, sigma0 that minimizes calcImpliedVol - marketVol
def optimize():
    result = optimize.minimize(calcImpliedVol, [alpha_init, rho_init, sigma0_init])
    return result

Thanks so, so much for any help! 非常感谢您的帮助!

限定搜索间隔。

This is a little late but bounding is the right way to go: 这有点晚了,但是限制是正确的方法:

bounds = [(0.0001, None), (-0.9999, 0.9999), (0.0001, None)]
x_solved = minimize(obj_func, initial_guess, args=(mkt_vols, F, K, tau, beta),
                    method='L-BFGS-B', bounds=bounds, tol=0.00001)

alpha represents the base volatility (atm vol can be used here to as an initialization) so it is bounded by 0.0. alpha表示基本波动率(此处可以将atm vol用作初始化),因此以0.0为界。 rho is the correlation between the axes so it is bounded by -1 and 1. nu (vol of volatility) is bounded on the downside by 0.0. rho是轴之间的相关性,因此由-1和1限制。nu(波动率)的下限由0.0限制。

The coefficient tuple is returned with: 系数元组返回:

   x_solved.x

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM