This question is related to recent rule changes in the Quantopian Open.

I am trying to figure out a closed form solution to a beta constrained minimum variance portfolio problem but it doesn't seem particularly tractable. Has anyone else tried this? So far, I have set up the problem

$$\begin{align} \min_w \quad& w^\prime \Sigma w \\ s.t. \quad& w^\prime\vec 1 = 1 \\ \text{and} \quad & w^\prime \beta = c \end{align}$$


  • $w$ is the vector of portfolio weights, our control
  • $\Sigma$ is the total covariance matrix
  • $\beta$ is the vector of CAPM-type market betas
  • $c$ a constant that the portfolio beta should be equal to

Changing constraints to Lagrange multipliers the objective becomes

$$\min_w \quad w^\prime\Sigma w - \lambda_1(w^\prime\vec 1 - 1) - \lambda_2(w^\prime\beta - c)$$

the first order conditions are

$$\begin{align} 0 &= 2w^\prime\Sigma - \lambda_1\vec 1 - \lambda_2 \beta\\ 1 &= w^\prime\vec 1\\ c &= w^\prime\beta \end{align}$$

I cannot seem to get the equations to work out nicely, perhaps no closed form solution exists but I wanted to check here and see if anyone could get something reasonable before I go to numerical optimization.

  • $\begingroup$ The constraints can be grouped together to something like $Aw=b$, so that the lambdas are a vector. This set-up is actually pretty common. I typically refer to the derivation in edoc.hu-berlin.de/master/jiao-wei-2003-12-16/PDF/jiao.pdf $\endgroup$
    – John
    Jun 4, 2015 at 18:44
  • $\begingroup$ @John I like this reference but I would suggest pointing interested readers to page 7 (pdf page 15) when making it $\endgroup$
    – user25064
    Jun 5, 2015 at 13:43

2 Answers 2


Assuming that $\Sigma$ is invertible, then \begin{align} 2\omega' = \lambda_1\overrightarrow{1}'\Sigma^{-1}+\lambda_2\beta'\Sigma^{-1}. \end{align} We can then solve $\lambda_1$ and $\lambda_2$ from the system of equations \begin{align*} 2 &= \lambda_1\overrightarrow{1}'\Sigma^{-1}\overrightarrow{1}+\lambda_2\beta'\Sigma^{-1}\overrightarrow{1}\\ 2c &= \lambda_1\overrightarrow{1}'\Sigma^{-1}\beta+\lambda_2\beta'\Sigma^{-1}\beta. \end{align*} Consequently, $\omega$ can be obtained from the above equation.

  • $\begingroup$ I was hoping for some cute $w = \ldots$ reduced form type equation but this certainly answers the question. edit - I bet mathematica could help but I don't own it $\endgroup$
    – user25064
    Jun 4, 2015 at 16:37
  • $\begingroup$ @user25064, I believe this can be done in Excel 2010. $\endgroup$
    – Gordon
    Jun 4, 2015 at 17:24
  • $\begingroup$ I was referring to symbolic manipulation... $\endgroup$
    – user25064
    Jun 4, 2015 at 17:25

This is an interesting problem. I don't think the problem is set up correctly quite yet. I rewrote it slightly to correspond to how it's generally written as a quadratic program.

The optimization problem you write down fixes betas to be a certain value. That could make sense but instead I wondered if we could simply minimize beta across the portfolio while minimizing correlations. In that case, the optimization problem becomes:

\begin{align} \min_w \quad& w^\prime \Sigma w + w^\prime\lvert\beta\rvert\\ s.t. \quad& w^\prime\vec 1 = 1 \\ \text{and} \quad & w > 0 \end{align}

I don't think a closed-form solution exists to this problem. But it's quite easy (and fast) to solve this with a quadratic optimizer such as provided by cvxopt. Here is some example code:

import numpy as np import matplotlib.pyplot as plt import cvxopt as opt from cvxopt import blas, solvers import pandas as pd np.random.seed(123) # Turn off progress printing solvers.options['show_progress'] = False ## NUMBER OF ASSETS n_assets = 4 ## NUMBER OF OBSERVATIONS n_obs = 1000 # Generate returns return_vec = np.random.randn(n_assets, n_obs) betas = np.array([.1, .8, .2, .05]) def markowitz_beta(returns, betas): n = len(returns) returns = np.asmatrix(returns) # Convert to cvxopt matrices # minimize: w * mu*S * w + betas * x S = opt.matrix(np.cov(returns)) # Minimize betas, can add mean returns here if desired pbar = opt.matrix(np.abs(betas)) # Create constraint matrices # Gx < h: Every item is positive G = opt.matrix(-np.eye(n)) # negative n x n identity matrix h = opt.matrix(np.zeros(n)) # Ax = b sum of all items = 1 A = opt.matrix(1.0, (1, n)) b = opt.matrix(1.0) # CALCULATE THE OPTIMAL PORTFOLIO wt = solvers.qp(S, pbar, G, h, A, b)['x'] return np.asarray(wt).ravel() weights = markowitz_beta(return_vec, betas) print weights print betas.ravel() print np.dot(weights, betas) Output: [ 3.50677883e-01 3.34638307e-07 2.50326847e-01 3.98994936e-01] [ 0.1 0.8 0.2 0.05] 0.105083172131

As you can see, the highest betas receive very low weights.

We also wrote a blog post on this (and the code is a version from there) which you can find here: https://www.quantopian.com/posts/the-efficient-frontier-markowitz-portfolio-optimization-using-cvxopt-repost-cloning-of-nb-now-enabled

Disclaimer: I work at Quantopian.

  • 1
    $\begingroup$ You just wrote down a different problem which is totally fine. The problem I was trying to solve has a closed form solution because my constraint is an equality constraint (I happen to use $c=0$) and I allow long/short portfolios. Still interesting and illustrative, thanks $\endgroup$
    – user25064
    Aug 5, 2015 at 12:51
  • $\begingroup$ Ah, you're probably right in that case. I wonder in which cases you would want to target a specific beta value for your portfolio though. $\endgroup$
    – twiecki
    Aug 5, 2015 at 12:54
  • $\begingroup$ Separately, I posted this NB on our forums: quantopian.com/posts/… $\endgroup$
    – twiecki
    Aug 5, 2015 at 12:54

Your Answer

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

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