Минимизация SciPy не повторяется вообще - PullRequest
1 голос
/ 03 мая 2019

Я пытаюсь минимизировать функцию, которая в основном выглядит следующим образом:

enter image description here

На самом деле она имеет две независимые переменные, но так как x1 + x2= 1, они НЕ ДЕЙСТВИТЕЛЬНО независимы.

теперь вот целевая функция

def calculatePVar(w,covM):
    w = np.matrix(w)
    return (w*covM*w.T) [0,0]

wnere w - список весов каждого актива, а covM - ковариационная матрица, которая возвращаетсяby .cov () из pandas

Вот где вызывается функция оптимизации:

w0 = []
for sec in portList:
    w0.append(1/len(portList))

bnds = tuple((0,1)  for x in w0)
cons = ({'type': 'eq', 'fun': lambda x:  np.sum(x)-1.0})
res= minimize(calculatePVar, w0, args=nCov, method='SLSQP',constraints=cons, bounds=bnds)
weights = res.x

теперь есть четкий минимум для функции, но при минимизации просто выплюнут начальные значения какрезультат и он говорит: «Оптимизация успешно завершена».Любые предложения?

результаты оптимизации:

enter image description here

PS изображения в виде ссылок, потому что я не отвечаю требованиям!

1 Ответ

0 голосов
/ 05 мая 2019

В вашем коде были только некоторые непонятные переменные, поэтому я просто убрал это и упростил некоторые строки, теперь минимизация работает правильно. Однако теперь возникает вопрос: правильны ли результаты? и имеют ли они смысл? и это вам судить:

import numpy as np 
from scipy.optimize import minimize

def f(w, cov_matrix):
    return (np.matrix(w) * cov_matrix * np.matrix(w).T)[0,0]

cov_matrix = np.array([[1, 2, 3],
                       [4, 5, 6],
                       [7, 8, 9]])
p    = [1, 2, 3]
w0   = [(1/len(p))  for e in p]
bnds = tuple((0,1)  for e in w0)
cons = ({'type': 'eq', 'fun': lambda w:  np.sum(w)-1.0})

res  = minimize(f, w0, 
                args        = cov_matrix, 
                method      = 'SLSQP',
                constraints = cons, 
                bounds      = bnds)
weights = res.x
print(res)
print(weights)

Обновление:

Исходя из ваших комментариев, мне кажется, что, возможно, ваша функция имеет несколько минимумов, и поэтому scipy.optimize.minimize попадает туда. Я предлагаю scipy.optimize.basinhopping в качестве альтернативы, это будет использовать случайный шаг, чтобы пройти большинство минимумов вашей функции, и он все еще будет быстрым. Вот код:

import numpy as np 
from scipy.optimize import basinhopping


class MyBounds(object):
     def __init__(self, xmax=[1,1], xmin=[0,0] ):
         self.xmax = np.array(xmax)
         self.xmin = np.array(xmin)

     def __call__(self, **kwargs):
         x = kwargs["x_new"]
         tmax = bool(np.all(x <= self.xmax))
         tmin = bool(np.all(x >= self.xmin))
         return tmax and tmin

def f(w):
    global cov_matrix
    return (np.matrix(w) * cov_matrix * np.matrix(w).T)[0,0]

cov_matrix = np.array([[0.000244181, 0.000198035],
                       [0.000198035, 0.000545958]])

p    = ['ABEV3', 'BBDC4']
w0   = [(1/len(p))  for e in p]
bnds = tuple((0,1)  for e in w0)
cons = ({'type': 'eq', 'fun': lambda w:  np.sum(w)-1.0})

bnds = MyBounds()
minimizer_kwargs = {"method":"SLSQP", "constraints": cons}
res  = basinhopping(f, w0, 
                    accept_test  = bnds)
weights = res.x
print(res)
print("weights: ", weights)

Выход:

                        fun: 2.3907094432990195e-09
 lowest_optimization_result:       fun: 2.3907094432990195e-09
 hess_inv: array([[ 2699.43934183, -1184.79396719],
       [-1184.79396719,  1210.50404805]])
      jac: array([1.34548553e-06, 2.00122166e-06])
  message: 'Optimization terminated successfully.'
     nfev: 60
      nit: 6
     njev: 15
   status: 0
  success: True
        x: array([0.00179748, 0.00118076])
                    message: ['requested number of basinhopping iterations completed successfully']
      minimization_failures: 0
                       nfev: 6104
                        nit: 100
                       njev: 1526
                          x: array([0.00179748, 0.00118076])
weights:  [0.00179748 0.00118076]
...