Reputation: 511
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)
Upvotes: 5
Views: 9296
Reputation: 15
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])
Upvotes: 1
Reputation: 1
I think the reply marked as correct in fact has given a incorrect example.covxopt matrix is column majored. so the sample G and h need to be transposed.
Upvotes: 0
Reputation: 199
the main this is to organize your ineq and eq constraints e.g if you want to allow short selling for 2 assets then -1<=x(i)<=1 and sum(x(i))=1. Thus tackle ineq, one has 4 ineq so G must be 4x2 and h is 4x1. Check it...G=[I/-I] where I is ones i.e. G=[[1,0],[0,1],[-1,0],[0,-1]] x s [x1,x2] and h=[1,1,1,1] if you use Gx<=h you get x1<=1, x2<=1 x1>=-1 and x2>=-1/. Equality time is Ax=b, b=1 and A=[1,1]..aagin check it, x1 +x2 = 1 which matches the constraint. P and Q you already have. You are now ready to solve.
Upvotes: 0
Reputation: 7070
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 mu
is q
in 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.
Upvotes: 5