|
| 1 | +.. _faq: |
| 2 | + |
| 3 | +#### |
| 4 | +FAQs |
| 5 | +#### |
| 6 | + |
| 7 | +Constraining the number of assets |
| 8 | +--------------------------------- |
| 9 | + |
| 10 | +Unfortunately, cardinality constraints are not convex, making them difficult to implement. |
| 11 | + |
| 12 | +However, we can treat it as a mixed-integer program and solve (provided you have access to a solver). |
| 13 | +or small problems with less than 1000 variables and constraints, you can use the community version of CPLEX: |
| 14 | +``pip install cplex``. In the below example, we limit the portfolio to at most 10 assets:: |
| 15 | + |
| 16 | + ef = EfficientFrontier(mu, S, solver=cp.CPLEX) |
| 17 | + booleans = cp.Variable(len(ef.tickers), boolean=True) |
| 18 | + ef.add_constraint(lambda x: x <= booleans) |
| 19 | + ef.add_constraint(lambda x: cp.sum(booleans) <= 10) |
| 20 | + ef.min_volatility() |
| 21 | + |
| 22 | +This does not play well with ``max_sharpe``, and needs to be modified for different bounds. |
| 23 | +See `this issue <https://github.com/robertmartin8/PyPortfolioOpt/issues/243>`_ for further discussion. |
| 24 | + |
| 25 | +Tracking error |
| 26 | +-------------- |
| 27 | + |
| 28 | +Tracking error can either be used as an objective (as described in :ref:`efficient-frontier`) or |
| 29 | +as a constraint. This is an example of adding a tracking error constraint:: |
| 30 | + |
| 31 | + from objective functions import ex_ante_tracking_error |
| 32 | + |
| 33 | + benchmark_weights = ... # benchmark |
| 34 | + |
| 35 | + ef = EfficientFrontier(mu, S) |
| 36 | + ef.add_constraint(ex_ante_tracking_error, cov_matrix=ef.cov_matrix, |
| 37 | + benchmark_weights=benchmark_weights) |
| 38 | + ef.min_volatility() |
| 39 | + |
| 40 | + |
0 commit comments