rquantstratblotterback-testing

Keep getting the "dims do not match the length of object" in quantstrat


I have been modifying a backtest I made a few months ago using quantstrat. It was all working fine until I added in signal and rule 6 (donchian channel low) My full code is below. Any help would be greatly appreciated.

Thanks in advance.

PS: Sorry if the code looks messy, this is my first time asking a question here.

library(blotter)
library(quantstrat)
library(xts)
library(quantmod)
Sys.setenv(TZ="UTC") 

getSymbols('^DJI', from="2016-01-01", to="2016-12-31", index.class="POSIXct", adjust=T)


colnames(DJI)<- c("Open","High","Low","Close","Volume","Adjusted")

currency("AUD") 
Sys.setenv(TZ="UTC") 
initdate <- '2016-01-03' 
startdate <- '2016-01-04' 
enddate <- '2016-12-30'
portfolioname <- "Dow Jones" 
accountname <- "Dow Jones" 
contracts <- 1 
txncost <- -0.79 
margin <- 15000
strategyname <- accountname
startingcapital <- 1e+6
symbollist <- 'DJI'
instrument<-"DJI"


rm.strat(strategyname) 
initPortf(portfolioname,
      symbollist,initDate=initdate,currency="AUD")
initAcct(accountname,portfolios=portfolioname,initDate=initdate,initEq=startingcapital,currency="AUD")
initOrders(portfolio=portfolioname,initDate=initdate)
strategy(strategyname,store=TRUE)
strat <- getStrategy(strategyname)
summary(strat)


osInvestAll <- function (data, timestamp, orderqty, ordertype, orderside, equity, portfolio, symbol, ruletype, ..., orderprice) 
{   
datePos <- format(timestamp,"%Y-%m-%d")

  updatePortf(Portfolio=portfolio,Symbol=symbol,Dates=datePos)
updateAcct(portfolio,Dates=datePos)   
updateEndEq(portfolio,Dates=datePos)     
Posn <- getPosQty(portfolio,Symbol=symbol,Date=datePos)
equity <- getEndEq(portfolio,datePos) 
ClosePrice <- getPrice(get(symbol))[datePos]
#UnitSize <- as.numeric(trunc(equity*0.25/ClosePrice)) 

if (Posn == 0) { 
    osInvestAll <- UnitSize } else
        {osInvestAll <- 0
         }

}

Rule1<-function(price,SMA,...)
{ifelse(price>SMA,1,-1)}
add.indicator(strategy=strategyname,name="SMA",
          arguments=list(x=quote(mktdata$Close),n=40),label="SMA40")

add.indicator(strategyname, name="Rule1", arguments=list(price =     quote(mktdata$Close), SMA=quote(mktdata$SMA.SMA40)), label="Rule1Signal")

Rule2<-function(SMA2,SMA5,...)
{ifelse(SMA5>SMA2,1,-1)}
add.indicator(strategy=strategyname,name="SMA",
          arguments=list(x=quote(mktdata$Close),n=2),label="SMA2")
add.indicator(strategy=strategyname,name="SMA",
          arguments=list(x=quote(mktdata$Close),n=5),label="SMA5")

add.indicator(strategyname, name="Rule2",     arguments=list(SMA5=quote(mktdata$SMA.SMA5), SMA2=quote(mktdata$SMA.SMA2)), label="Rule2Signal")




#Daily range less than the 10 day average range, buy next day if todays close was higher (+1) or short if it was lower 
#HLC <- HLC(DJI)
Rule3<-function(HLC, n)
{ 
   DJI$TR <- ATR(HLC(DJI),10)[,1]    
    DJI$todays <-DJI$High-DJI$Low

Rule3 <- ifelse(DJI$todays>DJI$TR, ifelse((HLC$Close > lag.xts(HLC$Close)), -1,1), ifelse((HLC$Close >       lag.xts(HLC$Close)), 1, -1))

}

    add.indicator(strategyname, name="Rule3", arguments=list(HLC=quote(HLC(mktdata)), n=10), label="Rule3Signal")


##Donchian Channel
#High
Rule4 <- function(H,L,Close)
{ifelse(Close>H,1,0)}

add.indicator(strategy=strategyname,name="DonchianChannel",
          arguments=list(HL=quote(mktdata$Close),n=50),label="DCH")

add.indicator(strategyname, name="Rule4", arguments=list(H=quote(mktdata$high.DCH),L=quote(mktdata$low.DCH),Close=quote(mktdata$Close)), label="Rule4Signal")
#Low
Rule6 <- function(H,L,Close)
{ifelse(Close<L,-1,0)}

add.indicator(strategy=strategyname,name="DonchianChannel",
          arguments=list(HL=quote(mktdata$Close),n=50),label="DCH")

add.indicator(strategyname, name="Rule6", arguments=list(H=quote(mktdata$high.DCH),L=quote(mktdata$low.DCH),Close=quote(mktdata$Close)), label="Rule6Signal")



#Rule 5
Rule5<-function(H15,L15)
{
X<-(H15+L15)/2
ifelse(DJI$Close>X,1,-1)}

    add.indicator(strategy=strategyname,name="SMA",
          arguments=list(x=quote(mktdata$High),n=15),label="H15")
    add.indicator(strategy=strategyname,name="SMA",
          arguments=list(x=quote(mktdata$Low),n=15),label="L15")

    add.indicator(strategyname, name="Rule5", arguments=list(Close=quote(mktdata$Close), H15=quote(mktdata$High),L15=quote(mktdata$Low)), label="Rule5Signal")




RuleSum <- function(R1,R2,R3,R4,R5,R6,...)
{
RuleSum <- ( R1 + R2 + R3 + R4 + R5 + R6 )
}
add.indicator(strategyname, name="RuleSum",     arguments=list(R1=quote(mktdata$Close.Rule1Signal), R2=quote(mktdata$SMA.SMA5.Rule2Signal),R3=quote(mktdata$todays.Rule3Signal),R4=quote(mktdata$Rule4Signal),R5=quote(mktdata$Close.Rule5Signal),R6=quote(mktdata$Close.Rule6Signal)), label="RuleSum")


#Signals
add.signal(strategyname,name="sigThreshold",
       arguments=list(column="Close.Rule1Signal.RuleSum",relationship="gt",threshold=0,cross=FALSE),
  label="signal.gt.zero")


 add.signal(strategyname,name="sigThreshold",
  arguments=list(column="Close.Rule1Signal.RuleSum",relationship="lt",threshold=0,cross=FALSE),
  label="signal.lt.zero")



#Rules
 add.rule(strategyname,name='ruleSignal',
arguments = list(sigcol="signal.gt.zero", sigval=TRUE,
replace=FALSE,
prefer='open',
orderside='long',
ordertype='market',
orderqty=1,
orderset='ocolong'
  ),
  type='enter',
  label='LE'
 )


add.rule(strategyname,name='ruleSignal',
arguments = list(sigcol="signal.gt.zero", sigval=TRUE,
replace=FALSE, 
prefer='close',
orderside='long',
ordertype='market',
orderqty='all',
orderset='ocolong'
  ),
  type='exit',
  label='LX'
)

trailingStopPercent <- .20

 add.rule(strategyname, name = 'ruleSignal',
 arguments=list(sigcol="signal.gt.zero" , sigval=TRUE,
 replace=FALSE,
 prefer='close',
 orderside='long',
 ordertype='stoptrailing',
 tmult=TRUE,
 threshold=quote(trailingStopPercent),
 orderqty='all',
orderset='ocolong'
  ),
type='chain', parent="LE",
label='StopTrailingLong',
enabled=TRUE
 )

###short rules
add.rule(strategyname,name='ruleSignal',
arguments = list(sigcol="signal.lt.zero", sigval=TRUE,
replace=FALSE,
prefer='open',
orderside='short',
ordertype='market',
orderqty=-1,
orderset='ocoshort'
),
type='enter',
label='SE'
)


add.rule(strategyname,name='ruleSignal',
arguments = list(sigcol="signal.lt.zero", sigval=TRUE,
replace=FALSE,  
prefer='close',
orderside='short',
ordertype='market',
orderqty='all',
orderset='ocoshort'
  ),
  type='exit',
  label='SX'
)

trailingStopPercent <- .20

add.rule(strategyname, name = 'ruleSignal',
arguments=list(sigcol="signal.lt.zero" , sigval=TRUE,
replace=FALSE,
prefer='close',
orderside='long',
ordertype='stoptrailing',
tmult=TRUE,
threshold=quote(trailingStopPercent),
orderqty='all',
orderset='ocoshort'
  ),
type='chain', parent="SE",
label='StopTrailingShort',
enabled=TRUE
 )

summary(getStrategy(strategyname))

     applyStrategy(strategy=strategyname,portfolios=portfolioname,verbose=TRUE,update.equity = TRUE, showEq = TRUE) #verbose=FALSE not to print


updatePortf(strategyname)
updateAcct(strategyname)
updateEndEq(strategyname)

Solution

  • If you run traceback() after getting the error, you can quickly identify where the trouble in your code likely lies.

    You haven't correctly specified the column name used in R4 for the RuleSum indicator, which should be R4=quote(mktdata$Close.Rule4Signal).

    Your backtest works once you correct the add.indicator for RuleSum:

    add.indicator(strategyname, name="RuleSum",     arguments=list(R1=quote(mktdata$Close.Rule1Signal), R2=quote(mktdata$SMA.SMA5.Rule2Signal),R3=quote(mktdata$todays.Rule3Signal),R4=quote(mktdata$Close.Rule4Signal),R5=quote(mktdata$Close.Rule5Signal),R6=quote(mktdata$Close.Rule6Signal)), label="RuleSum")
    

    Tip: For debugging purposes, you can test all the indicators work in isolation from the signals and rules by calling

    res <- applyIndicators(strategyname, DJI)
    

    after you have completed all add.indicator's. (And before you add add.signals, and way before you run applyStrategy. If this code works as expected, then you know the problem may either be with the signals or the rules. Then you can test the signals work using applySignals, etc...