Monday, 1 May 2017

Backtesting Trading Strategy in R

We backtested a simple trading strategy earlier in Excel.

The same strategy has been implemented in R in this post. RStudio (version 0.99.902) was used as IDE. In this case, a function called MovingAverageStrategy has been written that takes four arguments: the file location, start row for SMA calculation, start row for LMA calculation and the row from which trading calculation is to be commenced. The code is fairly simple to understand and uses for loop and ifelse constructs.

The data for this code has been downloaded in the same way as in the post on Excel. Two columns called SMA and LMA have been added in the .csv file with values added for the first 4 and first 19 rows, respectively.

The code is shown below:

MovingAverageStrategy <- function(file,SMAStart,LMAStart,TradeStart)
{

# read the downloaded .csv file
data_frame <- read.table(file,sep=",", header=TRUE)
ntotal = nrow(data_frame)

# initialize the new columns
data_frame$TradeSignal = ""
data_frame$TradePrice = 0
data_frame$Return = 0

# for loop to calculate SMA, LMA, TradeSignal, TradePrice, Return 
for (i in 1:ntotal){
  if(i>=SMAStart){
    data_frame$SMA[i] = mean(data_frame$Close[(i-(SMAStart-1)):i])
  }
  if(i>=LMAStart){
    data_frame$LMA[i] = mean(data_frame$Close[(i-(LMAStart-1)):i])
  }
  if(i>=TradeStart){
    data_frame$TradeSignal[i] = ifelse((data_frame$SMA[i-1]<data_frame$LMA[i-1])&&(data_frame$SMA[i]>data_frame$LMA[i]),"BUY",ifelse((data_frame$SMA[i-1]>data_frame$LMA[i-1])&&(data_frame$SMA[i]<data_frame$LMA[i]),"SELL",""))

    data_frame$TradePrice[i] = ifelse(data_frame$TradeSignal[i-1] != "",data_frame$Open[i],data_frame$TradePrice[i-1])

    data_frame$Return[i] = 100*ifelse((data_frame$TradeSignal[i-1] != "")&&(data_frame$TradePrice[i-1] != 0),ifelse( data_frame$TradeSignal[i-1] == "BUY",1-(data_frame$TradePrice[i]/data_frame$TradePrice[i-1]),(data_frame$TradePrice[i]/data_frame$TradePrice[i-1])-1),0)
      }
}

# Trade Calculations
TotalReturns=as.numeric(data_frame$Return)
TotalReturns = sum(TotalReturns)
Positive_trades=length(data_frame$Return[data_frame$Return>0])
Negative_trades=length(data_frame$Return[data_frame$Return<0])
no_of_trades=Positive_trades + Negative_trades

Metrics = c("Positive trades","Negative trades","No.of Trades","Total Return")
Values = c(Positive_trades,Negative_trades,no_of_trades,paste(round(TotalReturns,digits=4),"%",sep=""))
tsummary = data.frame(Metrics,Values)
tsummary
}

The first 36 lines of the calculation output is shown below and that looks to be in line with the formulas corresponding to the trading strategy.















The result of running the code is shown below and compares well with the results seen on the same strategy in Excel.