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
}