One can use TTR:SMA() or TTR::EMA() but these do not allow custom weights. One solution I came up with is using data.table::frollapply:
library(data.table)
x <- data.table(type=rep(1:100, 10000), val=sample(1:1000000, 1000000))
my.roll.2 <- function(x, weights=NULL) {
n <- length(x)
if(is.null(weights)) weights <- 1/(1:n)
sum(weights[1:n]*x, na.rm=T)/sum(weights[1:n])
}
my.roll.1 <- function(x, n, name, ref.col, val.col, weights=NULL) {
x[, (name) := frollapply(get(val.col), n, my.roll.2, weights=weights), by=ref.col]
}
However the performance of my.roll.1 is not great (and it gets exponentially worse compared to the other ones the bigger the input data):
library(microbenchmark)
library(TTR)
n <- 10
name <- 'test'
microbenchmark(
my.roll=my.roll.1(x, n, name, 'type', 'val')
, frollmean=x[, (name):=data.table::frollmean(val, n), type]
, EMA=x[, (name):=TTR::EMA(val, n), type]
, times=10L
)
Results:
Unit: milliseconds
expr min lq mean median uq max neval
my.roll 7661.0278 7666.0732 7698.69693 7693.28025 7708.6880 7778.6171 10
frollmean 17.1724 17.6321 19.54878 19.56485 20.9490 23.5549 10
EMA 43.0090 43.7332 45.92251 45.79210 47.2391 51.9399 10
data.table::frollmean is very fast (implemented in C) but it doesn't use any weights. TTR::EMA uses only the EMA specific weights/smoothing (the only flexibility is to use the parameter wilder=TRUE or wilder=FALSE). My need is to achieve the functionality of my.roll.1 but to be faster.