Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Constraint on portfolio variance

Hi,

I want to maximize return but set a constraint such the the portfolio variance is less than or equal to a threshold. Anyone knows how to do it with CVXPY?

Best regards,
Pravin

7 responses

Ignore me. I found the answer. It's an SOCP and CVXPY automatically does that for you.

If you have a look at my recent posts on https://www.quantopian.com/posts/minimum-variance-w-slash-constraint , you'll see a form for the variance, in CVXPY:

    prices = data.history(context.stocks,'price',context.N*390,'1m')  
    ret = prices.pct_change()[1:].as_matrix(context.stocks)  
    p = prices.as_matrix(context.stocks)  
    ret_mean = np.mean(ret,axis=0)  
    ret_mean_norm = ret_mean/np.std(ret,axis=0)  
    p = np.squeeze(np.asarray(ret))  
    Acov = np.cov(p.T)  
    x = cvx.Variable(m) # portfolio weights to be found  
    variance = cvx.quad_form(x, Acov)  

I think it is a matter of using the variance as one of the constraints, instead of the objective to be minimized. I'm a little fuzzy on the scaling here. If you'll be setting a threshold on the variance, it would seem that if you use the variance of the returns in percent, everything should be o.k. However, perhaps there is some scaling with the number of securities in the universe that is unaccounted for? Basically, you need the constraint to be written in such a way that it is not some kind of magic number, if you are going to set a fixed threshold (alternatively, you could use a dynamic threshold).

Thanks Grant.

No problem. If you sort it out, perhaps you could share a code snippet here. I'd be interested. --Grant

def getWeights(signal, cov):  
    (m, m) = cov.shape  
    x = cvx.Variable(m)  
    risk = cvx.quad_form(x, cov)  
    alpha = signal.T * x  
    objective = cvx.Maximize(alpha)  
    constraints = [risk < np.min(np.diag(cov))]  
    prob = cvx.Problem(objective, constraints)  
    prob.solve(solver=cvx.CVXOPT)  
    return x.value  

What is the idea behind:

constraints = [risk < np.min(np.diag(cov))]  

Also, don't you need a constraint on the leverage:

cvx.sum_entries(x) == 1  

or

cvx.sum_entries(cvx.abs(x)) == 1  
constraints = [risk < np.min(np.diag(cov))]  

implies that the portfolio risk is less than the risk of any stock in the portfolio. I just used this as an example. You could have other thresholds.

cvx.sum_entries(cvx.abs(x)) == 1  

This won't work because absolute constraint is not convex.