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

Recently, Trading the odds posted one of many flavors of mean reverting strategies and I decided to get my hands dirty by writing R code and testing it.

You can find full description of the strategy by following latter link above. Long story short – if SPY shows lower open, high and close 3 days in a row, then buy on the close of third day and sell it 1 days later.
Let’s do simple test:

``` require('xts') require('quantmod') getSymbols('SPY',from='1995-01-01',index.class=c("POSIXt","POSIXct")) dividends=getDividends('SPY',from='1995-01-01',index.class=c("POSIXt","POSIXct"))   temp=cbind(dividends,SPY) temp[,1][is.na(temp[,1])]=0   SPY=cbind(temp[,2],temp[,3],temp[,4],temp[,1]+temp[,5]) colnames(SPY)=c('Open','High','Low','Close')   #one day before lag1=lag((SPY),1)   #two days defore lag2=lag((SPY),2)   signal=ifelse( (Cl(lag2)>Cl(lag1) & Cl(lag1)>Cl(SPY))& (Hi(lag2)>Hi(lag1) & Hi(lag1)>Hi(SPY)) & (Op(lag2)>Op(lag1) & Op(lag1)>Op(SPY)), 1,0 ) #one day later lag3=lag(Cl(SPY),-1)   profit=(lag3/Cl(SPY)-1)*signal profit[is.na(profit)]=0 png(file='first.png',width=500) plot(cumprod(profit+1),main='Profit 1995-2010') dev.off() ```

The code above supposed to produce something similar:

Nice curve, isn’t it? But neither commissions nor slippage were taken into account. So, let’s run more complicated test. For that purpose I utilized blotter package. Here’s the code:

``` require('xts') require('quantmod') require('blotter') require('PerformanceAnalytics') require('FinancialInstrument') getSymbols('SPY',from='1995-01-01',index.class=c("POSIXt","POSIXct")) dividends=getDividends('SPY',from='1995-01-01',index.class=c("POSIXt","POSIXct"))   temp=cbind(dividends,SPY) temp[,1][is.na(temp[,1])]=0   SPY=-cbind(temp[,2],temp[,3],temp[,4],temp[,1]+temp[,5]) colnames(SPY)=c('Open','High','Low','Close')   #one day before lag1=lag((SPY),1)   #two days defore lag2=lag((SPY),2)   signal=ifelse( (Cl(lag2)>Cl(lag1) & Cl(lag1)>Cl(SPY))& (Hi(lag2)>Hi(lag1) & Hi(lag1)>Hi(SPY)) & (Op(lag2)>Op(lag1) & Op(lag1)>Op(SPY)), 1,0 ) #one day later lag3=lag(Cl(SPY),-1)   symbols=c('SPY')   initDate=index(get(symbols)[1]) initEq=10000 rm(list=ls(envir=.blotter),envir=.blotter) ltportfolio='3days' ltaccount='3days' initPortf(ltportfolio,symbols, initDate=initDate) initAcct(ltaccount,portfolios=c(ltportfolio), initDate=initDate,initEq=initEq) currency("USD") stock("SPY",currency="USD",multiplier=1)   signal[is.na(signal)]=0   counter=0 for(i in 2:length(signal)) { currentDate= time(signal)[i] equity = 10000 #getEndEq(ltaccount, currentDate) #print(paste("equity ",equity)) position = getPosQty(ltportfolio, Symbol=symbols[1], Date=currentDate) print(currentDate) if(position==0) { #open a new position if signal is >0 if(signal[i]>0 &counter ==0) { print('open position') closePrice=as.double(Cl(SPY[currentDate])) unitSize = as.numeric(trunc((equity/closePrice))) commssions=-unitSize*closePrice*0.0003 addTxn(ltportfolio, Symbol=symbols[1], TxnDate=currentDate, TxnPrice=closePrice, TxnQty = unitSize , TxnFees=commssions, verbose=T) counter=1 } } else { #position is open. If signal is 0 - close it. if(position>0 &counter>=1) { print('close position>>>>') position = getPosQty(ltportfolio, Symbol=symbols[1], Date=currentDate) closePrice=as.double((Cl(SPY[currentDate])))#as.double(get(symbols[1])[i+100]) commssions=-position*closePrice*0.0003 addTxn(ltportfolio, Symbol=symbols[1], TxnDate=currentDate, TxnPrice=closePrice, TxnQty = -position , TxnFees=commssions, verbose=T) counter=0 } else counter=counter+1 } updatePortf(ltportfolio, Dates = currentDate) updateAcct(ltaccount, Dates = currentDate) updateEndEq(ltaccount, Dates = currentDate) } result=rez1\$symbols\$SPY\$txn[,7] result=result[result!=0]   png(file='second.png',width=500) #fix commission rate 2*3 plot(cumsum(result-6)) #next line will allow you to compare the performace with and without commissions #chart.CumReturns(cbind((result)/10000,(result-6)/10000)) dev.off() ```

Nice curve, but let’s look beyond that. First of all, here’s nice function in PerformanceAnalytics package, AnnulizedReturns:
table.AnnualizedReturns((result-6)/10000)
Gross.Txn.Realized.PL
Annualized Return 0.0265
Annualized Std Dev 0.0494
Annualized Sharpe (Rf=0%) 0.5366

Well, Sharpe ratio is not impressive. The profit percentage of this strategy is 57% and mean of profitable return is 111\$ against 98\$ loss. Profit factor is ~1.55.

I think, this strategy can be as one of the parameter or vote in another system, but alone it is weak.