1

I have a simple vector as follows:

x = c(14.24, 13.82, 12.75, 12.92, 12.94, 13.00, 14.14, 16.28, 20.64, 17.64)

I have found the EMA of this vector using

library(TTR)
y = EMA(x, 5)

and the result is

[1] NA NA NA NA 13.33400 13.22267 13.52844 14.44563 16.51042 16.88695

The next day a new value is added to the end of original vector x and the updated x vector is:

x = c(14.24, 13.82, 12.75, 12.92, 12.94, 13.00, 14.14, 16.28, 20.64, 17.64, 18.09)

The expected output is -

y = [1] NA NA NA NA 13.33400 13.22267 13.52844 14.44563 16.51042 16.88695 17.28796

This output can be produced by EMA(x, 5), but this statement will calculate EMA of the entire vector again and will be time inefficient. Since we already have the previous day's EMA calculation in vector y, is there a way to calculate the EMA of just the last 5 days instead of recalculating for the entire vector and merge the new value in vector y?

Thanks!

Saurabh
  • 1,566
  • 10
  • 23
  • What do you meant by the last value mean. There is only single element – akrun Jan 14 '21 at 19:25
  • I am still trying to understasnd how you got 18.09 from the `tail(x, 5)` – akrun Jan 14 '21 at 19:53
  • The 18.09 calculation is not clear. I am not getting that value – akrun Jan 14 '21 at 20:01
  • Can you show your expected output as it is not clear to me – akrun Jan 14 '21 at 20:03
  • I checked your update, but it is still the same input 'x' with `18.09`. Not clear what your expected output is – akrun Jan 14 '21 at 20:07
  • If you want to do this only once, wouldn't it be better to calculate EMA at the end of trial – akrun Jan 14 '21 at 20:11
  • What I meant is you don't have to calculate EMA thousand times each day. Calculate it at the end of a day when the 'x' is nolonger updated – akrun Jan 14 '21 at 20:18
  • The ema is calculated with a weight. `The exponential moving average is a weighted moving average that reduces influences by applying more weight to recent data points () reduction factor` – akrun Jan 14 '21 at 20:25
  • If you just subset the last 10 elements and do the EMA, it would be different – akrun Jan 14 '21 at 20:39

2 Answers2

1

If you read ?TTR::EMA,

For 'EMA', 'wilder=FALSE' (the default) uses an exponential smoothing ratio of '2/(n+1)'

It helps to understand that in EMA, this ratio is effectively the weight applied to the current value (x), and the inverse (one minus this) is applied to the previous average (y).

x = c(14.24, 13.82, 12.75, 12.92, 12.94, 13.00, 14.14, 16.28, 20.64, 17.64)
n <- 5
y <- TTR::EMA(x, n)

x = c(14.24, 13.82, 12.75, 12.92, 12.94, 13.00, 14.14, 16.28, 20.64, 17.64, 18.09)
ratio <- 2/(n+1)
ratio
# [1] 0.3333333
sum( c(y[10], x[11]) * c(1-ratio, ratio) )
# [1] 17.28796
r2evans
  • 141,215
  • 6
  • 77
  • 149
1

As already suggested in this post, looking at C code of TTR provides a possible solution :

x = c(14.24, 13.82, 12.75, 12.92, 12.94, 13.00, 14.14, 16.28, 20.64, 17.64)

n <- 5
y = TTR::EMA(x,n)

ratio <- 2 / (n+1)

newx <- 18.09
newy <- tail(y,1) * (1 - ratio) + ratio * newx
newy
#> [1] 17.28796

y = c(y,newy)
y
#>  [1]       NA       NA       NA       NA 13.33400 13.22267 13.52844 14.44563
#>  [9] 16.51042 16.88695 17.28796
Waldi
  • 39,242
  • 6
  • 30
  • 78
  • Thanks! Using ```y[length(y)]``` instead of tail(y,1) made it considerably faster. – Saurabh Jan 15 '21 at 07:06
  • Thanks for the feedback, and as usual with R, benchmarking is the only way to find out which solution is faster! – Waldi Jan 15 '21 at 09:24