我有一个列表对象,它基本上取两个值之间的差。这是一个优化问题,我要找出最接近零的值,这样我才能找到局部最小值。列表对象的值为[-100,-90,-80,…0.0001,…80,90,100]。
import numpy as np
import scipy.stats as sp
def BSM_Call(S,K,T,r,Sigma):
d1 = (np.log(S/K) + (r+Sigma**2/2)*T) / (Sigma*np.sqrt(T))
d2 = d1 - (Sigma*np.sqrt(T))
Call = S*sp.norm.cdf(d1) - K*np.exp(-r*T)*sp.norm.cdf(d2)
return Call
ini_vol = 0.0001
rng = np.arange(0.0001,1,0.0001)
diff = []
for i in range(len(rng)):
diff.append(67.33923210204784 - BSM_Call(4395.26,4400,31/365,0,ini_vol+rng[i]))
一旦确定了优化点,我想获取ini_vol+rng[I]对应的值。
在我看来,你正试图找到Sigma的值,它给出了最接近零的结果(减去BSM_Call的返回值和常数67.339…)。假设是这样的话,我会这样做:-
import numpy as np
import scipy.stats as sp
def BSM(S, K, T, r, Sigma):
_St = Sigma * np.sqrt(T)
d1 = (np.log(S / K) + (r + Sigma**2 / 2) * T) / _St
return S * sp.norm.cdf(d1) - K * np.exp(-r * T) * sp.norm.cdf(d1 - _St)
lo = None
ini = None
for i in range(1, 10000):
ini_vol = i / 10000
bsm = BSM(4395.26, 4400, 31 / 365, 0, ini_vol)
diff = 67.33923210204784 - bsm
adiff = abs(diff)
if lo is None or adiff < lo:
lo = diff
ini = ini_vol
if lo == 0:
break
print(f'ini_vol = {ini:.4f}')
请注意,我已经将BSM_Call更改为BSM,以突出其中的小效率改进。还需要注意的是,没有必要构建一个列表,因为您可以在执行循环时找出它。有可能提前休息,所以我已经允许了