# Backtesting a Trading Strategy

[This article was first published on

Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

I’ve ordered Time Series Analysis and Its Applications: With R Examples (Springer Texts in Statistics) to help me up the time series in R learning curve. So far what I have seen it looks good. The author has a good page with the issues in R and time series. The book should arrive by the end of the week.**Adventures in Statistical Computing**, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

In the meantime, I came across a trading strategy while reading an article provide on John Mauldin’s “Over My Shoulder” service (which I highly recommend). The crux of it was that in the bear market that started with the tech bubble crash, a strategy of betting on mean reversion of the S&P500 generated significant returns. Naturally I wanted to test.

Please note, I am not recommending anything that follows. Do your homework and speak with an investment professional if you have questions.

The strategy is to go long the S&P500 when the market closes at a maximum over the previous 3 days. Reverse the trade and go long when the market closes at the minimum over the previous 3 days. ETFs make this strategy relatively easy to trade. SPY will be our vehicle for being long the S&P500 and SH will be our vehicle for going short.

The SH began trading on 06/21/2006. We focus our backtesting from that point until now.

Using the importSeries() function we previously created, get all the values for SPY and SH.

to = “2012-01-14”

from = “2006-06-21”

spy = importSeries(“spy”,to=to,from=from)

sh = importSeries(“sh”,to=to, from=from)

series = merge(spy,sh)[,c(“spy.Open”,“spy.Close”,“spy.Return”,

“sh.Open”,“sh.Close”,“sh.Return”)]

We need to create some additional timeSeries to hold

- Long/Short Flag — lets us know the current status of our holdings.
- Trade Flag — signals that we instituted a trade on this date.
- Strat.Returns — nominal return for the day with the strategy.
- Dollar Amount — a gross dollar value of the portfolio assuming a $10,000 dollar value on 06/21/2006, and a $2 transaction fee when we trade.

After we calculate the strategy we will also create a gross return series from the Dollar Amount series.

f =

**function**(x) 0*xls = fapply(series[,1],FUN=f)

colnames(ls) = “long_short”

rets = fapply(series[,1],FUN=f)

colnames(rets) = “Strat.Return”

trades = rets;

colnames(trades) = “trade”

amt = rets

colnames(amt) = “DollarAmount”

amt[seq(1,3)] = 10000

We will loop from the 3rd day of the series until the end and calculate the values.

n = nrow(series)

**for**(i

**in**seq(3,n)){

maxSpy = max(series[seq(i,i–2),“spy.Close”])

minSpy = min(series[seq(i,i–2),“spy.Close”])

#get the appropriate return

**if**(ls[i–1] == 1){

rets[i] = series[i,“spy.Return”]

}

**else****if**(ls[i–1] == –1){ rets[i] = series[i,“sh.Return”]

}

#change long/short as appropriate

**if**(maxSpy == series[i,“spy.Close”]){

ls[i] = –1

}

**else****if**(minSpy == series[i,“spy.Close”]){ ls[i] = 1

}

**else**{ ls[i] = ls[i–1]

}

#mark a trade if we did one

**if**(ls[i] != ls[i–1]) trades[i] = 1

#Calculate the dollar amount

amt[i] = amt[i–1]*exp(rets[i])

**if**(trades[i]) amt[i] = amt[i] – 2

}

#Calculate gross returns

amt2 = returns(amt)

colnames(amt2) = “Strat.DollarReturns”

Next let’s output the annualized returns and CAPM statistics. We will do this for the entire period as well as for each year.

#Merge all the series

series=merge(series,ls)

series = merge(series,rets)

series = merge(series,trades)

series = merge(series,amt)

series = merge(series,amt2)

vars = c(“spy.Return”,“sh.Return”,“Strat.DollarReturns”)

series[1,vars] = 0

#Calculate the Annualized Statistics and the CAPM statistics

print(“Total”)

table.AnnualizedReturns(series[,vars])

table.CAPM(as.xts(series[,“Strat.Return”,drop=FALSE]),as.xts(series[,“spy.Return”,drop=FALSE]))

#Overall cumulative returns

png(“c:\\temp\\overall.png”)

chart.CumReturns(series[,vars],main=“Total Return”,legend.loc=“topleft”)

dev.off()

#Create the outputs for each year.

**for**(year

**in**seq(2006,2011)){

start = paste(year,“-01-01”,sep=“”)

end = paste(year,“-12-31”,sep=“”)

title = paste(“Total Return “,year,sep=“”)

file = paste(“c:\\temp\\”,year,“.png”,sep=“”)

s = window(series,start=start, end=end)

png(file)

chart.CumReturns(s[,vars],main=title,legend.loc=“topleft”)

dev.off()

print(paste(year,“Returns”,sep=” “))

print(table.AnnualizedReturns(s[,vars]))

print(table.CAPM(as.xts(s[,“Strat.Return”,drop=FALSE]),as.xts(s[,“spy.Return”,drop=FALSE])))

}

spy.Return | sh.Return | Strat.DollarReturns | |

Annualized Return | -0.0067 | -0.0903 | 0.3535 |

Annualized Std Dev | 0.2529 | 0.2512 | 0.2508 |

Annualized Sharpe (Rf=0%) | -0.0263 | -0.3593 | 1.4092 |

Strat.Return to spy.Return | |

Alpha | 0.0013 |

Beta | 0.1921 |

Beta+ | 0.6830 |

Beta- | -0.0803 |

R-squared | 0.0374 |

Annualized Alpha | 0.3990 |

Correlation | 0.1934 |

Correlation p-value | 0.0000 |

Tracking Error | 0.7447 |

Active Premium | 0.3694 |

Information Ratio | 0.4960 |

Treynor Ratio | 1.8885 |

So there seems to be something to this strategy. The yearly return and CAPM tables are close to the total. Some years are better than others. I will leave it to you to create and study them (mostly to save space on here).

There are things to think of:

- It should be noted that this strategy is NOT tax efficient — any gains will be taxed at the short term capital gains rate.
- There were 411 trades. A trade involves buying and selling, so 822 times would you be charged a brokerage fee. I assumed 1 dollar per buy/sell — what is charged by Interactive Brokers. Using someone like TD Ameritrade would cost FAR more.
- This also assumes that you can buy and sell at the market closing price. Something that is possible, but slippage will occur.

To

**leave a comment**for the author, please follow the link and comment on their blog:**Adventures in Statistical Computing**.R-bloggers.com offers

**daily e-mail updates**about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.

Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.