-1

I want to optimise my portfolio using Markowitz theory (risk minimization by the Markowitz method for a given income = 15%) and Scipy.minimize

I have risk function

def objective(x):   
    x1=x[0];x2=x[1];x3=x[2]; x4=x[3]
    return 1547.87020*x1**2 + 125.26258*x1*x2 + 1194.3433*x1*x3 + 63.6533*x1*x4  \
    + 27.3176649*x2**2 + 163.28848*x2*x3 + 4.829816*x2*x4 \
    + 392.11819*x3**2 + 56.50518*x3*x4 \
    + 34.484063*x4**2

Sum of parts of stocks(in %) = 1

def constraint1(x):
    return (x[0]+x[1]+x[2]+x[3]-1.0)

Income function with restriction

def constraint2(x):     
    return (-1.37458*x[0] + 0.92042*x[1] + 5.06189*x[2] + 0.35974*x[3] - 15.0)

And I test it using:

x0=[0,1,1,0] #Initial value
b=(0.0,1.0) 
bnds=(b,b,b,b)
con1={'type':'ineq','fun':constraint1}
con2={'type':'eq','fun':constraint2}
cons=[con1,con2]
sol=minimize(objective,x0,method='SLSQP',\
             bounds=bnds,constraints=cons)

And my result is:

     fun: 678.5433939
     jac: array([1383.25920868,  222.75363159, 1004.03005219,  130.30312347])
 message: 'Positive directional derivative for linesearch'
    nfev: 216
     nit: 20
    njev: 16
  status: 8
 success: False
       x: array([0., 1., 1., 1.])

But how? Sum of parts of portfolio cant be more than 1(now parts of stock 2=stock3=stock4=100%). Its constraint1. Where is problem?

SuperKogito
  • 2,998
  • 3
  • 16
  • 37

2 Answers2

1

The output says "success: False" So it is telling you that it failed to find a solution to the problem.

Also, why did you put con1={'type':'ineq','fun':constraint1}

Don't you want con1={'type':'eq','fun':constraint1}

I got success using method='BFGS'

Sohrab T
  • 625
  • 4
  • 14
1

Your code is returning values that do not respect your constraint due to false definition of the first constraint (a-b >= 0 => a>b) so in your case a=1(the order in an inequality is important). On the other hand your x0 must also respect your constraints and sum([0,1,1,0]) = 2 > 1. I slightly improved your code and fixed the aforementioned issues, but I still think that you need to review your second constraint:

import numpy as np
from scipy.optimize import minimize


def objective(x):   
    x1, x2, x3, x4 = x[0], x[1], x[2], x[3]
    coefficients   = np.array([1547.87020, 125.26258, 1194.3433, 63.6533, 27.3176649, 163.28848, 4.829816, 392.11819, 56.50518, 34.484063])
    xs             = np.array([     x1**2,     x1*x2,     x1*x3,   x1*x4,      x2**2,     x2*x3,    x2*x4,     x3**2,    x3*x4,     x4**2])
    return np.dot(xs, coefficients)

const1 = lambda x: 1 - sum(x)
const2 = lambda x: np.dot(np.array([-1.37458, 0.92042, 5.06189, 0.35974]), x) - 15.0

x0   = [0, 0, 0, 0] #Initial value
b    = (0.0, 1.0) 
bnds = (b, b, b, b)
cons = [{'type':'ineq','fun':const1}, {'type':'eq', 'fun':const2}]

# minimize
sol  = minimize(objective,
                x0,
                method      = 'SLSQP',
                bounds      = bnds,
                constraints = cons)

print(sol)

output:

     fun: 392.1181900000138
     jac: array([1194.34332275,  163.28847885,  784.23638535,   56.50518036])
 message: 'Positive directional derivative for linesearch'
    nfev: 92
     nit: 11
    njev: 7
  status: 8
 success: False
       x: array([0.00000000e+00, 5.56638069e-14, 1.00000000e+00, 8.29371293e-14])
SuperKogito
  • 2,998
  • 3
  • 16
  • 37
  • Coefficients in objective function is coefficients from covariation matrix. It is risk function. I try to minimise it. Constraint1 is a restriction on the portfolio(sum should be = 1). I also have restrictions on the profitability(constraint2) of the portfolio (not more profitable than 15%). Coefficients in constraint2 is mean profit of stocks. And I havent ideas where can be problem. Can the problem be in all coefficients in constraints? I mean, maybe this is bad data or not enough to get normal coefficients to solve the optimization problem? – Ильшат Мурзурбеков May 31 '19 at 17:45
  • From what I see, your issues are not code related but rather theoretical. You need to first figure the theory out. – SuperKogito May 31 '19 at 18:06