Constraining the number of portfolio assets

788 views
Skip to first unread message

tomhar...@gmail.com

unread,
Apr 3, 2017, 6:11:12 PM4/3/17
to cvxpy
I'm attempting to create a constraint in a portfolio optimization problem, so as to enforce a certain number of assets in the optimal solution. In simple logic, this means "the number of assets with a weight greater than zero must be at least k" for a long-only portfolio.

My initial thought was to implement by combining sum_entries and sum_largest, e.g. :

import numpy as np
import cvxpy as cvx

np.random.seed(12345)
n = 10
k = 8
mu = np.abs(np.random.randn(n, 1))
Sigma = np.random.randn(n, n)
Sigma = Sigma.T.dot(Sigma)
w = cvx.Variable(n)
ret = mu.T*w 
risk = cvx.quad_form(w, Sigma)
objective = cvx.Maximize(ret - risk)
constraints = [cvx.sum_entries(w) == 1, cvx.sum_largest(w, k) == 1, w >= 0]
prob = cvx.Problem(objective, constraints)
prob.solve()
print(w.value)

but the sum_largest constraint violates DCP and also this won't work logically. Is there is more straightforward way to "count" the number of entries that are included in the optimal solution (above some negligible threshold) and constrain around it? Very new to convex optimization, so I could be missing something
Message has been deleted

MarkusLondon

unread,
Apr 5, 2017, 12:19:40 PM4/5/17
to cvxpy
sorry couldn't edit or delete my reply, made a few changes

I was working on a similar implementation, there are a couple of ways of doing this, depending on your universe size. The accurate one would be to implement a mixed integer convex programming version of your code, which get's very computationally intense for #stocks > 20.The other one is do a non-cardinality constraint solving step over the universe, sort by weight(or what ever you are solving for), and start iteratively trimming the universe down until you reach your target universe size or the last solvable size. The risk part of your objective function should give you a reasonably good approximation, but you have to see what step size for the trimming is a good trade off between losing information and good speed. Another way would be using a l2-norm, there is a lot of literature out there describing cardinality constraints using norms. hope that will get you started 

tomhar...@gmail.com

unread,
Apr 5, 2017, 6:22:43 PM4/5/17
to cvxpy
Thank you Markus for the informative response. I think doing an MIP is unrealistic for the program I'm trying to build. Replicating this without a strict cardinality constraint (as you describe in your second suggestion) seems to be the best option for me, but I don't know how I can handle the scenario in which the number of non-zero weights is less than a desired minimum (e.g. if the optimal portfolio has 3 assets but I want at least 5). If there is anything you can point me toward that would be fantastic. I appreciate your help

MarkusLondon

unread,
Apr 5, 2017, 10:28:48 PM4/5/17
to cvxpy
i would argue that in terms of portfolio diversification such a low number of stocks wouldn't make much sense, but one way you could implement it would be minimum and maximum weights per stock and constraint on them, so basically do benchmark-x and benchmark+x for your weight constraints. Or do s.th like w>= 1/n in order to ensure you get enough stocks, really hard to say without knowing what your goal is.

tomhar...@gmail.com

unread,
Apr 6, 2017, 10:56:57 AM4/6/17
to cvxpy
The goal is to have any universe of assets (stocks/funds) and be able to ensure a minimum of k assets in the solution. Controlling this with a hard max (like 1/n) would achieve that, but wouldn't give me the outcomes I'm looking for. I need to set a minimum and say "w == 0 OR w >= min" and also ensure that "w >= min" occurs at least k times.

I don't know how to do this without implementing a mixed integer program, which is essentially infeasible for some of the universe sizes I will need to solve for. I'm okay with sacrificing accuracy, but I simply cannot see a way to approximate the constraints I'm looking for. 

You've been very helpful so far Markus, thank you again for your input. It is greatly appreciated

Steven Diamond

unread,
Apr 9, 2017, 5:17:43 AM4/9/17
to cvxpy
Here's one way to do it:

sum_smallest(w, n-k) >= gamma,   (gamma > 0)

This is a convex constraint, and it ensures that at least k assets are non-zero (specifically >= gamma/(n-k)).

MarkusLondon

unread,
Jul 24, 2017, 7:07:12 AM7/24/17
to cvxpy
Hi Steve, 

I am just looking your solution here, can you give some explanation what gamma is here ? Also can you also put an upper bound on this i.e. target number of stocks between x and y ?

Steven Diamond

unread,
Jul 28, 2017, 10:38:12 PM7/28/17
to cvxpy
gamma is an arbitrary positive parameter.
Reply all
Reply to author
Forward
0 new messages