SciPy optimization with grouped bounds

后端 未结 2 351
予麋鹿
予麋鹿 2020-12-13 11:45

I am trying to perform a portfolio optimization that returns the weights which maximize my utility function. I can do this portion just fine including the constraint that we

相关标签:
2条回答
  • 2020-12-13 12:00

    Not totally sure I understand, but I think you can add the following as another constraint:

    def w_opt(W):
        def filterer(x):
            v = x.range.values
            tp = v[0]
            lower, upper = tp
            return lower <= x[column_name].sum() <= upper
        return not W.groupby(level=0, axis=0).filter(filterer).empty
    
    c_ = {'type': 'eq', 'fun': w_opt}  # add this to your other constraints
    

    where x.range is the interval (tuple) repeated K[i] times where K is the number of times a particular level occurs and i is the ith level. column_name in your case happens to be a date.

    This says constrain the weights such that the sum of the weights in the ith group is between the associated tuple interval.

    To map each of the level names to an interval do this:

    intervals = [(.08,.51), (.05,.21), (.05,.41), (.05,.41), (.2,.66), (0,.16), (0,.76), (0,.11)]
    names = ['equity', 'intl_equity', 'bond', 'intl_bond', 'commodity', 'pe', 'hf', 'cash']
    
    mapper = Series(zip(names, intervals))
    fully_mapped = mapper[init_weights.get_level_values(0)]
    original_dataset['range'] = fully_mapped.values
    
    0 讨论(0)
  • 2020-12-13 12:17

    After much time this seems to be the only solution that fits...

    def solve_weights(Rt, b_ = None):
    
        W = np.ones(len(Rt.columns)) / len(Rt.columns)
        if  b_ is None:
            b_ = [(0.01, 1.0) for i in Rt.columns]
            c_ = ({'type':'eq', 'fun': lambda W: sum(W) - 1})
        else:
            covar = Rt.cov()
            c_ = ({'type':'eq', 'fun': lambda W: sum(W) - 1},
                  {'type':'eq', 'fun': lambda W: sqrt(np.dot(W, np.dot(covar, W)) * 252) - risk_tgt})
    
        optimized = opt.minimize(fitness, W, args = [Rt], method='SLSQP', constraints=c_, bounds=b_)  
    
        if not optimized.success: 
            raise ValueError(optimized.message)
    
       return optimized.x  # Return optimized weights
    
    class_cont = Rt.ix[0].copy()
    class_cont.ix[:] = np.around(np.hstack(Rt.groupby(axis=1, level=0).apply(solve_weights).values),3)
    scalars = class_cont.groupby(level=0).sum()
    scalars.ix[:] = np.around(solve_weights((class_cont * port_rets).groupby(level=0, axis=1).sum(), list(model['tactical'].values)),3)
    
    class_cont.groupby(level=0).transform(lambda x: x * scalars[x.name])
    
    0 讨论(0)
提交回复
热议问题