/cardiel

A tool for portfolio managers: use the Black-Litterman model to view optimal portfolio allocations using several of the most popular optimization methods.

Primary LanguagePython

Cardiel - A portfolio allocation tool based on Black-Litterman

Thomas Kirschenmann
thk3421@gmail.com

Description

This script is a tool for portfolio managers to input their market forecasts using the Black-Litterman (BL) method, and then use the resulting return vector and covariance matrix estimates as input for optimal portfolio allocations under several different portfolio optimization methods. The Black-Litterman model is a mathematically consistent way to combine a portfolio manager's views on future asset return distributions as a Bayesian prior, which combined with historical market data, produces a posterior distribution for asset returns and covariances. This is particularly useful, because a portfolio manager may have a view or forecast on individual securities, and a model like BL is required to propogate that view to other securities through an updated covariance matrix and expected return vector. If you have a view on one security, that implies you have a view on other securities because they are all correlated to varying degrees!

This tool will query market data for any security supported by Yahoo! Finance and can also be used with proprietary data in a CSV file.
The BL return vector and covariance matrix serve as inputs to any standard portfolio optimization methodology, such as Markowitz mean-variance optimization under a variety of utility functions. This tool calculates the optimal portfolio allocations using several methodologies and presents them simultaneously for side-by-side comparison, which helps guide a portfolio manager's decision to adjust the portfolio allocation.

A large portion of this tool relies on a terrific library put together by Robert Martin called PyPortfolioOpt. Tip o' the hat to Robert!

Steps for Using This Tool to Produce Portfolio Allocation Weights

Step 1: Pip install the required python libraries:

pip install argparse matplotlib numpy pandas statsmodels yfinance cvxopt joblib pypfopt

Step 2: Adjust the included config.json file to your situation.

The example file in the repo contains the necessary fields:

  • max_lookback_years -- the maximum number of years to query Yahoo! Finance for historical market data
  • annual_risk_free_rate -- the annual risk free rate
  • max_position_size -- the maximum allowed position size in percentage terms
  • min_position_size -- the minimum allowed position size in percentage terms
  • price_data -- set this string to "yahoo" to automatically query Yahoo! Finance or provide a path to a CSV file to use proprietary data
  • views -- See the note below
The "views" field is where the user can entry their views on individual securities in the form of 3 numbers per security. The first number is the user-provided lower bound annual return for a 1 standard deviation downward move. The second number is the user-provided estimated annual return, and the third number is the upper bound for a 1 standard deviation upward move. For example, if a user believes BABA stock is going to have a one-year return of 10% with a lower range forecast of -10% and upper bound forecast of 30% they can enter: "BABA":[-0.10, 0.10, 0.20]. Similarly, the user should repeat this process and enter their views for each asset of interest into their config.json file. A hypothetical example would be:
"views":{
            "BABA":[-0.10, 0.10, 0.20],
            "NVDA":[-0.10, 0.10, 0.30],
            "DIS":[-0.10, 0.07, 0.15],
            "BA":[-0.05, 0.07, 0.15],
            "XOM":[-0.05, 0.07, 0.15],
            "FB":[-0.05, 0.07, 0.15],
            "GOOG":[-0.05, 0.07, 0.15],
            "BAC":[0.0, 0.10, 0.25] 
        }
An argument can be made that if a portfolio manager does not hold any view whatsoever on a security, then it does not belong in their portfolio!

Step 3: Run the script and review the Black-Litterman results

From a terminal, simply run:

        python main.py --config config.json

and the program will load the daily adjusted close prices and compute the Black-Litterman return vector and covariance matrices. These will be automatically plotted and displayed for validation purposes. An example summary comparing the views, historical returns, and posterior returns looks like: Similarly, the Black-Litterman model covariance and correlations matrices are provided:

Cached Results

One may wish to repeat the above process several times if they are unhappy with the resulting BL returns and covariances. The Yahoo! query results are automatically cached in local directory, /cachedir, after being received on a given day. If the program is re-run on the same day with the same set of assets, then cached result will be used. This will speed up the program by skipping the Yahoo! query and allow for quicker iteration and data exploration.

Step 4: Choose a level of risk-aversion

Several optimization routines are automatically run (see details in the portfolio optimization methodology section of this document). Most of them require no further input from the user, however the most commonly used optimization is a Markowitz mean-variance optimization that requires the user to choose a level of risk-aversion. This is handled by viewing the efficient frontier, which is the expected return for an optimal portfolio for a given amount of risk (volatility). The risk aversion parameter is varied, which creates the full curve. The user is required to choose a point on the efficient frontier and enter the corresponding number into the terminal.
For example: The user seeing the efficient frontier in the chart above may think "I'm okay with 24% volatility for a 10.5% expected return, so I choose point number 2." Now enter that number into the terminal:

Step 5: Compare the portfolio allocations

The tool reports the portfolio allocation weight for each security, using several different optimization schemes. The portfolio optimizations are all foreced to obey the constraints specified in the config file. The portfolio optimizations are:

The various results should now be compared using the final chart produced. This is the main purpose of the tool, to get a feel for the portfolio weights recommended by a variety of algorithms:

The goal is now achieved: comparison of optimal portfolio allocations using a variety of methods, all based on the user-provided views that are married to historical data in a Bayesian way through the Black-Litterman model. The weights are automatically saved to a local CSV file as well. The user can now look for patterns in the assets and determine if they prefer to increase or decrease a particular holding in order to either reduce expected volatility or to increase potential returns.

Hope someone finds this useful or interesting! Please send me a note if you want me to add more output or a custom feature!

Best wishes, warmest regards!