0
$\begingroup$

I am using python and the cvxopt library 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 as cmatrix
from cvxopt.blas import dot as cdot 
from cvxopt.solvers import qp, options 

# Number of assets
n = 4
# Convariance matrix
S = cmatrix( [[ 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 = cmatrix([.12, .10, .07, .03])

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

# bounds 
b = cmatrix([1.0,1.0,1.0,1.0,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 = [ cdot(pbar,x) for x in xs ]
risks = [ sqrt(cdot(x, S*x)) for x in xs ]


sharpes = [x/y for x,y in zip(returns,risks)]
max_sharpe = max(sharpes)
max_index = sharpes.index(max_sharpe)
print xs[max_index]

Output:

  File "<ipython-input-45-8e583df5adc5>", line 29, in <module>
    xs = [ qp(mu*S, -pbar, G, h, A, b)['x'] for mu in mus ]

  File "C:\Users\Anaconda\lib\site-packages\cvxopt\coneprog.py", line 4496, in qp
    return coneqp(P, q, G, h, None, A,  b, initvals)

  File "C:\Users\Anaconda\lib\site-packages\cvxopt\coneprog.py", line 1986, in coneqp
    raise ValueError("Rank(A) < p or Rank([P; G; A]) < n")

ValueError: Rank(A) < p or Rank([P; G; A]) < n
$\endgroup$
3
  • $\begingroup$ Any upper or lower bound can be expressed by $A<b$. Just append an identity matrix to $A$ and whatever the upper bound is to $b$ $n$ times. $\endgroup$
    – John
    Jun 2, 2014 at 23:56
  • $\begingroup$ Thanks John! I tried what you said but I get a ValueError. I edited the OP to show. Any thoughts? $\endgroup$
    – bobo5645
    Jun 3, 2014 at 2:47
  • $\begingroup$ Before I do an optimization, I try to verify that the objective function, its derivatives, the constraints, and derivatives of constraints are all right. Beyond that, I don't use cvxopt so really can't provide more guidance. $\endgroup$
    – John
    Jun 3, 2014 at 3:45

1 Answer 1

1
$\begingroup$

If you don't know the meaning of the other matrices, I'd look more at the docs and the definition of the quadratic program:

http://cvxopt.org/userguide/coneprog.html#quadratic-programming

This is also an example from the book:

http://www.ee.ucla.edu/~vandenbe/publications/mlbook.pdf

And there is a good deal of explanation there.

Finally, if you don't want to get into that I'd look at CVXPY which allow much simpler constraints (from their page):

# Construct the problem.
x = Variable(n)
objective = Minimize(sum_squares(A*x - b))
constraints = [0 <= x, x <= 1]
prob = Problem(objective, constraints)
$\endgroup$

Your Answer

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

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