我是Python的初学者,我正在尝试使用相同的Excel Solver Logic最小化此功能,但我无法这样做。你能帮我吗?
我想要最小化的功能如下:
from datetime import date
import numpy as np
def nelsonsiegel(Beta0,Beta1,Beta2,Beta3,Lambda1,Lambda2):
SettleDate = date(2017,07,14)
Bond1MaturityDate = date(2018,7,13)
Bond3MaturityDate = date(2020,2,17)
Bond5MaturityDate = date(2022,7,21)
Bond10MaturityDate = date(2027,1,20)
Bond15MaturityDate = date(2031,9,16)
Bond20MaturityDate = date(2037,3,17)
Yearfraction = [float((Bond1MaturityDate-SettleDate).days)/365,float((Bond3MaturityDate-SettleDate).days)/365, float((Bond5MaturityDate-SettleDate).days)/365, float((Bond10MaturityDate-SettleDate).days)/365, float((Bond15MaturityDate-SettleDate).days)/365, float((Bond20MaturityDate-SettleDate).days)/365]
CouponRate = [0,0.0290,0.0321,0.0494,0.0585,0.0624]
BondPrices = [0.97863,0.99745,0.9968, 0.99922,0.98724,0.96679 ]
NS = []
df = []
rst = []
NSS = []
NegM = []
for i in range(len(Yearfraction)):
NelsonSiegel = Beta0 + (Beta1 * ((1-np.exp(-Yearfraction[i]/Lambda1)/Yearfraction[i]*Lambda1))) + (Beta2 * ((((1-np.exp(-Yearfraction[i]/Lambda1))/(Yearfraction[i]*Lambda1))) - (np.exp(-Yearfraction[i]/Lambda1)))) + (Beta3 * ((((1-np.exp(-Yearfraction[i]/Lambda2))/(Yearfraction[i]*Lambda2))) - (np.exp(-Yearfraction[i]/Lambda2))))
NS.append(NelsonSiegel)
discountfactor = np.exp(-Yearfraction[i]*NS[i])
df.append(discountfactor)
if i < 6:
result = (1 + CouponRate[i])* df[i]
m = Yearfraction[i] - 1
if m < 0:
rst.append(result)
while m > 0:
NelsonSiegelCpnRe = Beta0 + (Beta1 * ((1-np.exp(-m/Lambda1)/m*Lambda1))) + (Beta2 * ((((1-np.exp(-m/Lambda1))/(m*Lambda1))) - (np.exp(-m/Lambda1)))) + (Beta3 * ((((1-np.exp(-m/Lambda2))/(m*Lambda2))) - (np.exp(-m/Lambda2))))
result = result + (CouponRate[i] * np.exp(-m*NelsonSiegelCpnRe))
NSS.append(NelsonSiegelCpnRe)
m = m -1
if m <0:
rst.append(result)
a = np.array(rst)
Spread = (BondPrices - a )**2
#SpreadtoMinimize = sum(Spread)
return sum(Spread)
通常会返回一笔金额。应该通过在Beta0,Beta1,Beta2,BEta3,Lambda1,Lambda2上播放来最小化这个总和。 Beta0到Beta3的约束应该是这些变量可以在-1和1之间振荡.Lambda1和Lambda2没有约束。
您知道如何编写代码来执行该任务吗? 谢谢 SB
P.S:我用这些参数执行函数:nelsonsiegel(0.01,0.01,0.01,0.01,1,1)
答案 0 :(得分:0)
好吧,我会重写这个等式,所以它只需要一个参数,然后根据需要将其解析为函数内部的变量。在通过
调用优化引擎之后scipy.optimize.minimize
因此,产生的代码将像:
from datetime import date
import numpy as np
from scipy.optimize import minimize
def nelsonsiegel(x):
Beta0, Beta1, Beta2, Beta3, Lambda1, Lambda2 = x
SettleDate = date(2017,07,14)
Bond1MaturityDate = date(2018,7,13)
Bond3MaturityDate = date(2020,2,17)
Bond5MaturityDate = date(2022,7,21)
Bond10MaturityDate = date(2027,1,20)
Bond15MaturityDate = date(2031,9,16)
Bond20MaturityDate = date(2037,3,17)
Yearfraction = [float((Bond1MaturityDate-SettleDate).days)/365,float((Bond3MaturityDate-SettleDate).days)/365, float((Bond5MaturityDate-SettleDate).days)/365, float((Bond10MaturityDate-SettleDate).days)/365, float((Bond15MaturityDate-SettleDate).days)/365, float((Bond20MaturityDate-SettleDate).days)/365]
CouponRate = [0,0.0290,0.0321,0.0494,0.0585,0.0624]
BondPrices = [0.97863,0.99745,0.9968, 0.99922,0.98724,0.96679 ]
NS = []
df = []
rst = []
NSS = []
NegM = []
for i in range(len(Yearfraction)):
NelsonSiegel = Beta0 + (Beta1 * ((1-np.exp(-Yearfraction[i]/Lambda1)/Yearfraction[i]*Lambda1))) + (Beta2 * ((((1-np.exp(-Yearfraction[i]/Lambda1))/(Yearfraction[i]*Lambda1))) - (np.exp(-Yearfraction[i]/Lambda1)))) + (Beta3 * ((((1-np.exp(-Yearfraction[i]/Lambda2))/(Yearfraction[i]*Lambda2))) - (np.exp(-Yearfraction[i]/Lambda2))))
NS.append(NelsonSiegel)
discountfactor = np.exp(-Yearfraction[i]*NS[i])
df.append(discountfactor)
if i < 6:
result = (1 + CouponRate[i])* df[i]
m = Yearfraction[i] - 1
if m < 0:
rst.append(result)
while m > 0:
NelsonSiegelCpnRe = Beta0 + (Beta1 * ((1-np.exp(-m/Lambda1)/m*Lambda1))) + (Beta2 * ((((1-np.exp(-m/Lambda1))/(m*Lambda1))) - (np.exp(-m/Lambda1)))) + (Beta3 * ((((1-np.exp(-m/Lambda2))/(m*Lambda2))) - (np.exp(-m/Lambda2))))
result = result + (CouponRate[i] * np.exp(-m*NelsonSiegelCpnRe))
NSS.append(NelsonSiegelCpnRe)
m = m -1
if m <0:
rst.append(result)
a = np.array(rst)
Spread = (BondPrices - a )**2
#SpreadtoMinimize = sum(Spread)
return sum(Spread)
x_0 = [0.01, 0.01, 0.01, 0.01, 1, 1] # Here you have to define an intial guess
bnds = zip([-1,-1,-1,-1, -np.inf, -np.inf],[1,1,1,1,np.inf, np.inf])
result = minimize(nelsonsiegel, x_0, bounds=bnds)
我希望它能做到
此致