Friday 12 May 2017

Addition of Graph to Backtesting in R

After the first post on backtesting a trading strategy in Excel, we followed it up by another post that added a graph in Excel to make it more meaningful. Later, we replicated this trading strategy in R. In this post, we will add a graph showing SMA and LMA versus time in R like we had done in the case of Excel.

We will add a line to the earlier function that we wrote in the last post. This line will return the dataframe that is calculated by the function. We need this data frame as this data frame contains the SMA and LMA values that are needed for plotting the graph in R. The line is 
return(data_frame) added just before the close of the function as shown in bold 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
return(data_frame)
}

After the above function has been modified and run, the following command is run to fetch the values of the calculation into a data frame.

data_frame <- MovingAverageStrategy("D:\\blog\\apple_data.csv",5,20,2)

Note that the first column containing dates. But, R may not recognize it as being of type Date. So, let us cast it using below command, else, we might end up an absurd graph otherwise. We use below command:

data_frame[,1] = as.Date(data_frame[,1],format='%d-%b-%y')

Once, this is run, we are ready to run the first draft of the graph using below command:

plot(data_frame[,1],data_frame[,7],col="dodgerblue", type="l",main="SMA & LMA versus Date",xlab="Date",ylab="SMA & LMA",lwd=2)

plot is used draw a graph. The argument, data_frame[,1], is Date column and values lie on the x-axis. data_frame[,7] argument contains the calculated SMA values and are the values on the y-axis. col parameter is set to color "dodgerblue". type is set to "l" so that a line is plotted. main parameter used is set to the title of the graph and is assigned a value, "SMA & LMA versus Date". xlab and ylab parameters are used to the titles for the x-axis and y-axis and are set to "Date" and "SMA & LMA", respectively. Lastly, lwd is line width and default value is 1. To make the line appear bold, the value of lwd is set to 2. Once above command is run, the following plot is seen:














To add LMA, we run below command:

lines(data_frame[,1],data_frame[,8],col="darkorange2",lwd=2)

The arguments are self-explanatory. We get the LMA line on the plot as shown below:














Once LMA is added, we just need to add the legend as shown by the command below:

legend("topleft",legend=c("SMA","LMA"),col=c("dodgerblue","darkorange2"),bg="white",lwd=2,cex=0.60)

The argument "topleft" specifies the position of the legend on the plot. The legend argument specifies the text and col specifies the color corresponding to the text. bg specifies the background color of the legend. lwd, like before specifies the line width and cex specifies the level of magnification of the legend of the text and symbols and is set to 0.60. The final plot is shown below:















The plot is identical to the one shown in the case of excel. With this comparison of graphs, we come to the end of this post.