Adding a Beta-Neutrality Constraint to a Minimum-Variance Portfolio
Summary
The document explains how to add a market-neutrality condition to a long-only, fully invested minimum-variance portfolio in CVXPY. Given a vector of asset betas and portfolio weights, neutrality is imposed by requiring their dot product to equal zero. The discussion distinguishes this linear constraint from a quadratic form, which would express a different condition and is not suitable for setting portfolio beta to zero.
The example also notes that the optimization problem only needs to be solved once; repeating the same solve call without changing the inputs does not improve the result. The exchange answers are brief and provide no numerical portfolio output or treatment of feasibility. In particular, a long-only portfolio with weights summing to one may not be able to achieve zero beta for a given set of assets, so the stated constraints depend on the available beta values.
Key ideas
- Portfolio beta neutrality is expressed as the dot product of portfolio weights and asset betas equaling zero.
- The beta condition belongs in the optimization problem’s constraint list.
- A quadratic form of the weights and beta vector does not represent the intended linear beta constraint.
- Repeatedly solving an unchanged optimization problem is unnecessary.
Tags
Full text
# How to build a market-neutral portfolio using CVXPY?
# 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)
risk = quad_form(w, Sigma)
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.
## Answer by SRKX (score 1, accepted)
https://quant.stackexchange.com/a/30928
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.
## Answer by ThatQuantDude (score 1)
https://quant.stackexchange.com/a/30925
the constraint can simply be implemented by creating the following constraint
```
w.T*beta == 0
```Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.