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*x

ls = 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”]

} elseif (ls[i–1]==–1){

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

}

#change long/short as appropriate

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

ls[i] = –1

} elseif (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.

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.