2

with the x1 and x2 dataframes being: alloc 0.400000 mean 0.000732 stdev 0.015961 rfr 0.000000

alloc 0.200000 mean 0.000957 stdev 0.016520 rfr 0.000000

def create_function_duo(x1df, x2df):
    def funct(xi):
        y=0
        
        y+=xi*(x1df.iat[1]-x1df.iat[3])/(x1df.iat[2]-x1df.iat[3])
        y+=(1-xi)*(x2df.iat[1]-x2df.iat[3])/(x2df.iat[2]-x2df.iat[3])
        #only includes minimization, answer is flipped to negative
        return -y
    xi=x1df.iat[0].item()
    bi = (0,None)
    be = (1,None)
    bnds = (bi, be)
    
    min_result = spo.minimize(funct, xi, method = 'SLSQP',  bounds = bnds, options = {'disp':True}) #, 
    print('minima found at')
    print(min_result.x, min_result.fun)
    
    return min_result.x

Explanation: I'm trying to maximize the sharpe ratio of two funds. I realize this is expected to just spit back 1, but I can't get the minimize function to turn back anything with the bounds. If I declare bounds=(1,0) I get 'int is not iterable'

If I use the above, it spits back 'ValueError: Objective function must return a scalar'

I've even tried to return -y.item() to convert it to a float instead, and that gives an error: 'ValueError: can only convert an array of size 1 to a Python scalar'

I have no idea what's wrong here. the function returns a value (tested), the function declaration is inside the outer function and all x1df and x2dfs should be 'constant' when minimize is called. I need to set the bounds so xi is only between 0 and 1, but y should be free to change. I've tried bi=(0,1), be=(None, None), as well as bi=(None, 0), be=(None, 1), even bi=(0,), be=(1,) ('ValueError: not enough values to unpack (expected 2, got 1)'). I looked at a bounds question here, but I don't believe I have a Xi variable instead of xi. I don't understand something with bounds, please let me know what I'm doing wrong.

user3452643
  • 182
  • 1
  • 7
  • xi should be a vector, but is it? Does this: xi=x1df.iat[0].item() select a single value? – Stefan Nov 08 '20 at 08:19
  • x1df.iat[0] selects a single value. I tried to add .item() in case converting from numpy float64 to python float would make a difference. It didn't as far as I can tell – user3452643 Nov 08 '20 at 08:36
  • I dont know this particular minimizing function, but I don't think it makes sense to minimize a function at a single value, so you should keep xi as a vector (then yi will be vector too). – Stefan Nov 08 '20 at 08:43
  • Another thing I can't see, is: what are the parameters that should change, while minimizing the function? – Stefan Nov 08 '20 at 08:45

1 Answers1

2

Bounds should be a sequence of (min,max) for each dimension. I understand you have 1 dimension, still it needs to be a sequence. So the following works (note bounds argument specifying min=0.0, max=1.0 bounds for the first, and only, argument xi)

    min_result = spo.minimize(funct, xi, method = 'SLSQP',  bounds = ((0,1),), options = {'disp':True}) #, 

and produces (the rest of your code intact)

Optimization terminated successfully    (Exit mode 0)
            Current function value: [-0.05792978]
            Iterations: 5
            Function evaluations: 10
            Gradient evaluations: 5
minima found at
[0.] [-0.05792978]
array([0.])
piterbarg
  • 8,089
  • 2
  • 6
  • 22