【问题标题】:Roll-applying EMA function over two columns in data.table在 data.table 中的两列上滚动应用 EMA 函数
【发布时间】:2021-04-21 11:09:32
【问题描述】:

我的data.table如下

dt <- structure(list(x = c(-0.888888888888886, -0.588235294117648, 
0.630952380952381, 0.0769230769230788, 0.250000000000003, -0.615384615384616, 
0.888888888888891, 0.924528301886792, -0.477326968973745, 0), 
    ema = c(-0.121833534531943, -0.148485063651126, -0.103945781102354, 
    -0.0936104177866151, -0.0739755367702369, -0.104913198405344, 
    -0.0481245077028166, NA, NA, 
    NA)), row.names = c(NA, -10L), class = c("data.table", 
"data.frame"))

看起来像

             x         ema
 1: -0.88888889 -0.121833535
 2: -0.58823529 -0.148485064
 3:  0.63095238 -0.103945781
 4:  0.07692308 -0.093610418
 5:  0.25000000 -0.073975537
 6: -0.61538462 -0.104913198
 7:  0.88888889 -0.048124508
 8:  0.9245283          NA
 9: -0.4773270          NA
10:  0.0000000          NA

在此 data.table 中,x 列是每天更新的连续变量,ema 列是 x 列的 EMA(指数移动平均线)。由于某种原因,过去 3 天我无法更新 x 的 EMA(在列 ema 中),现在我需要使用下面给出的函数 ema_add 更新它 -

ema_add <- function(newx, lasty){
   ratio <- 2 / (34+1)
   lasty * (1 - ratio) + ratio * newx
 }

正如帖子中所建议的 - Rolling a function on two columns in data.table ,我正在使用以下代码来查找最后三个值的 EMA,但它没有给出预期的结果。以下是我得到的结果。

dt$updated_ema = Reduce(ema_add, x = dt$x[-1], init = first(dt$ema), accumulate = T)
dt$updated_ema
[1] -0.12183353 -0.43276804  0.27637891  0.14340835  0.21446945 -0.33876659  0.47967039  0.77624233 -0.05947054 -0.01982351

预期结果是-

             x         ema
 1: -0.88888889 -0.121833535
 2: -0.58823529 -0.148485064
 3:  0.63095238 -0.103945781
 4:  0.07692308 -0.093610418
 5:  0.25000000 -0.073975537
 6: -0.61538462 -0.104913198
 7:  0.88888889 -0.048124508
 8:  0.92452830  0.007455653
 9: -0.47732697 -0.020246211
10:  0.00000000 -0.019089285

在应用上面的Reduce 函数时,有人能发现我做错了什么吗?

提前致谢。

【问题讨论】:

  • 你的代码抛出Error in match.fun(f) : object 'ema_update' not found。如果我将函数名称更正为发布的函数Error in f(init, x[[i]]) : object 'ratio' not found.
  • 感谢您指出。我已经修复了这些错误。
  • 还是没有ratio
  • 变量ratioema_add函数内部定义。

标签: r data.table rolling-computation


【解决方案1】:

我无法真正复制您的值,但包 pracma 包含移动平均功能,应该可以使用:

library(pracma) 
dt[,.(x
  , ema
  , ema_test =  movavg(x, n = 3, type="e")
  )]

指数函数的移动平均函数代码为:

movavg
function (x, n, type = c("s", "t", "w", "m", "e", "r")) 
{
stopifnot(is.numeric(x), is.numeric(n), is.character(type))
if (length(n) != 1 || ceiling(n != floor(n)) || n <= 1) 
    stop("Window length 'n' must be a single integer greater 1.")
nx <- length(x)
if (n >= nx) 
    stop("Window length 'n' must be greater then length of time series.")
y <- numeric(nx)
if (type == "s") {
    for (k in 1:(n - 1)) y[k] <- mean(x[1:k])
    for (k in n:nx) y[k] <- mean(x[(k - n + 1):k])
}
else if (type == "t") {
    n <- ceiling((n + 1)/2)
    s <- movavg(x, n, "s")
    y <- movavg(s, n, "s")
}
else if (type == "w") {
    for (k in 1:(n - 1)) y[k] <- 2 * sum((k:1) * x[k:1])/(k * 
        (k + 1))
    for (k in n:nx) y[k] <- 2 * sum((n:1) * x[k:(k - n + 
        1)])/(n * (n + 1))
}
else if (type == "m") {
    y[1] <- x[1]
    for (k in 2:nx) y[k] <- y[k - 1] + (x[k] - y[k - 1])/n
}
else if (type == "e") {
    a <- 2/(n + 1)
    y[1] <- x[1]
    for (k in 2:nx) y[k] <- a * x[k] + (1 - a) * y[k - 1]
}
else if (type == "r") {
    a <- 1/n
    y[1] <- x[1]
    for (k in 2:nx) y[k] <- a * x[k] + (1 - a) * y[k - 1]
}
else stop("The type must be one of 's', 't', 'w', 'm', 'e', or 'r'.")
return(y)
}

【讨论】:

  • 感谢指点!我不知道这个图书馆。我要解决的问题是 - 我拥有的时间序列有数千个值,并且每天运行这些时间序列时,需要数小时才能执行。我只需要找到每天添加到这些时间序列的新值的 EMA,因此我正在使用自定义函数。
  • 嗯,我认为原因是您的计算与答案的累积总和根本不同,您从中获得了 reduce 函数。也许看看 data.table 的滚动功能。
猜你喜欢
  • 2021-04-21
  • 2017-08-23
  • 2021-04-21
  • 1970-01-01
  • 2022-11-11
  • 2019-10-20
  • 2015-07-08
  • 1970-01-01
  • 2014-02-12
相关资源
最近更新 更多