我试图从金融期权数据中退出Black-Scholes隐含波动率。如果数据包含无法找到隐含波动率的选项,则会使所有结果等于初始猜测。请参阅以下示例
from scipy.optimize import fsolve
import numpy as np
from scipy.stats import norm
S = 1293.77
r = 0.05
K = np.array([1255, 1260, 1265, 1270, 1275])
T = 2./365
price = np.array([38.9, 34.35, 29.7, 25.35, 21.05])
def black_scholes(S, K, r, T, sigma):
d1 = (np.log(S / K) + (r + sigma ** 2 / 2) * T) / (sigma * np.sqrt(T))
d2 = d1 - sigma * np.sqrt(T)
return S * norm.cdf(d1) - K * np.exp(-r * T) * norm.cdf(d2)
volatility = lambda x: black_scholes(S, K, r, T, x) - price
print fsolve(volatility, np.repeat(0.1, len(K)))
给出
RuntimeWarning: The iteration is not making good progress, as measured by the
improvement from the last ten iterations.
warnings.warn(msg, RuntimeWarning)
[ 0.1 0.1 0.1 0.1 0.1]
通过与Matlab或Maple进行相同的操作,我知道第一个选项无法找到解决方案。如果我排除那个,那么
K = np.array([1260, 1265, 1270, 1275])
price = np.array([34.35, 29.7, 25.35, 21.05])
我确实得到了正确的结果
[ 0.19557092 0.20618568 0.2174149 0.21533821]
因此,如果找不到解决方案,我希望fsolve
返回NaN
而不是我最初的猜测,而不是弄乱其余的解决方案。
答案 0 :(得分:3)
使用full_output
参数告诉fsolve
返回更多信息,并在返回时检查ier
的值。例如,
sol, info, ier, msg = fsolve(volatility, np.repeat(0.1, len(K)), full_output=True)
if ier != 1:
print "ier = %d" % (ier,)
print msg
else:
print "sol =", sol
你说:
...如果找不到解决方案,我希望fsolve返回NaN而不是我最初的猜测,而不是弄乱其余的解决方案。
fsolve
无法知道您正在解决的问题实际上是一系列解耦问题。你给它一个n维问题。要么成功要么找不到解决问题的方法。