Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use cvxopt for mean variance optimization with constraints?

I am able to use cvxopt to calculate an efficient frontier, per the docs:

http://cvxopt.org/examples/book/portfolio.html

However, I cannot figure out how to add a constraint so that there is an upper bound on a particular asset's maximum allowed weight. Is that possible using cvxopt?

Here is my code so far that produces an efficient frontier with no constraints, except I believe b, which sets the max sum of weights to 1. I'm not sure what G, h, A, and mus do, and the docs don't really explain. Where does the 10**(5.0*t/N-1.0) in the formula for mus come from?

from math import sqrt
from cvxopt import matrix
from cvxopt.blas import dot 
from cvxopt.solvers import qp, options 

# Number of assets
n = 4
# Convariance matrix
S = matrix( [[ 4e-2,  6e-3, -4e-3,   0.0 ], 
             [ 6e-3,  1e-2,  0.0,    0.0 ],
             [-4e-3,  0.0,   2.5e-3, 0.0 ],
             [ 0.0,   0.0,   0.0,    0.0 ]] )
# Expected return
pbar = matrix([.12, .10, .07, .03])

# nxn matrix of 0s
G = matrix(0.0, (n,n))
# Convert G to negative identity matrix
G[::n+1] = -1.0
# nx1 matrix of 0s
h = matrix(0.0, (n,1))
# 1xn matrix of 1s
A = matrix(1.0, (1,n))
# scalar of 1.0
b = matrix(1.0)

N = 100
mus = [ 10**(5.0*t/N-1.0) for t in range(N) ]
options['show_progress'] = False
xs = [ qp(mu*S, -pbar, G, h, A, b)['x'] for mu in mus ]
returns = [ dot(pbar,x) for x in xs ]
risks = [ sqrt(dot(x, S*x)) for x in xs ]

#Efficient frontier
plt.plot(risks, returns)
like image 595
bobo5645 Avatar asked May 23 '14 15:05

bobo5645


People also ask

How does mean variance optimization work?

A mean-variance analysis is a tool that investors use to help spread risk in their portfolio. In it the investor measures an asset's risk, expressed as the “variance,” then compares that with the asset's likely return. The goal of mean-variance optimization is to maximize an investment's reward based on its risk.

What is Cvxopt in Python?

CVXOPT is a free software package for convex optimization based on the Python programming language. It can be used with the interactive Python interpreter, on the command line by executing Python scripts, or integrated in other software via Python extension modules.


2 Answers

You are using the quadratic programming solver of the cvxopt package, check out the documentation.

As you can see from the formula there, Gx <= h are the inequality constraints and Ax = b are the equality constraints. G and A are matrices, while h and b and are vectors.

Let's assume you want to restrict you're first asset to weights between 2% and 5%, you would formulate this as follows:

G = matrix([[-1, 0, 0, 0],
            [ 1, 0, 0, 0]])

h = matrix([[-0.02],
            [0.05]])

Note that the first row is turning the inequality condition into Gx >= h by multiplying by -1.

The conditions you have above set all assets to bounds between 0% and 100%, the common no short selling condition.

The formula your using is explained here: your muis qin the Wikipedia article and therefore a risk-tolerance parameter. It doesn't really matter if you attach it to the covariance or return part of the target function. It just means that you are either walking from the top right corner to the bottom left or the other way round for each value of mu. So it's just a function that gives you a risk-tolerance from very small to very big. I think there is a mistake though in that the series start at 0.1 but should really start at 0.

like image 107
Felix Zumstein Avatar answered Sep 17 '22 11:09

Felix Zumstein


I know this is old but it is very difficult to find a good constrained mean variance example anywhere;

Well the constraint part does not work like that;

In this case G Mat should be 4 X 4 and h should be 1 X 4 as below If a minimum threshold is required, one can input in "h" matrix as in my example below (20%) in this case. Yet, I could not manage to add max constraint.

G = matrix([[-1.0, 0.0, 0.0, 0.0],
       [0.0, -1.0, 0.0, 0.0],
       [0.0, 0.0, -1.0, 0.0],
       [0.0, 0.0, 0.0, -1.0]])


 h = matrix([-0.2, 0.0, 0.0, 0.0])
like image 1
skatip Avatar answered Sep 17 '22 11:09

skatip