stock market, charts, graphs-2616931.jpg

backtesting Engine system state

Our backtesting engine needs to know the state of the system at each step of the iteration through the data set. This can be accomplished by writing a function to calculate the system state based on:

  • Buy or sell entry signals generated from our code in a previous step
  • Buy or sell exit signals generated previously in our code
  • System state variables calculated concurrently to indicate previous states of the trading system
    • Long or short
    • Time constraints such as holding overnight

We start by instantiating a function that accepts 4 vectors. In this case the vectors are integers consisting of zeros and ones that represent buy/sell entry signals or buy/sell exit signals generated previously the code.

getBarAction <- function(buySig, exitBuySig, sellSig, exitSellSig)

Here is the full function code in its entirety.

getBarAction <- function(buySig, exitBuySig, sellSig, exitSellSig) {
 n <- length(buySig)
 output <- vector("integer", n) #Create output vector length of data frame
 stateV <- vector("integer", n) #Create system state vector length of data frame
 state           <- 0 #Init current sys state to zero = no trade, 1 = long, -1 = short
 prevBuySig      <- 0
 prevExitBuySig  <- 0
 prevSellSig     <- 0
 prevExitSellSig <- 0
 
 for (i in seq_along(buySig)) {
   # if (i==70)
   # browser()
   if (state == 0) { #If sys is flat check for change in signal
     # sigBuyDelta <- buySig[[i]] - prevBuySig             !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     sigBuyDelta <- buySig[[i]]
     # sigSellDelta <- sellSig[[i]] - prevSellSig             !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     sigSellDelta <- sellSig[[i]]
     if (sigBuyDelta != 0) {#Enter Long Trigger
       output[[i]] <- 1
       stateV[[i]] <- 1
       state <- 1
     } else if (sigSellDelta != 0) {#Enter Short Trigger
       output[[i]] <- -1
       stateV[[i]] <- -1
       state <- -1
     } else {#No trigger
       output[[i]] <- 0
       stateV[[i]] <- 0
     }
   } else if (state == 1) { #If sys is long check for exit conditions
     # exitBuySigDelta <- exitBuySig[[i]] - prevExitBuySig             !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     exitBuySigDelta <- exitBuySig[[i]]
     if (exitBuySigDelta != 0) {#Exit Long Trigger
       output[[i]] <- 3
       stateV[[i]] <- 0
       state <- 0
     } else {#Keep Long Trade
       output[[i]] <- 2
       stateV[[i]] <- 1
     }
   } else if (state == -1) {#If sys is short check for exit conditions
     # exitSellSigDelta <- exitSellSig[[i]] - prevExitSellSig             !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     exitSellSigDelta <- exitSellSig[[i]]
     if (exitSellSigDelta != 0) {#Exit Short Trigger
       output[[i]] <- -3
       stateV[[i]] <- 0
       state <- 0
     } else {#Keep Short Trade
       output[[i]] <- -2
       stateV[[i]] <- -1
     }
   }
   
   if (i == n) {#If last row of data frame need to close open trades
     if (prevBuySig == 1) {#Next to last row entered new long
       output[[i]] <- 3 #Exit long
     } else if (prevSellSig == 1) {#Next to last row entered new short
       output[[i]] <- -3 #Exit short
     } else if (abs(output[[i]]) == 1) {#If last row is new long/short
       output[[i]] <- 0 #No new trade entered on last row
     } else if (abs(output[[i]]) == 2) {#If last row is still long/short
       output[[i]] <- state * 3 #Exit long or short
     } else { #Natural exit or no trade
       output[[i]] <- output[[i]]
     }
   }
   
   prevBuySig <- buySig[[i]] #Update last signal state to carry to next iteration
   prevSellSig <- sellSig[[i]]
 }
 
 return(cbind(output, stateV)) #Function returns output and sys state vectors
 }