An open-source multi-asset portfolio optimizer

Fabian Scheler
November 20, 2021
A good portfolio is more than a long list of good stocks and bonds. It is a balanced whole, providing the investor with protections and opportunities with respect to a wide range of contingencies.

Harry Markowitz

Of course, there are countless software vendors providing highly sophisticated optimization and risk management packages. Unfortunately, those solutions are usually quite costly and require subscription to financial data. Beyond that, while a complex multi-factor model is certainly valuable in advanced portfolio construction (we use them a lot for tracking error and turnover optimized single stock strategies), it may actually be an overkill in many situations (for instance, when assessing the risk/return trade-off faced by a private investor interested in a fund or ETF based solution).

At the end of August, I added this small Shiny App to the quantamental platform introducing a portfolio optimization-based approach to foreign currency hedging. The application utilizes the Systematic Investor Toolbox for the optimization. We initially built on the Investing.com financial data API using investpy which, however, doesn't work anymore. An alternative could be yfinance which after several years seems to be supported by Yahoo Finance again.

I have since then extended this framework and developed the first beta version of an interactive multi-asset optimizer, based on the free Investing.com API and the R Optimization Infrastructure. The new optimizer (available under this link) also includes the differentiation between local and reference currency returns presented in my article on the FX Hedging Frontier but now allows the construction of complex, constrained portfolios. The complete source code is also on GitHub and is available upon request. It can easily be installed in a local or Docker environment.

While the optimizer is very easy to use in principle, some steps may not be intuitive. Most importantly, adding assets to the investment universe using investpy requires a couple of steps. For this reason, I have added a brief introduction video below, explaining how to use the app.

Of course, this optimization framework can still be improved in many ways. Among other things, current development efforts include the integration of a GARCH model to consider volatility clustering.

Comparing Results with Bloomberg

To run an optimization, the user first needs to define an investment universe by searching for assets using name or ISIN and adding them. This universe can subsequently be saved and revisited as the app is connected with an Amadeus Quantamental database. I have pre-configured a couple of universes that can be loaded by using an example account (see tutorial video above). One of the pre-configurd investment universes is a global multi-asset framework containing ETFs on European and US American Bonds (Government, Corporate Investment Grade, Corporate High Yield), European, US American, Emerging Markets and Japanese Equities as well as Gold.

I also uploaded the same set of assets to Bloomberg Port and compared optimization results that would have been obtained at the end of 2019 and 2020. I subsequently simulated the actual performance that the portfolios would have generated between December 2019 and November 2021.

In this case, I constructed a EUR denominated portfolio with a target return of 5% and minimum volatility given this constraint. For the sake of simplicity I deactivated the FX hedging optimization by forcing the weight of the hedged asset to zero for all foreign currency denominated investments.

As Shihao Gu (2021) pointed out, "predicting future excess stock returns with historical averages typically underperforms a naive forecast of zero by a large margin". I therefore feed both optimizers with the expected returns shown below (a mix of running yields and judgement).

Global multi-asset universe with expected returns

I haven't added any further constraints, neither in Port nor in the quantamental optimizer. It is a well known shortcoming of classical mean/variance optimization that it tends to generate highly concentrated corner portfolios. Covariance shrinkage is one way to increase robustness by reducing sampling error. The chart below compares the results for optimizations with different settings.

Interestingly, the Port optimizer (based on Bloomberg's proprietary multi-factor model) creates a highly concentrated portfolio containing only 5 out of the given 11 assets and with a 50% weight in the European High Yield ETF. I obtain a very similar result with the quantamental optimizer using a shrinkage lambda of 0.1. Compared to the Bloomberg solution, my optimizer substitutes European High Yield for European Equities and overweights the Gold ETF.

The effect of Covariance Shrinkage

I use the Herfindahl-Hirschman Index (HHI) to measure the concentration of the obtained unconstrained portfolios. The index is calculated as the sum of the squared percentage weight of all assets and ranges from close to 0 (perfect diversification) to 10.000 (only one asset with a weight of 100%).

As can be seen below, even in the absence of further constraints, portfolio concentration improves substantially with a higher shrinkage lambda. With a lambda of 0.4, the optimizer invests in 8 of the 11 assets and of course results improve further if the automatic FX hedging is enabled.

Portfolio concentration based on the HHI (lower = less concentrated)

Due to the return estimates given, a 5% target yield required a fairly high degree of risk taking and the portfolios consist mostly of Equities and High Yield. However, as the optimization date was set to the end of 2019, expected volatility estimates were rather low (too low). Interestingly, the Bloomberg optimizer with its highly concentrated portfolio gave the lowest volatility estimate and delivered the highest out of sample volatility, thus understimated portfolio risk the most.

It is also noteworthy, that compared to the December 2019 optimization, the December 2020 portfolio update resulted in even higher concentration when the Bloomberg optimizer was used.

Of course, the tested time period includes the Covid crisis which resulted in an exceptionally large gap. The rolling 90 and 260 days portfolio volatities have since reverted to the levels predicted initially. Bloomberg also acknowledges that its estimates are rather short-term while I utilized multi-year historical averages (eventually, adding a GARCH model makes more sense of course).

The findings emphasizes that the sophisticated multi-factor approach doesn't necessarily outperform a simple single factor mean/var optimization with covariance shrinkage. Portfolio optimization is a tricky exercise and more of an art than science. It is crucial to remember the Garbage-in, Garbage-put principle and carefully configure assumptions, constraints and other parameters.

Optimizer expected volatility based on historical averages and realized average portfolio volatility Dec 2019-Nov 2021
Realized annualized return and average volatility Dec 2019-Nov 2021