3 weak days in a row
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.
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.

