braverock / PerformanceAnalytics

211 stars 105 forks source link

Speed up Return.annualized #170

Open klin333 opened 2 years ago

klin333 commented 2 years ago

Description

Return.annualized seems to be unnecessarily slow. Seems a simple code tweak (1 line change) can speed it up by 100x? Am I missing something? I'm new to this package.

Minimal, reproducible example


library(xts)
library(PerformanceAnalytics)

# tweaked 1 line from PerformanceAnalytics::Return.annualized
tweaked <- function (R, scale = NA, geometric = TRUE) 
{
  if (!xtsible(R) & is.na(scale)) 
    stop("'R' needs to be timeBased or xtsible, or scale must be specified.")
  if (is.na(scale)) {
    freq = periodicity(R)
    switch(freq$scale, minute = {
      stop("Data periodicity too high")
    }, hourly = {
      stop("Data periodicity too high")
    }, daily = {
      scale = 252
    }, weekly = {
      scale = 52
    }, monthly = {
      scale = 12
    }, quarterly = {
      scale = 4
    }, yearly = {
      scale = 1
    })
  }
  if (is.vector(R)) {
    R = checkData(R)
    R = na.omit(R)
    n = length(R)
    if (geometric) {
      result = prod(1 + R)^(scale/n) - 1
    }
    else {
      result = mean(R) * scale
    }
    result
  }
  else {
    R = checkData(R, method = "xts")
    result = apply(zoo::coredata(R), 2, Return.annualized, scale = scale,  # tweaked here: R -> zoo::coredata(R)
                   geometric = geometric)
    dim(result) = c(1, NCOL(R))
    colnames(result) = colnames(R)
    rownames(result) = "Annualized Return"
    return(result)
  }
}

dates <- seq(as.Date('2010-01-01'), as.Date('2020-12-31'), by = 1)
returns <- rep(0.01, length(dates))
ts <- xts::xts(returns, order.by = dates)
microbenchmark::microbenchmark(times = 10, unit = 'ms', Return.annualized(ts), tweaked(ts))

# Unit: milliseconds
#                  expr        min         lq       mean     median       uq        max neval
# Return.annualized(ts) 345.446601 352.530002 368.548451 364.888551 367.3592 423.677401    10
#           tweaked(ts)   1.390701   1.460401   1.616781   1.552252   1.7372   1.956401    10

print(Return.annualized(ts))
#                   [,1]
# Annualized Return 11.274

print(tweaked(ts))
#                   [,1]
# Annualized Return 11.274

R version 3.6.3 (2020-02-29) Platform: x86_64-w64-mingw32/x64 (64-bit) Running under: Windows 10 x64 (build 19044)

Matrix products: default

locale: [1] LC_COLLATE=English_Australia.1252 LC_CTYPE=English_Australia.1252 LC_MONETARY=English_Australia.1252 LC_NUMERIC=C
[5] LC_TIME=English_Australia.1252

attached base packages: [1] stats graphics grDevices utils methods base

other attached packages: [1] PerformanceAnalytics_2.0.4 xts_0.12-0 zoo_1.8-8

loaded via a namespace (and not attached): [1] microbenchmark_1.4.9 BiocManager_1.30.10 compiler_3.6.3 tools_3.6.3 grid_3.6.3 packrat_0.5.0
[7] renv_0.13.2 lattice_0.20-38 quadprog_1.5-8