2

I am trying to solve a portfolio optimisation problem with the constraint that weights can be either zero or at least min (a Nx1 vector).

import cvxpy as cp

w = cp.Variable(len(mu))
mins = np.ones(len(mu)) * 0.03
risk = cp.quad_form(w, S)

prob = cp.Problem(cp.Minimize(risk), 
                  [cp.sum(w) == 1, 
                   w >= 0,
                   w >= min OR w == 0  # pseudocode for my desired constraint]

This is equivalent to a constraint that the weights are NOT 0 < w <= min, but I cannot find a way to express this in CVXPY (I have googled things like "cvxpy OR constraint" to no avail).

It feels like I'm missing something obvious. Perhaps there is a solution involving some boolean vector?

lagrange103
  • 169
  • 3
  • 9

2 Answers2

2

This is called w being a semi-continuous variable. Most advanced solvers support this type of variable directly. As CVXPY does not understand semi-continuous variables, we can use binary variables δ ∈ {0,1} and form the constraints:

   δ⋅min ≤ w ≤ δ⋅max

where we can set max=1.

This makes the problem a MIQP (Mixed-Integer Quadratic Programming) problem. This usually means that you need to use a high-end solver that supports this type of model.

Erwin Kalvelagen
  • 15,677
  • 2
  • 14
  • 39
  • Fantastic. That works well! I had tried something similar but without the maxes. No wonder that wasn't working :) – lagrange103 Jan 16 '21 at 13:20
1

Based on Erwin's answer, this is the working code.

import cvxpy as cp

w = cp.Variable(n)
mins = np.ones(n) * 0.03
maxs = np.ones(n)

risk = cp.quad_form(w, S)

prob = cp.Problem(cp.Minimize(risk), 
                  [cp.sum(w) == 1, 
                   w >= 0,
                   w >= cp.multiply(k, mins),
                   w <= cp.multiply(k, maxs)])
prob.solve(solver="ECOS_BB")

EDIT: changed k @ mins to cp.multiply(k, mins) as per comment

lagrange103
  • 169
  • 3
  • 9
  • 1
    Warning, ECOS_BB is not very reliable. I have seen many problems with this solver. Fine for experimentation, but don't use it for production models. – Erwin Kalvelagen Jan 16 '21 at 13:22
  • 1
    Also, you may want to use elementwise multiplication instead of matrix multiplication.. – Erwin Kalvelagen Jan 16 '21 at 13:26
  • @ErwinKalvelagen noted re the correctness issues. For anything serious I'd try CPLEX or MOSEK, but ECOS_BB is the only one that comes pre-packaged with cvxpy. – lagrange103 Jan 17 '21 at 03:38
  • Hi, could someone maybe explain what the k variable is in this scenario? I have am having a similar issue. – Aidan Donnelly Jul 07 '22 at 22:28