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)
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.
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.
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.
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])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With