Universal Investment Strategy – by Logical Invest – None too Sure!

Logical Invest Universal Investment Strategy

Ilya Kipnis Version

Quantopian Version

Here is the blurb from Logical Invest:

“The idea for this Universal Investment Strategy was to develop a strategy which has an adaptive allocation between 0% and 100% for each ETF (TLT / SPY) depending on the market situation.

The way to calculate the optimum composition is done by calculating which composition had the maximum Sharpe ratio during an optimized look back period (normally 50-80 days). During normal market periods, the maximum Sharpe ratio is not at a 100% SPY or at a 100% TLT allocation, but somewhere in between. To calculate this maximum Sharpe ratio, I loop through all possible compositions from 0%SPY-100%TLT to 100%SPY-0%TLT and calculate the resulting Sharpe ratio for the look back period.

For my UIS strategy I tweaked the Sharpe formula a little bit. Normally the Sharpe ratio is calculated by Sharpe = rd/sd with rd=mean daily return and sd= standard deviation of daily returns. I don’t use the risk free rate, as I only use the Sharpe ratio to do a ranking. My algorithm uses the modified Sharpe formula Sharpe = rd/(sd^f) with f=volatility factor. The f factor allows me to change the importance of volatility.

  • If f=0, then sd^0=1 the ranking algorithm will choose the composition with the highest performance without considering volatility.
  • If f=1, this is the normal Sharpe formula.
  • If f>1, then I rather want to find SPY-TLT combinations with a low volatility. With high f values, the algorithm becomes a “minimum variance” or “minimum volatility” algorithm.

To get good results, the f factor should normally be higher than 1. This way you do not need to rebalance too much. In a whipsaw market, rebalancing also has the negative effect of selling low and buying high on small intermediate market corrections. This is why a system which considers only performance will not do well.

The good f factor for a system can be found by “walk forward” optimization iterations of your backtests. Normally a good value for f is about 2, but the factor changes slightly, adapting to the current market conditions.”

I chose to code in Python and hence copied the coding found in the Quantopian link above, adapted for my own software:

returns = returns.pct_change().dropna()
ratio = [0, 1]
max_sharpe = -1000
ratios = []

for weight in np.arange(lower_bound, upper_bound, increment):
    ratios.append([weight, 1 - weight])

for c in range(len(ratios)):
    temp_returns = returns.ix[:, 0] * ratios[c][0] + returns.ix[:, 1] * ratios[c][1]
    sharpe = temp_returns.mean() / (temp_returns.std() ** volatilityFactor)

    if sharpe > max_sharpe:
        ratio = ratios[c]
        max_sharpe = sharpe

wts = ratio

There could of course be something wrong with my interpretation especially since my results do not match closely to a further version I drafted using Scipy Optimise with basin hopping. I must try a brute force grid search in Scipy and see how it compares with the brute force method outlined here.

I used unleveraged TLT and SPY taken from Yahoo before the selfish cads closed down their useful source of readily available data.

Anyway here is what I got:

Stat                 Logical Invest Universal Investment Strategy    S&P 500
-------------------  ----------------------------------------------  -----------
Start                2002-07-30                                      2002-07-30
End                  2016-12-20                                      2016-12-20
Risk-free rate       0.00%                                           0.00%

Total Return         425.82%                                         237.89%
Daily Sharpe         1.19                                            0.54
CAGR                 12.22%                                          8.83%
Max Drawdown         -20.46%                                         -55.25%
Monthly Vol (ann.)   10.45%                                          14.16%


The trouble is that in this (perhaps faultily constructed) version it did not do what it promised on the box: much of the time it took on / off binary bets as can be seen below:

binary bets

Here is what I get with  simple risk parity / inverse volatility weighting approach for a very slightly different period( a better risk adjusted return and a lower max dd):

Stat                 Inverse Volatility    Benchmark
-------------------  --------------------  -----------
Start                2002-10-30            2002-10-30
End                  2016-12-20            2016-12-20
Risk-free rate       0.00%                 0.00%

Total Return         233.98%               240.91%
Daily Sharpe         1.09                  0.55
CAGR                 8.90%                 9.06%
Max Drawdown         -17.88%               -55.25%

Monthly Vol (ann.)   8.41%                 13.78%
And here are the positions over time: notice that this achieves what the other system was supposed to achieve: morphing back and forth between the asset classes, no on/off binary switches:
I am not too sure I like the Logical Invest approach on a number of grounds but would be the first to confess that maybe the coding of my effort is simply wrong.
What worries me about the approach (as well as the on/off market timing) is the heavy reliance on negative correlation between TLT and SPY at crisis time. I’m just not too sure this will hold up. Which may not prove SO harmful to the risk parity approach. In any event I would prefer to add IEF to the mix (7 to 10 years US Govs) to downplay reliance on the highly volatile TLT. A lower return and correspondingly lower DD and std dev would be the result.
I have come to have deep suspicion for forecasting and market timing. To that end, a risk parity approach is far more comfortable. But not, of course, invincible!
I have also come to have deep scepticism for my own infallibility which is probably a good thing.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s