R trading strategy backtesting for loop

1.2k Views Asked by At

Folks, I am just getting started with learning how to properly build backtesting code for trading strategies in R. As my first example I am testing a very simple strategy where one goes long an index when it's closing price on day t is greater than the 50 day moving average. Any long position is sold when closing pricing falls below the 50 day average...however the strategy never gets short outright, only long or flat.

So, to test this properly, I have coded a bulky for loop with nested if/else if statements which is below. This does not run very fast, and I am wondering if there are any general methods of improving speed. R is supposed to be vectorized...but I cannot seem to run the code as such.

In have a data frame as below called "datasort"...and want to add columns for "signal" and "position" on each day. So I for loop using a time index i for each day filling the columns "signal" and "position" as each day passes. Position vector can only take on the value 0 or 1, and and signal can only take value of -1,0,1. Basic issue is that on any day, the signal vector value depends on the previous day position t-1...which makes it impossible to vectorize the operation, or am I incorrect in that thought?

I would appreciate any advice. Also, I am aware that quantmod and quantstrat packages include some backtesting functionality...I simply would like to build it out myself as eventually my signals will become too complicated for these packages to handle. Thank you.

Date        CO2    MA
2006-01-03 61.70 57.88
2006-01-04 62.02 57.95
2006-01-05 61.35 57.96
2006-01-06 62.91 58.03
2006-01-09 62.32 58.09
2006-01-10 62.30 58.14


for(i in 1:length(datasort$CO2)) {
if (i==1) {
  if(datasort$CO2>=datasort$MA) {
    datasort$signal[i]<-1
    datasort$position[i]<-1}
  else if (datasort$CO2[i]<datasort$MA[i]){
    datasort$signal[i]<-0
    datasort$position[i]<-0}}
else if (i>1){
  if ((datasort$CO2[i]>=datasort$MA[i])&(datasort$position[i-1]==0))
  {datasort$signal[i]<-1
   datasort$position[i]<-1}
     else if ((datasort$CO2[i]>=datasort$MA[i])&(datasort$position[i-1]==1))
  {datasort$signal[i]<-0
   datasort$position[i]<-datasort$position[i-1]}
  else if ((datasort$CO2[i]<datasort$MA[i])&(datasort$position[i-1]==1))
  {datasort$signal[i]<- -1
   datasort$position[i]<-datasort$position[i-1]-1}
  else if ((datasort$CO2[i]<datasort$MA[i])&(datasort$position[i-1]==0))
  {datasort$signal[i]<-0
   datasort$position[i]<-datasort$position[i-1]}
}}  
1

There are 1 best solutions below

1
On

It seems that your code cannot be vectorized... But it can be simplified a lot, so please double check it. As currently posed, it is equivalent to this simple function:

f <- function(x, y){
  z <- x >= y
  position <- signal <- as.numeric(z[1])
  for(i in 2:length(z)){
    signal[i] <- z[i] - position[i-1]
    position[i] <- z[i] * position[i-1]
  }
  data.frame(signal=signal, position=position)
}

To test it, use this:

datasort <- read.table(header=TRUE,text="
Date        CO2    MA
2006-01-03 61.70 57.88
2006-01-04 62.02 57.95
2006-01-05 61.35 57.96
2006-01-06 62.91 58.03
2006-01-09 62.32 58.09
2006-01-10 62.30 58.14
")

cbind(datasort, with(datasort, f(CO2, MA)))