2

I am having trouble backtesting a Bollinger Band strategy in R. The logic is that I want to take a short position if the Close is greater than the Upper Band and then close the position out when it crosses the Average. I also want to take a Long position if the Close is lower than the Lower Band, and Close the position when it crosses the Average. So far this is what I have:

bbands <- BBands(stock$Close, n=20,sd=2)

sig1 <- Lag(ifelse((stock$Close >bbands$up),-1,0))

sig2 <- Lag(ifelse((stock$Close <bbands$dn),1,0))

sig3 <- Lag(ifelse((stock$Close > bbands$mavg),1,-1))

sig <- sig1 + sig2

... This is where i am stuck, how do i use sig3 to get the desired results?

jball
  • 24,791
  • 9
  • 70
  • 92
Jason
  • 311
  • 1
  • 4
  • 14

1 Answers1

7
library(quantmod)

getSymbols("SPY", src="yahoo", from="2013-01-01", to="2013-08-01")
x <- na.omit(merge(SPY, BBands(Cl(SPY))))

x$sig <- NA

# Flat where Close crossed the mavg
x$sig[c(FALSE, diff(sign(Cl(x) - x$mavg), na.pad=FALSE) != 0)] <- 0
x$sig[Cl(x) > x$up] <- -1 # short when Close is above up
x$sig[Cl(x) < x$dn] <- 1 # long when Close is below dn
x$sig[1] <- 0 # flat on the first day
x$sig[nrow(x)] <- 0 # flat on the last day

# Fill in the signal for other times
x$sig <- na.locf(x$sig) # wherever sig is NA, copy previous value to next row

# Now Lag your signal to reflect that you can't trade on the same bar that 
# your signal fires
x$sig <- Lag(x$sig)
x$sig[1] <- 0 # replace NA with zero position on first row

Now, sig is your position. If you have your position, you can calculate other things like number of trades, PnL, etc.

sum(abs(diff(x$sig, na.pad=FALSE))) # number of trades

sum(diff(Cl(x)) * x$sig, na.rm=TRUE) # PnL of 1 share
cumsum(diff(Cl(x), na.pad=FALSE) * x$sig[-1]) # equity over time

sum(ROC(Cl(x)) * x$sig, na.rm=TRUE) # Return of fully invested account
cumsum(ROC(Cl(x), na.pad=FALSE) * x$sig[-1]) # cumulative return
GSee
  • 48,880
  • 13
  • 125
  • 145
  • @ GSee when i was running this on a Pair Trading Spread the `#number of trades` , `#PnL of 1 Share`, `#equity over time`, & `#cumulative return` come back as `NA` values, could it be that it is because in some points the spread is negative? – Jason Aug 21 '13 at 01:16
  • @user2634864 It's more likely that there is an NA somewhere; if any values are NA, then multiplying or adding a number to it will also result in NA – GSee Aug 21 '13 at 01:19