I'm trying to do some portfolio construction in cvxpy in Python:

weight = Variable(n)
ret = mu.T * weight
risk = quad_form(weight, Sigma)

prob = Problem(Maximize(ret), [risk <= .01])

However I would like to include asset level risk budgeting constraints e.g. no asset can contribute more than 1% risk to the total risk. This constraint would look like (mctr = marginal contribution to total risk, actr = absolute contribution to total risk)

mctr = Sigma * weight / 0.1
actr = mul_elemwise(mctr, weight)
prob = Problem(Maximize(ret), [risk <= .01, actr <=.01])

However, when I try to do this cvxpy errors out with

>> mul_elemwise(mctr, w)
*** ValueError: The first argument to mul_elemwise must be constant.

And then I tried reformulating the constraint as

actr = diag(mctr, weight.T)

but still an error:

(Pdb) prob.solve()
*** cvxpy.error.DCPError: Problem does not follow DCP rules.

Now I understand why I'm getting these errors, but I also know that these are fairly common constraints, so I'm wondering how to formulate them into cvxpy so I can solve my optimization. Thanks


1 Answer 1


The underlying problem: your ACTR constraints aren't convex

The $i$th constraint on your risk contribution can be written:

$$ w_i \sum_j \sigma_{ij} w_j \leq c_i s$$ And this isn't a convex constraint because of the $w_j w_i$ terms (a function $g(x,y)=xy$ isn't convex in $x$ and $y$). They're not convex constraints, so you won't be able to write them as convex constraints in CVX's ruleset.

More detail on your optimization problem

Let $\mathbf{w}$ denote a vector of portfolio weights, $\boldsymbol{\mu}$ a vector of expected returns, $\Sigma$ a covariance matrix, $s$ the maximum standard deviation, $\mathbf{m}$ a vector of the maximum marginal contributions to risk, and $\mathbf{c}$ a vector of the the maximum contributions to risk.

Directly translating a maximize return subject to constraints on (1) standard deviation of portfolio returns, (2) marginal contribution to risk, and (3) marginal contribution to risk times portfolio weights where $\circ$ denotes the element wise product (i.e. hadammard product).

\begin{equation} \begin{array}{*2{>{\displaystyle}r}} \mbox{maximize (over $\mathbf{w}$)} & \boldsymbol{\mu}' \mathbf{w} \\ \mbox{subject to} & \sqrt{\mathbf{w}' \Sigma \mathbf{w}} \leq s\\ & \frac{1}{\sqrt{ \mathbf{w}' \Sigma \mathbf{w} }}\Sigma \mathbf{w} \leq \mathbf{m} \\ & \frac{1}{\sqrt{\mathbf{w}'\Sigma \mathbf{w}}}\left( \Sigma \mathbf{w} \right) \circ \mathbf{w} \leq \mathbf{c} \end{array} \end{equation}

Assuming the standard deviation constraint binds we have:

\begin{equation} \begin{array}{*2{>{\displaystyle}r}} \mbox{maximize (over $\mathbf{w}$)} & \boldsymbol{\mu}' \mathbf{w} \\ \mbox{subject to} & \sqrt{\mathbf{w}' \Sigma \mathbf{w}} \leq s\\ & \Sigma \mathbf{w} \leq s \mathbf{m} \\ & \left( \Sigma \mathbf{w} \right) \circ \mathbf{w} \leq s \mathbf{a} \quad \quad \text{<----- still not convex} \end{array} \end{equation}

We now have a convex optimization problem (i.e. convex objective subject to affine equality constraints and convex inequality constraints) EXCEPT for the last constraint! You won't be able to write the contribution to risk constraint as a convex constraint using CVX's ruleset because it is not convex!

What to do? One approach is to use a more generalized solver and be aware that you may encounter local maxima since the problem is not convex. You're right that these are common constraints. There are papers out there on this topic, and you could possibly examine some of the algorithms proposed. For example, the paper, "SCRIP: Successive Convex Optimization Methods for Risk Parity Portfolio Design" looks interesting, but I haven't read it closely enough to endorse it.

Further background on the problem: why these constraints?

Let $\mathbf{w}$ be a vector representing portfolio weights of $n$ risky assets (i.e. excluding the risk free rate), and Let $\Sigma$ be the covariance matrix of their returns..

The standard deviation of portfolio returns $R_p = \mathbf{w}' \mathbf{R} + \left( 1 - \sum_i w_i\right) r_f $ as a function of weights $\mathbf{w}$ are given by:

\begin{align*} f (\mathbf{w}) &= \operatorname{Std}(R_p) \\ &= \sqrt{\mathbf{w}'\Sigma\mathbf{w} } \end{align*}

Take the partial derivative with respect to portfolio weights and you get:

$$ \frac{\partial f}{\partial \mathbf{w}} = \frac{1}{f (\mathbf{w})}\Sigma \mathbf{w}$$

Observe that the standard deviation of returns $f(\mathbf{w})$ is homogenous of degree one in weights $\mathbf{w}$ (i.e. $f (\lambda \mathbf{w}) = \lambda f(\mathbf{w})$ hence by Euler's homogeneous function theorem:

$$ f(\mathbf{w}) = w_1 \frac{\partial f}{\partial w_1} +w_2 \frac{\partial f}{\partial w_2}+ \ldots + w_n \frac{\partial f}{\partial w_n} $$

A lot of people call $w_i \frac{\partial f}{\partial w_i}$ asset $i$'s contribution to risk since they nicely adds up to the total. But note that $w_i\frac{\partial f}{\partial w_i}$ does NOT measure what would happen to the standard deviation of portfolio returns if the entire position in asset $i$ is excluded.

Rather, it's a derivative. Observe $\frac{\partial f}{\partial \log w_i} = w_i \frac{\partial f}{\partial w_i}$ hence the term relates the change in standard deviation to an infinitesimally small percent change in position size. (You can show taking $\frac{d}{\log x}$ gives the derivative with respect to a percent change in $x$.)


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.