0

I get some warnings when running my quantstrat code, for example one of them is: Warning messages: 1: In match.names(columns, colnames(data)) : all columns not located in Close SMA50 for AGG.Open AGG.High AGG.Low AGG.Close AGG.Volume AGG.Adjusted AGG.Rank SMA.SMA50 Cl.gt.SMA50

My code is:

library(quantstrat)
library(PerformanceAnalytics)

Sys.setenv(TZ="UTC")

currency("USD")
symbols <- c("XLY", "XLP", "XLE", "AGG", "IVV")
stock(symbols, currency="USD")

# get data for the symbols
getSymbols(symbols, from="2005-01-01", to="2012-12-31")

# create an xts object of monthly adjusted close prices
symbols.close <- monthlyPrices(symbols)

# create an xts object of the symbol ranks
sym.rank <- applyRank(x=symbols.close, rankFun=ave3ROC, n=c(2, 4, 6))


# this is an important step in naming the columns, e.g. XLY.Rank
# the "Rank" column is used as the trade signal (similar to an indicator)
# in the qstratRank function
colnames(sym.rank) <- gsub(".Close", ".Rank", colnames(sym.rank))

# ensure the order of order symbols is equal to the order of columns 
# in symbols.close
stopifnot(all.equal(gsub(".Close", "", colnames(symbols.close)), symbols))

# bind the rank column to the appropriate symbol market data
# loop through symbols, convert the data to monthly and cbind the data
# to the rank
for(i in 1:length(symbols)) {
  x <- get(symbols[i])
  x <- to.weekly(x,indexAt='lastof',drop.time=TRUE)
  indexFormat(x) <- '%Y-%m-%d'
  colnames(x) <- gsub("x",symbols[i],colnames(x))
  x <- cbind(x, sym.rank[,i])
  assign(symbols[i],x)
}

bt <- qstratRank(symbols=symbols, init.equity=100000, top.N=1,
                 max.size=1000, max.levels=1)

And qstratRank function is:

qstratRank <- function(symbols, init.equity=100000, top.N=1, 
                       max.size=1000, max.levels=1) {
  # The qstratRank function uses the quantstrat framework to backtest a
  # ranking or relative strength strategy
  #
  # args
  # symbols     : character vector of symbols
  # init.equity : initial equity
  # top.N       : trade the top N ranked assets
  # max.size    : maximum position size
  # max.levels  : maximum levels to scale in a trade
  # max.size and max.levels are passed to addPosLimit
  #
  # return value
  # returns a list: end.eq, returns, book, stats

  # remove variables
  suppressWarnings(rm("order_book.Rank", pos=.strategy))
  suppressWarnings(rm("account.Rank", "portfolio.Rank", pos=.blotter))
  suppressWarnings(rm("account.st", "port.st", "stock.str", "stratRank",
                      "initDate", "initEq", 'start_t', 'end_t'))


  # set initial variables
  initDate <- "1900-01-01"
  initEq <- init.equity
  port.st <- "Rank"
  account.st <- "Rank"

  # trade the top "N" ranked symbols
  N <- top.N

  # initialize quantstrat objects
  initPortf(port.st, symbols=symbols, initDate=initDate)
  initAcct(account.st, portfolios=port.st, initDate=initDate,initEq=initEq)
  initOrders(portfolio=port.st, initDate=initDate)

  # initialize a strategy object
  stratRank <- strategy("Rank")

  # there are two signals
  # the first signal is when Rank is less than or equal to N
  # (i.e. trades the #1 ranked symbol if N=1)

  stratRank <- add.indicator(strategy=stratRank, name="SMA", 
                         arguments=list(x = quote(Cl(mktdata)), n=50), label="SMA50")

  stratRank <- add.signal(stratRank, name="sigComparison", 
           arguments=list(columns=c("Close", "SMA50"), relationship="gt"), label="Cl.gt.SMA50")

  stratRank <- add.signal(stratRank, name="sigComparison", 
                          arguments=list(columns=c("Close", "SMA50"), relationship="lt"), label="Cl.lt.SMA50")

  stratRank <- add.signal(strategy=stratRank, name="sigThreshold", 
                          arguments=list(threshold=N, column="Rank", 
                                         relationship="lte", cross=FALSE), 
                          label="Rank.lte.N")

  # the second signal is when Rank is greter than or equal to N
  # (i.e. trades the #1 ranked symbol if N=1)
  stratRank <- add.signal(strategy=stratRank, name="sigThreshold", 
                          arguments=list(threshold=N, column="Rank", 
                                         relationship="gt", cross=FALSE), 
                          label="Rank.gt.N")



  # add buy rule
  stratRank <- add.rule(strategy=stratRank, name='ruleSignal', 
                        arguments = list(sigcol="Cl.lt.SMA50", sigval=TRUE, 
                                         orderqty=max.size, ordertype='market', 
                                         orderside='long', pricemethod='market', 
                                         replace=FALSE, osFUN=osMaxPos), 
                        type='enter', path.dep=TRUE)



  stratRank <- add.rule(strategy=stratRank, name='ruleSignal', 
                        arguments = list(sigcol="Rank.lte.N", sigval=TRUE, 
                                         orderqty=max.size, ordertype='market', 
                                         orderside='long', pricemethod='market', 
                                         replace=FALSE, osFUN=osMaxPos), 
                        type='enter', path.dep=TRUE)

  # add exit rule
#   stratRank <- add.rule(strategy=stratRank, name='ruleSignal', 
#                         arguments = list(sigcol="Cl.lt.SMA50", sigval=TRUE, 
#                                          orderqty="all", ordertype='market', 
#                                          orderside='long', pricemethod='market', 
#                                          replace=FALSE, osFUN=osMaxPos), 
#                         type='exit', path.dep=TRUE)
#   

  stratRank <- add.rule(strategy = stratRank, name='ruleSignal', 
                        arguments = list(sigcol="Rank.gt.N", sigval=TRUE, 
                                         orderqty='all', ordertype='market', 
                                         orderside='long', pricemethod='market', 
                                         replace=FALSE), 
                        type='exit', path.dep=TRUE)

  #set max position size and levels
  for(symbol in symbols){ addPosLimit(port.st, symbol, initDate, max.size, max.levels) }

  print("setup completed")

  # apply the strategy to the portfolio
  start_t <- Sys.time()
  out <- try(applyStrategy(strategy=stratRank, portfolios=port.st))
  end_t <- Sys.time()
  print(end_t-start_t)

  # update Portfolio
  start_t <- Sys.time()
  updatePortf(Portfolio=port.st, Dates=paste('::', as.Date(Sys.time()), sep=''))
  end_t <- Sys.time()
  print("trade blotter portfolio update:")
  print(end_t - start_t)

  # update account
  updateAcct(account.st)

  # update ending equity
  updateEndEq(account.st)

  # get ending equity
  eq <- getEndEq(account.st, Sys.Date()) + initEq

  # view order book to confirm trades
  order.book <- getOrderBook(port.st)

  # get trade statistics
  stats <- tradeStats(port.st)

  # portfolio returns
  ret1 <- PortfReturns(port.st)
  ret1$total <- rowSums(ret1, na.rm=TRUE)

  return(list(end.eq=eq, returns=ret1, book=order.book, stats=stats))
}

And the functions I use are:

##### monthlyAd function #####
monthlyAd <- function(x){
  # Converts daily data to monthly and returns only the monthly close 
  # Note: only used with Yahoo Finance data so far
  # Thanks to Joshua Ulrich for the Monthly Ad function
  # 
  # args:
  #   x = daily price data from Yahoo Finance
  #
  # Returns:
  #   xts object with the monthly adjusted close prices

  sym <- sub("\\..*$", "", names(x)[1])
  Cl(to.weekly(x, indexAt = 'lastof', drop.time = TRUE, name = sym))
}

##### monthlyReturns function #####
monthlyReturns <- function(symbols) {
  # The function takes a character vector of symbols loaded into
  # the environment and returns an xts object of simple returns
  # Currently this is only for prepping monthly data

  # symbols : character vector of symbols

  ROC(x = monthlyPrices(symbols), n = 1, type = "discrete", na.pad = TRUE)
}

##### monthlyPrices function #####
monthlyPrices <- function(symbols) {
  # The function takes a character vector of symbols loaded into
  # the environment and returns an xts object of Adjusted close prices
  # Currently this is only for prepping monthly data

  # symbols         : character vector of symbols
  # list.sym        : list of symbols with market data

  list.sym <- list()
  for(i in 1:length(symbols)) {
    list.sym[[symbols[i]]] <- get(symbols[i])
  }

  do.call(merge, lapply(list.sym, monthlyAd))
}

# Functions for ways to rank assets based on rate of change
# TODO - add functions to rank based on other factors

# The functions defined below depend on functions in the xts and TTR packages
# library(TTR)

##### applyRank #####
applyRank <- function(x, rankFun, ...) {
  # symbols : character vector of symbols
  # rankFun : function that returns the rank
  # rankFun should be ave3ROC, weightAve3ROC, strengthROC, strengthAve3ROC,
  # etfReplayRank, or strengthSMA.
  # x       : xts object of prices
  # ...     : arguments to rankFun

  FUN <- match.fun(rankFun)
  FUN(x, ...)
}

##### symbolRank #####
symbolRank <- function(symbols, rank.obj) {
  # loop through symbols
  # convert the market data to monthly periodicity 
  # cbind the appropriate column from rank.obj to the market data
  # makes the assumption that the order symbols and rank.obj are equal

  # symbols  : character vector of symbols
  # rank.obj : xts object of ranks of each symbol

  for(i in 1:length(symbols)) {
    x <- get(symbols[i])
    x <- to.monthly(x,indexAt='lastof',drop.time=TRUE)
    indexFormat(x) <- '%Y-%m-%d'
    colnames(x) <- gsub("x", symbols[i], colnames(x))
    x <- cbind(x, rank.obj[,i])
    assign(symbols[i],x)
  }
}

##### rowRank #####
rowRank <- function(x){
  # Computes the rank of an xts object of ranking factors
  # ranking factors are the factors that are ranked (i.e. asset returns)
  #
  #  x : xts object of ranking factors
  #
  #   Returns an xts object with ranks
  #   For ranking asset returns, the asset with the greatest return
  #   receives a  rank of 1

  as.xts(t(apply(-x, 1, rank, na.last = "keep")))
}

#Use the supplied TTR::ROC function for a straight ROC computation

##### ave3ROC #####
ave3ROC <- function(x, n=c(1, 3, 6)){
  # Computes the average rate of change based on averaging 3 periods
  #
  #  x   : xts object of prices
  #  n   : vector of periods to use n = (period1, period2, period3)
  #  ave : xts object of asset rate of change by averaging 3 periods

  roc1 <- ROC(x, n = n[1], type = "discrete")
  roc2 <- ROC(x, n = n[2], type = "discrete")
  roc3 <- ROC(x, n = n[3], type = "discrete")
  ave <- (roc1 + roc2 + roc3)/3
  rowRank(ave)
}

So the problem seems to be in SMA, any ideas? Best Regards

user1665355
  • 3,324
  • 8
  • 44
  • 84

1 Answers1

3

I just faced that problem. The error is not in the SMA function, I believe it's related to your column names (see the label parameter of add.indicator and the column parameter of add.signal) in your indicators and signals. Try debugging the error after your add.indicator and add.signal lines in your qstratRank function by using, temp <- applyIndicators(strategy = stratRank, mktdata = XLY) and then applySignals(strategy = stratRank, mktdata = temp). The error should be there. I fixed it by changing the label parameter of my add.indicator calls. I don't know what are the column names of your indicator, but it looks like it's because of arguments=list(columns=c("Close", "SMA50") in your signals.