Take the 2-minute tour ×
Quantitative Finance Stack Exchange is a question and answer site for finance professionals and academics. It's 100% free, no registration required.

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
share|improve this question
    
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. –  John Jun 2 at 23:56
    
Thanks John! I tried what you said but I get a ValueError. I edited the OP to show. Any thoughts? –  bobo5645 Jun 3 at 2:47
    
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. –  John Jun 3 at 3:45

1 Answer 1

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)
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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