# How to build a market-neutral portfolio using CVXPY?

I am trying to implement a simple minimum variance portfolio optimisation with a few simple constraints:

• long-only portfolio
• fully invested (sums to one)
• market-neutrality, i.e sum(betas) = 0.

I am not very experienced with cvxpy but I quite like it and want to implement my stuff with it going forward. Below is an example( from the cvxpy website), which uses

$$\min_x\;\; \frac{1}{2}x^T\Sigma x$$ Under the constraints $$x^T \mathbb{1}=1$$ $$\mu^Tx \geq \tau$$

I now want to add $B^Tx=0$, which will ensure that the portfolios beta is zero.

Here is the example:

from cvxpy import *
import numpy as np

np.random.seed(1)
n = 10
Sigma = np.random.randn(n, n)
Sigma = Sigma.T.dot(Sigma)

betas = [np.random.uniform(-1,1) for _ in range(10)]

w = Variable(n)

constraints = [sum_entries(w) == 1, w >= 0]
prob = Problem(Minimize(risk), constraints)

for i in range(100):
prob.solve()

print('Weights :', w.value)


How can I define the additional variable for beta and how do you alter your constraints list.

From the manual I assume we need something in the form a quad_form(), but does this have to be defined similarly to the risk variable in the example or inside the constraints object? how do you link it to the betas data vector?

I would have done something like

sum(quad_form(w, betas)) == 0


inside the constraints object which unfortunately doesn't work.

• I would compute the Betas outside of CVXOPT and use them as the coefficents in a linear equality constraint with 0 on the right hand side... Like $1.01*x_1+0.95*x_2+\cdots+1.20*x_n=0$ – Alex C Nov 5 '16 at 1:20
• I get the betas from a database I just use the calculated ones here as a working example – ThatQuantDude Nov 5 '16 at 1:29

The constraint you suggest is wrong as it implies $x^T B x = 0$ which is not what you want.

The right way to express $B^T x = 0$ is w.T * beta == 0 and you should including this in the constraints list:

constraints = [sum_entries(w) == 1, w >= 0, w.T * beta == 0]


Also the following lines look wrong:

for i in range(100):
prob.solve()


It seems you're solving a hundred times your problem. One call should be enough.

the constraint can simply be implemented by creating the following constraint

w.T*beta == 0