Quantstrat: how do I create a multi level Bollinger Band Strategy

57 Views Asked by At

I'm trying to create a Bollinger Band Strategy using QuantStrat that uses multiple standard deviations, exiting on a previous level's Bollinger Band or the Moving Average if there are no Bands below the examined Band. To do so, I made this code to create unique entry and exit rules for each level:


initEQ<-10000
MAperiod_input<- 200
stdev_input<-3.5
transaction_cost_input<-0
levels_input<-10
profit_ticks_input<-1

strategy.st <- portfolio.st <- account.st <- "BBands"
stdev_list<-seq(stdev_input/levels_input, stdev_input, by = stdev_input/levels_input)

initPortf(portfolio.st, symbols = c("PairsFinal"))
initAcct(account.st, portfolios = portfolio.st, initEq = initEQ)
initOrders(portfolio.st)

strategy(strategy.st, store = T)

#####
#Loop to create entries and exits for each level of Bollinger Band
for(i in c(1:length(stdev_list))){
  BollbandLabel<-paste0("BollBand",i)
  upperBandCrossLabel<-paste0("upperBandCross",i)
  lowerBandCrossLabel<-paste0("lowerBandCross",i)
  exitBollBandLabel<-paste0("exitBollBand",i)
  upperExitBandCrossLabel<-ifelse(i - profit_ticks_input > 0,  paste0("upperExitBandCross",i), "Cross.mid")
  lowerExitBandCrossLabel<-ifelse(i - profit_ticks_input > 0,  paste0("lowerExitBandCross",i), "Cross.mid")
  exit_stdev<-ifelse(which(stdev_list[i] %in% stdev_list) - profit_ticks_input > 0,  stdev_list[(i - profit_ticks_input)],0)
  
  
  add.indicator(strategy.st, name = strategy.st, arguments = list(HLC = quote(HLC(mktdata)) , n = MAperiod_input, sd =  stdev_list[i]), label = BollbandLabel)
  
  ##Enters
  add.signal(strategy.st, "sigCrossover", arguments = list(columns = c("Cl", paste0("dn.",BollbandLabel)), relationship = "lt"), label = upperBandCrossLabel)
  add.rule(strategy.st, name = "ruleSignal", arguments = list(sigcol = upperBandCrossLabel, orderqty = -100, orderside='short', sigval = T, ordertype = "market", TxnFees = transaction_cost_input),type = 'enter')
  add.signal(strategy.st, "sigCrossover", arguments = list(columns = c("Cl", paste0("up.",BollbandLabel)), relationship = "gt"), label = lowerBandCrossLabel)
  add.rule(strategy.st, name = "ruleSignal", arguments = list(sigcol = lowerBandCrossLabel, orderqty = 100, orderside='long', sigval = T, ordertype = "market", TxnFees = transaction_cost_input),type = 'enter')
  ##Exits
  
  if(upperExitBandCrossLabel != "Cross.mid"){
    add.indicator(strategy.st, name = "BBands", arguments = list(HLC = quote(HLC(mktdata)) , n = MAperiod_input, sd = stdev_list[i - profit_ticks_input]), label = exitBollBandLabel)
    add.signal(strategy.st, "sigCrossover", arguments = list(columns = c("Cl", paste0("up.",exitBollBandLabel)), relationship = "lt"), label = upperExitBandCrossLabel)
    add.rule(strategy.st, name = "ruleSignal", arguments = list(sigcol = upperExitBandCrossLabel, orderqty = 100, orderside='long', sigval = T, ordertype = "market", TxnFees = transaction_cost_input),type = 'exit')
    add.signal(strategy.st, "sigCrossover", arguments = list(columns = c("Cl", paste0("dn.",exitBollBandLabel)), relationship = "gt"), label = lowerExitBandCrossLabel)
    add.rule(strategy.st, name = "ruleSignal", arguments = list(sigcol = lowerExitBandCrossLabel, orderqty = -100, orderside='short', sigval = T, ordertype = "market", TxnFees = transaction_cost_input),type = 'exit')
  }else{
    add.signal(strategy.st, "sigCrossover", arguments = list(columns = c("Cl", "Cross.mid"), relationship = "lt"), label = upperExitBandCrossLabel)
    add.rule(strategy.st, name = "ruleSignal", arguments = list(sigcol = upperExitBandCrossLabel, orderqty = 100, orderside='long', sigval = T, ordertype = "market", TxnFees = transaction_cost_input),type = 'exit')
    add.signal(strategy.st, "sigCrossover", arguments = list(columns = c("Cl", "Cross.mid"), relationship = "gt"), label = lowerExitBandCrossLabel)
    add.rule(strategy.st, name = "ruleSignal", arguments = list(sigcol = lowerExitBandCrossLabel, orderqty = -100, orderside='short', sigval = T, ordertype = "market", TxnFees = transaction_cost_input),type = 'exit')
  }
}

strat<-applyStrategy(strategy.st, portfolio.st, mktdata = OHLC(PairsFinal))
updatePortf(portfolio.st)
strat<-getPortfolio(portfolio.st)$summary
tradeStats(portfolio.st)

However, I only want a single order at each level, and this code seems to be repeating already filled orders. Is there a way to limit each Bollinger Band of this ruleset to a single Open Position until it exits? This is my first time using QuantStrat, so if there's a multi-level function I missed, please let me know.

0

There are 0 best solutions below