尝试使用 #gekko 最大化这个简单的非线性问题但出现此错误

Trying to maximize this simple non linear problem using #gekko but getting this error

(@error: 未找到解决方案)

positions = ["AAPL", "NVDA", "MS","CI", "HON"]
cov = df_ret.cov()
ret = df_ret.mean().values
weights = np.array(np.random.random(len(positions)))

def maximize(weights):
    std = np.sqrt(np.dot(np.dot(weights.T,cov),weights))
    p_ret = np.dot(ret.T,weights)
    sharpe = p_ret/std
    return sharpe

a = GEKKO()
w1 = a.Var(value=0.2, lb=0, ub=1)
w2 = a.Var(value=0.2, lb=0, ub=1)
w3 = a.Var(value=0.2, lb=0, ub=1)
w4 = a.Var(value=0.2, lb=0, ub=1)
w5 = a.Var(value=0.2, lb=0, ub=1)

a.Equation(w1+w2+w3+w4+w5<=1)
weight = np.array([w1,w2,w3,w4,w5])

a.Obj(-maximize(weight))
a.solve(disp=False)

**** 试图弄清楚为什么它没有给出错误的解决方案

# df_ret 是一个数据框 returns (对于持仓股票)

Df_ret looks like this

# 试图最大化锐化率

#w(1到n)是和小于等于1的权重****

我不熟悉 GEKKO,所以我无法真正帮助解决这个问题,但万一有人不回答如何使用 GEKKO,这里有一个潜在的解决方案 scipy.optimize.minimize:

from scipy.optimize import minimize
import numpy as np
import pandas as pd



def OF(weights, cov, ret, sign = 1.0):
  std = np.sqrt(np.dot(np.dot(weights.T,cov),weights))
  p_ret = np.dot(ret.T,weights)
  sharpe = p_ret/std
  return sign*sharpe


if __name__ == '__main__':

  x0 = np.array([0.2,0.2,0.2,0.2,0.2])
  df_ret = pd.DataFrame(np.array([[.001729, .014603, .036558, .016772, .001983],
[-0.015906, .006396, .012796, -.002163, 0],
[-0.001849, -.019598, .014484, .036856, .019292],
[.006648, .002161, -.020352, -.007580, 0.022083],
[-.008821, -.014016, -.006512, -.015802, .012583]]))
  cov = df_ret.cov()
  ret = df_ret.mean().values


  minx0 = np.repeat(0, [len(x0)] , axis = 0)
  maxx0 = np.repeat(1, [len(x0)] , axis = 0)
  bounds = tuple(zip(minx0, maxx0))

  cons = {'type':'ineq', 
  'fun':lambda weights: 1 - sum(weights)}
  res_cons = minimize(OF, x0, (cov, ret, -1), bounds = bounds, constraints=cons, method='SLSQP')



  print(res_cons)
  print('Current value of objective function: ' + str(res_cons['fun']))
  print('Current value of controls:')
  print(res_cons['x'])

输出:

     fun: -2.1048843911794486
     jac: array([ 5.17067784e+00, -2.36839056e-04, -6.24716282e-04,  6.56819057e+00,
        2.45392323e-04])
 message: 'Optimization terminated successfully.'
    nfev: 69
     nit: 9
    njev: 9
  status: 0
 success: True
       x: array([5.47832097e-14, 1.52927443e-01, 1.87864415e-01, 5.32258098e-14,
       6.26433468e-01])
Current value of objective function: -2.1048843911794486
Current value of controls:
[5.47832097e-14 1.52927443e-01 1.87864415e-01 5.32258098e-14
 6.26433468e-01]

此处添加符号参数是因为为了最大化 objective 函数,您只需最小化 OF*(-1)。我将默认设置为 1(最小化),但我在 args 中传递 -1 来更改它。

这是一个使用 gekko 的解决方案:

from gekko import GEKKO
import numpy as np
import pandas as pd
a = GEKKO()

positions = ["AAPL", "NVDA", "MS","CI", "HON"]

df_ret = pd.DataFrame(np.array([[.001729, .014603, .036558, .016772, .001983],
[-0.015906, .006396, .012796, -.002163, 0],
[-0.001849, -.019598, .014484, .036856, .019292],
[.006648, .002161, -.020352, -.007580, 0.022083],
[-.008821, -.014016, -.006512, -.015802, .012583]]))
cov = df_ret.cov().values
ret = df_ret.mean().values

def obj(weights):
    std = a.sqrt(np.dot(np.dot(weights.T,cov),weights))
    p_ret = np.dot(ret.T,weights)
    sharpe = p_ret/std
    return sharpe

a = GEKKO()
w = a.Array(a.Var,len(positions),value=0.2,lb=1e-5, ub=1)
a.Equation(a.sum(w)<=1)
a.Maximize(obj(w))
a.solve(disp=False)

print(w)

我对问题所做的几件事是使用 Array 函数创建变量权重 w。我还切换到使用 gekko sqrt 以便它对 objective 函数进行自动微分。我还添加了 1e-5 的下限以避免 sqrt(0) 并除以零。 Obj() 函数最小化,所以我删除了负号并使用 Maximize() 函数使其更具可读性。它为 w:

生成此解决方案
[[1e-05] [0.15810629919] [0.19423029287] [1e-05] [0.6476428726]]

很多人更熟悉 scipy。这是一个 benchmark problem where the same problem is solved with scipy.minimize.optimize and gekko. There is also a link for that same solution with MATLAB fmincon or gekko with MATLAB.