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

Tau value does not effect the weight-on-views in BL Model #367

Closed cemozerr closed 3 years ago

cemozerr commented 3 years ago

Describe the bug tau value does not affect the weight-on-views when the omega value is not provided in the Black-Litterman Model.

Expected behavior A user might want to pass both absolute and relative views to the BlackLittermanModel by passing arguments both P and Q, and might not want to explicitly provide omega. In that scenario, the user should be able to adjust the weight to these views by providing the tau value. Yet, the test_bl_tau in test_black_litterman.py only passes when passing in an explicit omega.

Code sample I've updated the test_bl_tau() to consume P and Q instead of absolute_views and/or omega, and it fails the test.

    def test_bl_tau(self):
        df = get_data()
        S = risk_models.sample_cov(df)

        prices = pd.read_csv(
            resource("spy_prices.csv"), parse_dates=True, index_col=0, squeeze=True
        )

        delta = black_litterman.market_implied_risk_aversion(prices)

        mcaps = get_market_caps()
        prior = black_litterman.market_implied_prior_returns(mcaps, delta, S)

        # Explicitly provide P and Q instead of absolute views
        views = np.array([0.25]).reshape(-1, 1)

        # Set P views
        picking = np.array(
            [
                [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
            ]
        )

        bl0 = BlackLittermanModel(
            S, pi=prior, P=picking, Q=views, tau=1e-10
        )
        bl1 = BlackLittermanModel(
            S, pi=prior, P=picking, Q=views,  tau=0.01
        )
        bl2 = BlackLittermanModel(
            S, pi=prior, P=picking, Q=views, tau=0.1
        )

        # For tiny tau, posterior should roughly equal prior
        # np.testing.assert_allclose(bl0.bl_returns(), bl0.pi.flatten(), rtol=1e-5)

        # For bigger tau, GOOG should be given more weight
        assert bl1.bl_returns()["GOOG"] > bl0.bl_returns()["GOOG"]
        assert bl2.bl_returns()["GOOG"] > bl1.bl_returns()["GOOG"]

Update Generally, changing the tau does not seem to be affecting anything in black litterman model unless you explicitly provide omega.

Operating system, python version, PyPortfolioOpt version e.g MacOS 11.4, python 3.9.2, PyPortfolioOpt 1.4.2

cemozerr commented 3 years ago

I do want to say @robertmartin8, I appreciate your work, it is an amazing library. Just curious if you have any idea why this bug might be arising. I'd be glad to make the fix.

robertmartin8 commented 3 years ago

Hi @cemozerr,

Apologies for the slow reply. This is explained in the docs here. Let me know if there are additional questions!

Cheers, Robert