It is late and I am tired, but I wanted to quickly explore an idea, where I use the ratio of the S&P500 divided by the US 10yr Treasury note yield as the trigger for when to get in and out of the S&P500. I have lots of things to check to see if this spurious or not, but none the less this is the code I came up with.
But before we look at the code you can see some nice out performance of the index. I haven’t factored in transaction costs or spread. Will check and amend if this is likely to be material.
Some visuals of the indicators
Finally the code: [Post script: On the 25th of December I improved on the findings originally posted here. I don’t like to delete my workings as I like to have a source of reference for the progression of my thinking.]
require(quantmod) require(PerformanceAnalytics) require(Quandl) start<- "1962-01-02" #get the data (S&P500 and US 10yr Treasury) spy<- Quandl("YAHOO/INDEX_GSPC", authcode="kvYEqCqKCTyL4anWz5Zv", type="xts") bond<- Quandl("FRED/DGS10", authcode="kvYEqCqKCTyL4anWz5Zv", type="xts") data<- merge(spy[,6],bond[,1]) data<- data["1962::"] # This is the magic signal or is it? It is the Nominal Price of the S&P500 / bond yield. # The fact that it is nominal worries me. ratio<- data[,1]/data[,2] ratio<- na.omit(ratio) # moving averages of the ratio ratio_short<- rollmean(ratio, k=20, align= "right") ratio_long<- rollmean(ratio, k=100, align= "right") # I like visual references ignore the red errors in the output console I am too lazy to fix up the axis. plot(data[,1], main="Mike's Bond Timer") par(new=TRUE) plot(ratio_long, col ='red') axis(4) par(new=TRUE) plot(ratio_short, col ='green') par(new=TRUE) plot(ratio, col ='blue') #our baseline, unfiltered results ret <- ROC(data[,1]) #our comparision, filtered result. The idea being to trade the ratio while it is above the long term m.average sig_long <- Lag(ifelse(ratio > ratio_long, 1, 0)) sig_short <- Lag(ifelse(ratio > ratio_short, 1, 0)) sig_long <- ret * sig_long sig_short <- ret * sig_short btimer<- cbind(sig_long, sig_short, ret) colnames(btimer) = c('BT Long', 'BT Short','Buy&Hold') table.AnnualizedReturns(btimer, Rf= 0.02/252) charts.PerformanceSummary(btimer, Rf = 0.02, main="Bond Timer",geometric=FALSE) maxDrawdown(btimer) tail(ma_sig)