Lai, KK, Yu, L. & Wang, S. (2006, июнь). Оптимизация портфеля на основе средней дисперсии, асимметрии, эксцесса. В первых международных мульти-симпозиумах по компьютерным и вычислительным наукам (IMSCCS'06) (том 2, с. 292-297). IEEE.
P2-P5 1 : https://i.stack.imgur.com/0TWbr.png
[ P6] [2]: https://i.stack.imgur.com/WisD9.png
Я решил вышеупомянутые проблемы (P2-P6) отдельно с SLSQP, но понял, что решения, возможно, не были глобальным решением, так как SLSQP это локальный оптимизатор. Следовательно, я дал shgo снимок для P4, который не заканчивался ни в моем собственном терминале, ни в google colab (с использованием графического процессора) через 6-10 часов. Даже при установке параметров критерия остановки = {maxtime: 1} это не прекращалось для shgo. Может ли кто-нибудь сказать мне, что я сделал неправильно или предоставить мне альтернативные идеи / решатели? Я только начал читать документацию mysti c, и мой резервный план состоит в том, чтобы выполнить симуляцию Монте-Карло для догадок и найти оптимальный.
При этом код:
import os as os
path = os.path.dirname(os.path.realpath('__file__'))
from coskew import coskew
from cokurt import cokurt
from scipy.optimize import minimize, LinearConstraint, NonlinearConstraint, Bounds
from scipy.optimize import shgo
from scipy.optimize import differential_evolution
import numpy as np
import datetime
def polynomial_goal_programming(l0, df):
m3 = coskew(df)
m4 = cokurt(df)
# Step 1: Mathematical Optimization of Four Subproblems
def obj_mean(weights):
return -(np.sum(df.mean() * weights))
def obj_var(weights):
return np.dot(weights.T, np.dot(df.cov(), weights))
def obj_skew(weights):
return -(np.dot(weights.T, np.dot(m3,np.kron(weights,weights))))
def obj_kurt(weights):
return np.dot(weights.T, np.dot(m4,np.kron(weights,np.kron(weights,weights))))
def check_sum(weights):
'''
Returns 0 if sum of weights is 1.0
np.array(x[0]+x[1]+x[2]+x[3]+x[4]+x[5]+x[6]+x[7]+x[8]+x[9]+x[10]+x[11]-1)
'''
return np.sum(weights) - 1
# Initial Guess (equal distribution)
x0 = [1/len(df.columns)] * len(df.columns)
# 0-1 bounds for each weight -> no short selling
bounds = [(0, 1),] * len(df.columns) #float('inf')
#bounds = Bounds([0.]* len(df.columns), [1.]* len(df.columns))
# Constraints
cons = ({'type':'eq','fun': check_sum})
#lc = NonlinearConstraint(np.ones(len(df.columns)), lb=1, ub=1)
# Sequential Least SQuares Programming (SLSQP) -> pgp_simulation 15k no difference
opt_mean = minimize(obj_mean,x0,method='SLSQP',bounds=bounds,constraints=cons)
opt_var = minimize(obj_var,x0,method='SLSQP',bounds=bounds,constraints=cons)
#opt_skew = minimize(obj_skew,x0,method='SLSQP',bounds=bounds,constraints=cons)
time = datetime.timedelta(seconds=60)
opt_skew = shgo(obj_skew,bounds=bounds,constraints=cons,options=({'maxtime':time}))
#opt_skew = differential_evolution(obj_skew,bounds=bounds,constraints=(lc))
opt_kurt = minimize(obj_kurt,x0,method='SLSQP',bounds=bounds,constraints=cons)
#opt_kurt = shgo(obj_kurt,bounds=bounds,constraints=cons, n=1, iters=1)
opt = (-opt_mean.fun, opt_var.fun, -opt_skew.fun, opt_kurt.fun)
# Step 2: PGP
args = opt + l0
def obj(z0, a0,a1,a2,a3,a4,a5,a6,a7):
return np.power(1+np.abs(z0[0]/a0),a4) \
+ np.power(1+np.abs(z0[1]/a1),a5) \
+ np.power(1+np.abs(z0[2]/a2),a6) \
+ np.power(1+np.abs(z0[3]/a3),a7)
def constraint1(z0, a0,a1,a2,a3,a4,a5,a6,a7):
weights = z0[4:]
return np.sum(df.mean() * weights) + z0[0] - a0
def constraint2(z0, a0,a1,a2,a3,a4,a5,a6,a7):
weights = z0[4:]
return np.dot(weights.T, np.dot(df.cov(), weights)) - z0[1] - a1
def constraint3(z0, a0,a1,a2,a3,a4,a5,a6,a7):
weights = z0[4:]
return np.dot(weights.T, np.dot(m3,np.kron(weights,weights))) + z0[2] - a2
def constraint4(z0, a0,a1,a2,a3,a4,a5,a6,a7):
weights = z0[4:]
return np.dot(weights.T, np.dot(m4,np.kron(weights,np.kron(weights,weights)))) - z0[3] - a3
def check_sum(z0, a0,a1,a2,a3,a4,a5,a6,a7):
'''
Returns 0 if sum of weights is 1.0
'''
weights = z0[4:]
return np.sum(weights) - 1
# Initial Guess Goal and Weight Variables
d0 = [0]*4
# 0-1 bounds for each weight -> no short selling
d0_bnds = [(0, 50)] * 4 #float('inf')
bnds = d0_bnds + bounds
con1 = {'type':'eq','fun': constraint1, 'args':args}
con2 = {'type':'eq','fun': constraint2, 'args':args}
con3 = {'type':'eq','fun': constraint3, 'args':args}
con4 = {'type':'eq','fun': constraint4, 'args':args}
cons = {'type':'eq','fun': check_sum, 'args':args}
multi_cons = (con1, con2, con3, con4, cons)
opt_result = minimize(obj,d0+x0,args=args,method='SLSQP',bounds=bnds,constraints=multi_cons)
#opt_result = shgo(obj,bounds=bnds,args=args,constraints=multi_cons,n=1,iters=1,options={maxtime:1})
return opt_result