看着EMA的C源代码显示第一个值是平均窗口的平均值:
/* Raw mean to start EMA */
double seed = 0.0;
for(i = first; i < first + i_n; i++) {
d_result[i] = NA_REAL;
seed += d_x[i] / i_n;
}
d_result[first + i_n - 1] = seed;
这可以很容易地计算出来以替换 NA :
x = c(14.24, 13.82, 12.75, 12.92, 12.94, 13.00, 14.14, 16.28, 20.64, 17.64)
EMA2 <- function(x,n) {
y = TTR::EMA(x, n)
noNA <- which.min(is.na(x))
y[noNA:(noNA+n-2)] <- cumsum(x[noNA:(noNA+n-2)])/1:(n-1)
y
}
EMA2(x,5)
#> [1] 14.24000 14.03000 13.60333 13.43250 13.33400 13.22267 13.52844 14.44563
#> [9] 16.51042 16.88695
这也适用于领先的 NA:
x = c(NA, NA, 14.24, 13.82, 12.75, 12.92, 12.94, 13.00, 14.14, 16.28, 20.64, 17.64)
EMA2(x,5)
#> [1] NA NA 14.24000 14.03000 13.60333 13.43250 13.33400 13.22267 13.52844 14.44563
#> [11] 16.51042 16.88695
这个短向量的计算开销是最小的,对于较长的向量来说应该更好:
microbenchmark::microbenchmark(TTR::EMA(x,5),EMA2(x,5),times=1000)
#> Unit: microseconds
#> expr min lq mean median uq max neval cld
#> TTR::EMA(x, 5) 157.7 161.8 181.6156 164.0 180.55 593.5 1000 a
#> EMA2(x, 5) 164.2 167.5 193.0643 170.6 193.20 857.1 1000 b