程式
反轉上限價格的黑色公式以找到黑色隱含波動率
作為Coursera 上利率模型課程的一部分,我正在解決以下問題
我很難使用非線性根求解器來反轉上限價格的黑色公式,以獲得將進一步用於校準目的的黑色隱含波動率。我的 Python 程式碼附在下面。
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)
我收到一個錯誤,即 f(a) 和 f(b) 必須具有不同的符號,無論我的間隔選擇如何。我應該在 Python 中使用什麼特定的根求解方法來解決這個問題?還有什麼我做錯了嗎?
請注意,上限價格以百分比形式給出,因此您的上限價格向量應該是
CapPrices = [0.002, 0.008, 0.012, 0.016]
當你有
CapPrices = [0.20, 0.80, 1.20, 1.60]
程式碼應該為這些上限價格找到沒有問題的解決方案。
請注意,對於您錯誤給出的 CapPrices,沒有解決方案。注意:
$ {Caplet(F,\sigma,t) \to F} $ 作為 $ \sigma \to \infty $ . 因此最高的 caplet 值是 $ F $ ,但您正試圖大致找到解決方案 $ 2.5F $ 即 (0.20 / 0.08 = 2.5),因此求解器失敗。
我還注意到您在 d2 中的公式有錯誤,它應該等於:
return (np.log(ForwardRates[i]/SwapRates[i])+0.5*math.pow(sigma, 2)*Time[i-1])/(sigma*math.sqrt(Time[i-1])) - sigma*math.sqrt(Time[i-1])
雖然你有(缺少乘以 0.5)
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])