robertmartin8 / PyPortfolioOpt

Financial portfolio optimisation in python, including classical efficient frontier, Black-Litterman, Hierarchical Risk Parity
https://pyportfolioopt.readthedocs.io/
MIT License
4.38k stars 940 forks source link

How to prevent negative weights / shorting with BlackLittermanModel #371

Closed anarchy89 closed 2 years ago

anarchy89 commented 3 years ago

I use the following command to create a black litterman model.

But I end up with a mixture of positive and negative weights.

Here is my code.

bl = BlackLittermanModel(S, pi=mu, market_caps=None, absolute_views=viewdict, risk_free_rate=0.01, weights_sum_to_one=True)

rets = bl.bl_returns()
ef = EfficientFrontier(rets, S)

# OR use return-implied weights
delta = black_litterman.market_implied_risk_aversion(market_prices)
bl.bl_weights(delta)
weights = bl.clean_weights()

My output looks like this,

OrderedDict([('aapl', -0.08586),
             ('adbe', 0.02735),
             ('amzn', 0.14253),
             ('ba', 0.02955),
             ('bac', -0.06451),
             ('csco', -0.05583),
........

I checked and the weights actually add up to 1 when the negative values are included, meaning there is shorting involved right?

How do I prevent shorting or negative weights?

If I add up only the positive weights it adds up to 2.67, the negative weights add up to 1.67. How do I make it so that it's long only adding up to 1?

robertmartin8 commented 2 years ago

Hi @anarchy89,

Apologies for the slow reply. By definition, bl_weights gives the unconstrained weights that correspond to the views – it is meant to be a "quick" way of seeing which weights correspond to a given set of views.

To calculate constrained weights, you should use the BL returns and BL cov matrix as an input to EfficientFrontier, which is long-only by default.

Hope this helps!

Robert