It’s Amazing How Well Dumb Things Work?

Recently, Harry Long posted not one but four new articles on Seeking Alpha called It’s Amazing How Well Dumb Things Work II. The last time I replicated a strategy by Mr. Long, it came up short on the expectations it initially built. For the record, here are the links to the four part series.

First post
Second post (very valuable comments section)
Third post
Fourth post

While the strategy itself wasn’t the holy grail (nothing is, really, and it did outperform the S&P), it did pay off with some long-history ETF data for which I am extremely grateful (a project I’m currently working on involves those exact indices, I’ll see if I can blog about it), and it did give me the chance to show some R functionality that I hadn’t shown before that point, which in my opinion, made the endeavor more than worth it.

For this particular strategy, I’m not so sure that’s the case.

In short, the S&P 500, gold, and long-term bonds, rebalance to an equal-weight portfolio annually. Dirt simple. So simple, in fact, that I can backtest this strategy back to 1978!

The data I used was the actual GSPC index from Yahoo Finance, and some quandl data that I cleaned up with the quandClean function in my IKTrading package. While some of the futures I originally worked with have huge chunks of missing data, the long term bonds and gold futures are relatively intact. Gold had about 44 missing days in the 21st century when GLD had returns, so there may be some data integrity issues there, though the average return for GLD on those days is about -3 bps, so the general concept demonstration is intact. With the bonds, there were 36 missing days that TLT had returns for, but the average returns for those days were a -18 bps, so I instead imputed those missing days to zero.

In any case, here’s the script to set up the data:

require(IKTrading)
require(PerformanceAnalytics)
require(quantmod)

getSymbols("^GSPC", from="1800-01-01")
SPrets <- Return.calculate(Cl(GSPC))

goldFutures <- quandClean(stemCode = "CHRIS/CME_GC", verbose = TRUE)
getSymbols("GLD", from="1990-01-01") #quandl's data had a few gaps--let's use GLD to fill them in.
goldGLD <- merge(Cl(goldFutures), Cl(GLD), join='outer')
goldRets <- Return.calculate(goldGLD)
sum(is.na(goldRets[,1]))
mean(goldRets[is.na(goldRets[,1]),2], na.rm=TRUE)
goldRets[is.na(goldRets[,1]),1] <- goldRets[is.na(goldRets[,1]),2] #impute missing returns data with GLD returns data for that day
goldRets <- goldRets[,1]

thirtyBond <- quandClean(stemCode="CHRIS/CME_US", verbose = TRUE)
getSymbols("TLT", from="1990-01-01")
bondTLT <- merge(Cl(thirtyBond), Cl(TLT), join='outer')
bondRets <- Return.calculate(bondTLT)
sum(is.na(bondRets[,1]))
mean(bondRets[is.na(bondRets[,1]),2], na.rm=TRUE) #18 basis points? Just going to impute as zero.
bondRets[is.na(bondRets[,1]),1] <- 0 #there are 259 other such instances prior to this imputing
bondRets <- bondRets[,1]

SPbondGold <- cbind(SPrets, goldRets, bondRets)
SPbondGold <- SPbondGold["1977-12-30::"] #start off at beginning of 1978, since that's when gold futures were first in inception
colnames(SPbondGold) <- c("SandP", "Bonds", "Gold")

DTW_II_returns <- Return.rebalancing(R = SPbondGold, weights = c(1/3, 1/3, 1/3), geometric = FALSE, rebalance_on = "years")
stratSP <- merge(DTW_II_returns, SPrets, join='inner')
colnames(stratSP) <- c("Harry Long Strategy", "S&P 500")

First, let’s recreate the original equity curve, to prove that I’m comparing apples to apples.

#Recreate the original equity curve
charts.PerformanceSummary(stratSP["2004-12-01::"])

So, as you can see, everything seems to match, article confirmed, and that’s good.

But I wrote the backtest to go back to 1978, just so we can see as much of the performance as we possibly can. So, let’s take a look. Now, keep in mind that the article stated the following two assertions:

“As we previously observed, the approach has higher returns and lower drawdowns across an entire bull and bear market cycle than the S&P 500…” and that “…a portfolio manager who employed this decidedly humble, simple approach, would actually have been doing well for clients as a fiduciary.”

Let’s see if the full-period equity curve supports these assertions.

charts.PerformanceSummary(stratSP)

Here are some numerical values to put this into perspective:

> Return.cumulative(stratSP)
                  Harry Long Article  S&P 500
Cumulative Return           6.762379 20.25606
> Return.annualized(stratSP)
                  Harry Long Article    S&P 500
Annualized Return         0.05713769 0.08640992
> SharpeRatio.annualized(stratSP)
                                Harry Long Article   S&P 500
Annualized Sharpe Ratio (Rf=0%)           0.583325 0.4913877
> maxDrawdown(stratSP)
               Harry Long Article   S&P 500
Worst Drawdown           0.334808 0.5677539

In short, a 5.7% to an 8.6% annualized return in favor of the S&P 500 since 1978, with both sets of returns sporting substantial drawdowns compared to their annualized rates of return. So while this strategy gives a better risk-adjusted return, you get the return you pay for with the risks taken–smaller max drawdown for a similar Sharpe? Smaller return. Furthermore, the early 80s seem to have hurt this “all-weather” strategy more than the S&P 500.

For fun, let’s leverage the strategy 2x over and see what happens.

stratSP$leveragedStrat <- stratSP[,1]*2
charts.PerformanceSummary(stratSP)

And this is the resulting equity curve:

Hey, now we’re talking, right?! Well, the late 70s and early 80s say not exactly. But what if I wanted to make myself look better than the strategy justifies? Well, I can simply truncate those drawdowns, by just leaving off everything before 1985! (And put some marketing spin on it to justify it.)

charts.PerformanceSummary(stratSP["1985::"])

Here are some statistics:

> maxDrawdown(stratSP["1985::"])
               Harry.Long.Article   S.P.500 leveragedStrat
Worst Drawdown          0.2228608 0.5677539      0.4065492
> Return.annualized(stratSP["1985::"])
                  Harry.Long.Article    S.P.500 leveragedStrat
Annualized Return         0.05782724 0.08700208      0.1106892
> SharpeRatio.annualized(stratSP["1985::"])
                                Harry.Long.Article   S.P.500 leveragedStrat
Annualized Sharpe Ratio (Rf=0%)          0.6719875 0.4753468      0.6431376

Now look, higher returns, lower max drawdown, higher Sharpe, we can all go home happy?

Of course not. So what’s the point of this post?

Simply, to not believe everything you see at first glance. There’s often a phrase that’s thrown around that states “you’ll never see a bad backtest”–simply implying that if the backtest is bad, it’s thrown out, and all that’s left are the results with cherry-picked time frames, brute-force curve-fit parameter sets, and who knows what other sort of methodologies baked in to make a strategy look as good as possible.

On my blog, I try my best to be on the opposite side of the spectrum. In instances in which ideas were published years ago, some low-hanging fruit is an out-of sample test. On the opposite side of the spectrum, such as with Mr. Harry Long of SeekingAlpha here, when there are backtests with a very small time frame owing to newly released instruments, I’ll try and provide a much larger context. I provide the code, the data, and explanations in plain English, all to the best of my ability here on this blog. If you don’t wish to take my word for it, you can always run the scripts yourself. Worst to worst, leave a comment, and I’ll answer to the best of my ability.

I’ll have another Harry Long backtest replication up soon.

Thanks for reading.

12 thoughts on “It’s Amazing How Well Dumb Things Work?

  1. “I’ll try and provide a much larger context. I provide the code, the data, and explanations in plain English, all to the best of my ability here on this blog. If you don’t wish to take my word for it, you can always run the scripts yourself.”

    Bravo! That is what I really like about your work. You take nothing for granted and question everything, you test scientific rigor, and you provide code so that your research is repeatable. No one can ask for more.

    Very commendable indeed!

      • I try. Unfortunately, my abilities to understand things only goes so far. I have an undergrad engineering degree, and everything I did in my statistics masters, I needed to see a numerical example to truly understand. So once the mathematical and symbolic notation start flying, as they do in professorial papers, I have a far harder time understanding. If someone could train me to digest those things, I’d be eternally grateful.

  2. Pingback: The ZOMMA Warthog Index | QuantStrat TradeR

  3. Hello,

    Thanks for your detailed analysis. I would like to clarify a few points though:

    The Harry Long portfolio you are describing is Harry (another one) Browne’s Permanent Portfolio minus the cash part. This portfolio has a long track record of steady returns and low volatility by combining assets that react strongly to different market situations. The cash part omitted in Harry Long’s portfolio serves two purposes: as an anchor during recession or ‘tight money’ periods and as a barbell together with the long term bonds (LTB) to shorten their duration as if we had 50% inter-term bonds with less risk.

    Removing the cash allocation gives better returns with greater risks during times of tight money and inflation where LTB will hurt.

    It is possible to test all these asset allocations very easily using Bogleheads’ Simba spreadsheet from 1972. You’ll then see that both Harrys’ portfolios behave rather well compared to the S&P500 during that period with higher Sharpe and much higher Sortino ratios and much lower US and INTL market correlations.

    From 1972 to beginning 2014:
    100% S&P500 (VFINX): CAGR 10.21 Down SD 10.32 Sharpe .37 Sortino .64 US Corr .99 INTL corr .65

    Harry Long
    34% S&P500 (VFINX)
    33% LTB (VUSTX)
    33% Gold (GLD) : CAGR 10.05 Down SD 3.80 Sharpe .52 Sortino 1.45 US Corr .36 INTL corr .31

    Harry Browne w/ Larry Swedroe’s minimise Fat tails (from Fama/French model)
    12.5% US Small Cap Value (VISVX)
    8.5% INTL Small Cap Value (VFSVX)
    4% Emerging Markets (VEIEX)
    25% LTB (VUSTX)
    25% Cash
    25% Gold (GLD): CAGR 10.19 Down SD 2.57 Sharpe .64 Sortino 2.01 US Corr .26 INTL corr .48

    You are guilty of the same thing of which you accuse Harry Long: selecting a time window that serves your purpose. And so am I of course. I expect both Harrys portfolio to offer a smoother ride at all times (Browne’s much more so) than the S&P500 and as an investor, I will sleep better knowing I have a diversified portfolio hedged against most possible scenarios.

    • I’d contend that I selected a time window that serves my purpose, since I actually backtested this on the fly. In fact, maybe the next time Harry Long publishes an article, I might actually record a video of me creating a backtest “live”. But the reason I took the data out to the 70s is that was as far back as I could go for some of the instruments. If I could go back further, I actually would do that, as I have no horse in this race. It simply was a case of “Harry Long asserts something, let’s look at this over a longer period of time”. I had no knowledge beforehand of what type of performance I’d see, even if I did have a hunch that the SeekingAlpha article made the strategy look better than it would look over a longer time horizon.

      Also, I may look into Harry Browne’s strategy/allocation that you posted here as well.

Leave a comment