joshuaulrich / TTR

Technical analysis and other functions to construct technical trading rules with R
GNU General Public License v2.0
326 stars 102 forks source link

TTR::EMA and TTR::DEMA Profiling #69

Closed ckatsulis closed 5 years ago

ckatsulis commented 6 years ago

On a quick trial of supplying data to TTR as an xts object and then as coredata and recasting as xts, I was able to achieve performance improvements on the order of 60%. Are you able to explain why this is the case, or could you potential modify the call so that it does this naturally?

> dim(testData)
[1] 5783631       1

Pass as coredata and recast as xts with .xts and .index:

.xts(TTR::DEMA(coredata(testData)),.index(testData))

1220ms image

Pass as original xts object:

profvis::profvis(TTR::DEMA(testData))

2760ms image

joshuaulrich commented 6 years ago

Thanks for the report! The xts-input version is slower because the reclass() call in EMA() converts the result of .Call("ema", x, n, ratio) from a vector to a xts object (a matrix, with a dim attribute). That causes column names to be added, which creates copies of intermediate objects and causes the slowness.

One potential solution is to create a dema C function that calls the ema C function. That would require adding try.xts() and reclass() to DEMA(), since it would no longer get those automatically from EMA().

joshuaulrich commented 6 years ago

@ckatsulis The changes on this branch help close the performance gap in my tests. There's also an xts performance branch that contains some other relevant changes to help make this a bit faster.

The DEMA(x) call is still slower because the try.xts() and reclass() calls cause more temporary copies of objects, which usually means more garbage collections.

I would really appreciate if you could update both packages and provide feedback!

Here's the data and tests I was running:

require(xts)
require(TTR)
require(microbenchmark)
x <- .xts(rnorm(1e7), 1:1e7)

xts.dema <- function(x) {
  .xts(DEMA(coredata(x)), .index(x))
}
ttr.dema <- function(x) {
  DEMA(x)
}

Rprof(); o1 <- xts.dema(x); Rprof(NULL); summaryRprof()
Rprof(); o2 <- ttr.dema(x); Rprof(NULL); summaryRprof()
all.equal(drop(coredata(o1)), drop(coredata(o2)))

microbenchmark(xts.dema(x), ttr.dema(x), times = 5)
# Unit: milliseconds
#         expr      min       lq     mean   median       uq      max neval cld
#  xts.dema(x) 386.1508 413.3212 416.1767 425.5015 426.4050 429.5053     5  a 
#  ttr.dema(x) 456.2319 487.6094 493.3008 495.4675 509.4217 517.7736     5   b
ckatsulis commented 5 years ago

Thanks for the update!

On Mon, Sep 17, 2018 at 12:28 PM Joshua Ulrich notifications@github.com wrote:

Closed #69 https://github.com/joshuaulrich/TTR/issues/69 via 25aaf31 https://github.com/joshuaulrich/TTR/commit/25aaf31abd548087476f52c0933cb52dbdbb56bc .

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/joshuaulrich/TTR/issues/69#event-1850371026, or mute the thread https://github.com/notifications/unsubscribe-auth/AHKwqhwmrL8zGR0AiGpl_FiAaHhgkKj6ks5ub9u3gaJpZM4UyKjG .