scipy.optimize возвращает начальное предположение, когда входные параметры малы

#python #optimization #scipy

#python #оптимизация #scipy

Вопрос:

Мне нужно найти портфель с минимальной дисперсией, используя scipy optimize. У меня есть следующая ковариационная матрица:

 [[0.00076593 0.00087803 0.00082423 0.00094616 0.00090782]
  [0.00087803 0.0015638  0.00086395 0.00097013 0.00107642]
  [0.00082423 0.00086395 0.00092068 0.00104474 0.00099357]
  [0.00094616 0.00097013 0.00104474 0.00133651 0.00119894]
  [0.00090782 0.00107642 0.00099357 0.00119894 0.00132278]]]
  

И первоначальное предположение для весов портфеля равно:

 [0.2,0.2,0.2,0.2,0.2]
  

Запускаем следующий код, где V — ковариационная матрица сверху:

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

#Minimum Variance

cov_rol = df_smartbeta.rolling(window=36).cov()
cov_rol = cov_rol.values.reshape(665,5,5)
V = cov_rol

def objective(w, V): #portfolio variance, 1x1 array
    w1= np.matrix(w)
    wt = np.matrix(w1)
    wt = np.transpose(wt)
    return (w1*V)*wt

def constraint1(x): #constraint 1: sum w0 = 1
    return np.sum(x)-1

w0 = np.array([0.2,0.2,0.2,0.2,0.2]) #initial guess
cons = ({"type":"eq", "fun": constraint1}) #merge constraints
b = (0,None) #define bounds. Lower bound: 0. Upper bound: None
bnds = (b,b,b,b,b)

count = 0
w_min = []
for i in tqdm(range(len(cov_rol))):
    res =minimize(objective, w0, args=(V[count]), method="SLSQP",bounds=bnds, constraints=cons)
    w_min.append(res.x)
    count  = 1

w_min_dataframe = pd.DataFrame(w_min)
  

Код просто возвращает начальное предположение, хотя оно должно давать

 [1.0,0,0,0,0]
  

Если я изменяю масштаб ковариационной матрицы путем умножения на 100, код работает. Кто-нибудь знает, почему это происходит и как решить проблему без изменения масштаба? Я видел несколько похожих вопросов раньше, но не нашел никаких решений, которые работают…

Комментарии:

1. Пожалуйста, покажите также весь ваш импорт, это упрощает копирование и вставку.

2. Кроме того, вам следует избегать использования np.matrix, более стандартным является использование np.array. вы могли бы просто выполнить w1.T @ V @ w1 с w1 и V двумя неровными массивами в python 3.6

3. Я только что отредактировал импорт.

4. Я полагаю, что у optimize есть некоторый тест, который он использует, чтобы проверить, сходится ли он еще. Если это так, он останавливается раньше, вместо того, чтобы использовать максимально допустимое количество шагов. Может быть, из-за того, что ваши значения малы, это считается сходящимся раньше?