xts icon indicating copy to clipboard operation
xts copied to clipboard

a bug in plot.xts() and a possible solution / feature request

Open cloudcell opened this issue 9 years ago • 2 comments

This code was extracted (with minor modifications/additions) from quantstrat::chart.forward.training and based on the data supplied with demo(luxor.sample.walk.forward), using R 3.2.2 on Windows 7.

require(devtools) # version 1.9.1
install_github("joshuaulrich/xts") # as of 2015 November 07
require(quantstrat) # version 0.9.1687
audit.filename <- (paste0(path.package("quantstrat"),"/data/luxor.wfa.ples.RData"))

.audit <- NULL
load(audit.filename)
portfolios.st = ls(name = .audit, pattern = "portfolio.*")
n <- length(portfolios.st)
PL.xts <- xts()
for (portfolio.st in portfolios.st) {
  p <- getPortfolio(portfolio.st, envir = .audit)
  from <- index(p$summary[2])
  R <- cumsum(p$summary[paste(from, "/", sep = ""), "Net.Trading.PL"])
  names(R) <- portfolio.st
  PL.xts <- cbind(PL.xts, R)
}
chosen.one <- .audit$param.combo.nr
chosen.portfolio.st = ls(name = .audit, pattern = glob2rx(paste("portfolio",
                                                                "*", chosen.one, sep = ".")))
R <- PL.xts[, chosen.portfolio.st]
PL.xts <- cbind(PL.xts, R)
PL.xts <- na.locf(PL.xts)
CumMax <- cummax(PL.xts)
Drawdowns.xts <- -(CumMax - PL.xts)
data.to.plot <- as.xts(cbind(PL.xts, Drawdowns.xts))

# DEMONSTRATION OF THE BUG:
# Clears each panel before drawing, so instead of 32 lines, there are only 2
plot.xts(data.to.plot,multi.panel=2,main='Walk Forward Analysis',
        col = c(rep("grey", n), "blue"))

# FEATURE SUGGESTION AS A POSSIBLE SOLUTION:
# Vectorized panel plot ordering would be nice (seems it's not currently implemented)
on_ = c(rep(1,n+1),rep(2,n+1))
plot.xts(data.to.plot,multi.panel=2,main='Walk Forward Analysis',
         col = c(rep("grey", n), "blue"), on=on_)

cloudcell avatar Nov 08 '15 02:11 cloudcell

cloudcello, thank you for the reproducible example. From the ?plot.xts and the multi.panel argument, For example, if multi.panel = 2, then the data will be plotted in groups of 2 columns and each group is plotted in a separate panel. In your example, calling plot.xts with multi.panel=2 is actually creating 15 plot windows with 2 panels in each window. Also explained in the documentation, on is not an argument for plot.xts, it is an argument for lines.xts and points.xts.

This should produce the plot you are looking for

plot(PL.xts, col=c("blue", rep("grey", n-1)), main="Walk Forward Analysis")
# set on=NA so it is drawn on a new panel
lines(Drawdowns.xts, col=c("blue", rep("grey", n-1)), on=NA, main="Drawdowns")

I think we may have a bug with multi.panel behavior that I need to explore further.

rossb34 avatar Nov 08 '15 15:11 rossb34

Thank you for the solution, Ross. I definitely missed that option ("on=NA") while reading help. Also, I'm glad this has been helpful. Just one more comment: I think the code must nevertheless be as follows (as the total number of lines drawn is not n, but rather n+1:

plot(PL.xts, col=c("blue", rep("grey", n)), main="Walk Forward Analysis")
# set on=NA so it is drawn on a new panel
lines(Drawdowns.xts, col=c("blue", rep("grey", n)), on=NA, main="Drawdowns")

cloudcell avatar Nov 08 '15 16:11 cloudcell