Reputation: 1
I have used Python to perform optimization in the past; however, I am now trying to use a matrix as the input for the objective function as well as set bounds on the individual element values and the sum of the value of each row in the matrix, and I am encountering problems.
Specifically, I would like to pass the objective function ObjFunc
three parameters - w
, p
, ret
- and then minimize the value of this function (technically I am trying to maximize the function by minimizing the value of -1*ObjFunc
) by adjusting the value of w
subject to the bound that all elements of w
should fall within the range [0, 1] and the constraint that sum of each row in w
should sum to 1.
I have included a simplified piece of example code below to demonstrate the issue I'm encountering. As you can see, I am using the minimize
function from scipy.opimize
. The problems begin in the first line of objective function x = np.dot(p, w)
in which the optimization procedure attempts to flatten the matrix into a one-dimensional vector - a problem that does not occur when the function is called without performing optimization. The bounds = b
and constraints = c
are both producing errors as well.
I know that I am making an elementary mistake in how I am approaching this optimization and would appreciate any insight that can be offered.
import numpy as np
from scipy.optimize import minimize
def objFunc(w, p, ret):
x = np.dot(p, w)
y = np.multiply(x, ret)
z = np.sum(y, axis=1)
r = z.mean()
s = z.std()
ratio = r/s
return -1 * ratio
# CREATE MATRICES
# returns, ret, of each of the three assets in the 5 periods
ret = np.matrix([[0.10, 0.05, -0.03], [0.05, 0.05, 0.50], [0.01, 0.05, -0.10], [0.01, 0.05, 0.40], [1.00, 0.05, -0.20]])
# probability, p, of being in each stae {X, Y, Z} in each of the 5 periods
p = np.matrix([[0,0.5,0.5], [0,0.6,0.4], [0.2,0.4,0.4], [0.3,0.3,0.4], [1,0,0]])
# initial equal weights, w
w = np.matrix([[0.33333,0.33333,0.33333],[0.33333,0.33333,0.33333],[0.33333,0.33333,0.33333]])
# OPTIMIZATION
b = [(0, 1)]
c = ({'type': 'eq', 'fun': lambda w_: np.sum(w, 1) - 1})
result = minimize(objFunc, w, (p, ret), method = 'SLSQP', bounds = b, constraints = c)
Upvotes: 0
Views: 2373
Reputation: 231325
Digging into the code a bit. minimize
calls optimize._minimize._minimize_slsqp
. One of the first things it does is:
x = asfarray(x0).flatten()
So you need to design your objFunc
to work with the flattened version of w
. It may be enough to reshape it at the start of that function.
I read the code from a IPython session, but you can also find it in your scipy
directory:
/usr/local/lib/python3.5/dist-packages/scipy/optimize/_minimize.py
Upvotes: 1