尝试使用 GEKKO 解决此非线性优化,出现此错误
Trying to solve this non linear optimization using GEKKO, getting this error
@错误:用序列设置数组元素
我正在努力将下行风险降至最低。
我有一个 returns 形状的二维数组 (1000, 10),投资组合从 100 美元开始。连续每个 return 复合 10 次。对所有行都这样做。将每一行的最后一个单元格的值与最后一列的值的平均值进行比较。如果该值小于均值或为零,则保留该值。所以我们将有一个 (1000, 1) 的数组。最后我找到了它的标准偏差。
Objective是为了最小化标准差。
约束:权重需要小于1
预期的 return 即wt*ret 应该等于 7% 这样的值。我必须针对 7%、8% 或 10% 等几个值执行此操作。
wt = np.array([0.4, 0.3, 0.3])
cov = array([[0.00026566, 0.00016167, 0.00011949],
[0.00016167, 0.00065866, 0.00021662],
[0.00011949, 0.00021662, 0.00043748]])
ret =[.098, 0.0620,.0720]
iterations = 10000
return_sim = np.random.multivariate_normal(ret, cov, iterations)
def simulations(wt):
downside =[]
fund_ret =np.zeros((1000,10))
prt_ret = np.dot(return_sim , wt)
re_ret = np.array(prt_ret).reshape(1000, 10) #10 years
for m in range(len(re_ret)):
fund_ret[m][0] = 100 * (1 + re_ret[m][0]) #start with 0
for n in range(9):
fund_ret[m][n+1] = fund_ret[m][n]* (1 + re_ret[m][n+1])
mean = np.mean(fund_ret[:,-1]) #just need the last column and all rows
for i in range(1000):
downside.append(np.maximum((mean - fund_ret[i,-1]), 0))
return np.std(downside)
b = GEKKO()
w = b.Array(b.Var,3,value=0.33,lb=1e-5, ub=1)
b.Equation(b.sum(w)<=1)
b.Equation(np.dot(w,ret) == .07)
b.Minimize(simulations(w))
b.solve(disp=False)
#simulations(wt)
如果把gekko部分注释掉,调用最下面的模拟函数就可以了
在这种情况下,您需要考虑使用不同的优化器,例如 scipy.minimize.optimize
。 Gekko 当前不支持函数 np.std()
。 Gekko 将模型编译成字节码以进行自动微分,因此您需要将问题放入受支持的形式中。 Gekko 的方法有几个优点,特别是对于大规模或非线性问题。对于少于 100 个变量和近乎线性约束的小问题,scipy.minimize.optimize
等优化器通常是一个可行的选择。这是您遇到的问题的解决方案:
import numpy as np
from scipy.optimize import minimize
wt = np.array([0.4, 0.3, 0.3])
cov = np.array([[0.00026566, 0.00016167, 0.00011949],
[0.00016167, 0.00065866, 0.00021662],
[0.00011949, 0.00021662, 0.00043748]])
ret =[.098, 0.0620,.0720]
iterations = 10000
return_sim = np.random.multivariate_normal(ret, cov, iterations)
def simulations(wt):
downside =[]
fund_ret =np.zeros((1000,10))
prt_ret = np.dot(return_sim , wt)
re_ret = np.array(prt_ret).reshape(1000, 10) #10 years
for m in range(len(re_ret)):
fund_ret[m][0] = 100 * (1 + re_ret[m][0]) #start with 0
for n in range(9):
fund_ret[m][n+1] = fund_ret[m][n]* (1+re_ret[m][n+1])
#just need the last column and all rows
mean = np.mean(fund_ret[:,-1])
for i in range(1000):
downside.append(np.maximum((mean - fund_ret[i,-1]), 0))
return np.std(downside)
b = (1e-5,1); bnds=(b,b,b)
cons = ({'type': 'ineq', 'fun': lambda x: sum(x)-1},\
{'type': 'eq', 'fun': lambda x: np.dot(x,ret)-.07})
sol = minimize(simulations,wt,bounds=bnds,constraints=cons)
w = sol.x
print(w)
这将生成具有最佳值 w=sol.x
的解决方案 sol
:
fun: 6.139162309118155
jac: array([ 8.02691203, 10.04863131, 9.49171901])
message: 'Optimization terminated successfully.'
nfev: 33
nit: 6
njev: 6
status: 0
success: True
x: array([0.09741111, 0.45326888, 0.44932001])
@错误:用序列设置数组元素
我正在努力将下行风险降至最低。
我有一个 returns 形状的二维数组 (1000, 10),投资组合从 100 美元开始。连续每个 return 复合 10 次。对所有行都这样做。将每一行的最后一个单元格的值与最后一列的值的平均值进行比较。如果该值小于均值或为零,则保留该值。所以我们将有一个 (1000, 1) 的数组。最后我找到了它的标准偏差。
Objective是为了最小化标准差。 约束:权重需要小于1
预期的 return 即wt*ret 应该等于 7% 这样的值。我必须针对 7%、8% 或 10% 等几个值执行此操作。
wt = np.array([0.4, 0.3, 0.3])
cov = array([[0.00026566, 0.00016167, 0.00011949],
[0.00016167, 0.00065866, 0.00021662],
[0.00011949, 0.00021662, 0.00043748]])
ret =[.098, 0.0620,.0720]
iterations = 10000
return_sim = np.random.multivariate_normal(ret, cov, iterations)
def simulations(wt):
downside =[]
fund_ret =np.zeros((1000,10))
prt_ret = np.dot(return_sim , wt)
re_ret = np.array(prt_ret).reshape(1000, 10) #10 years
for m in range(len(re_ret)):
fund_ret[m][0] = 100 * (1 + re_ret[m][0]) #start with 0
for n in range(9):
fund_ret[m][n+1] = fund_ret[m][n]* (1 + re_ret[m][n+1])
mean = np.mean(fund_ret[:,-1]) #just need the last column and all rows
for i in range(1000):
downside.append(np.maximum((mean - fund_ret[i,-1]), 0))
return np.std(downside)
b = GEKKO()
w = b.Array(b.Var,3,value=0.33,lb=1e-5, ub=1)
b.Equation(b.sum(w)<=1)
b.Equation(np.dot(w,ret) == .07)
b.Minimize(simulations(w))
b.solve(disp=False)
#simulations(wt)
如果把gekko部分注释掉,调用最下面的模拟函数就可以了
在这种情况下,您需要考虑使用不同的优化器,例如 scipy.minimize.optimize
。 Gekko 当前不支持函数 np.std()
。 Gekko 将模型编译成字节码以进行自动微分,因此您需要将问题放入受支持的形式中。 Gekko 的方法有几个优点,特别是对于大规模或非线性问题。对于少于 100 个变量和近乎线性约束的小问题,scipy.minimize.optimize
等优化器通常是一个可行的选择。这是您遇到的问题的解决方案:
import numpy as np
from scipy.optimize import minimize
wt = np.array([0.4, 0.3, 0.3])
cov = np.array([[0.00026566, 0.00016167, 0.00011949],
[0.00016167, 0.00065866, 0.00021662],
[0.00011949, 0.00021662, 0.00043748]])
ret =[.098, 0.0620,.0720]
iterations = 10000
return_sim = np.random.multivariate_normal(ret, cov, iterations)
def simulations(wt):
downside =[]
fund_ret =np.zeros((1000,10))
prt_ret = np.dot(return_sim , wt)
re_ret = np.array(prt_ret).reshape(1000, 10) #10 years
for m in range(len(re_ret)):
fund_ret[m][0] = 100 * (1 + re_ret[m][0]) #start with 0
for n in range(9):
fund_ret[m][n+1] = fund_ret[m][n]* (1+re_ret[m][n+1])
#just need the last column and all rows
mean = np.mean(fund_ret[:,-1])
for i in range(1000):
downside.append(np.maximum((mean - fund_ret[i,-1]), 0))
return np.std(downside)
b = (1e-5,1); bnds=(b,b,b)
cons = ({'type': 'ineq', 'fun': lambda x: sum(x)-1},\
{'type': 'eq', 'fun': lambda x: np.dot(x,ret)-.07})
sol = minimize(simulations,wt,bounds=bnds,constraints=cons)
w = sol.x
print(w)
这将生成具有最佳值 w=sol.x
的解决方案 sol
:
fun: 6.139162309118155
jac: array([ 8.02691203, 10.04863131, 9.49171901])
message: 'Optimization terminated successfully.'
nfev: 33
nit: 6
njev: 6
status: 0
success: True
x: array([0.09741111, 0.45326888, 0.44932001])