Jorman Franzini
Jorman Franzini

Reputation: 339

Calculating Exponential Moving Average (EMA) using javascript

Hi Is possible to calculate EMA in javascript?

The formula for EMA that I'm trying to apply is this

EMA = array[i] * K + EMA(previous) * (1 – K)

Where K is the smooth factor:

K = 2/(N + 1)

And N is the Range of value that I wanna consider

So if I've an array of value like this, and this value grow during the times:

var data = [15,18,12,14,16,11,6,18,15,16];

the goal is to have a function, that return the array of the EMA, because any of this value, expect the very fist "Range" value, have this EMA, for each item on data, I've the related EMA value. In that way I can use all or use only the last one to "predict" the next one.

function EMACalc(Array,Range) {
var k = 2/(Range + 1);
...
}

I can't figure out how to achieve this, any help would be apreciated

Upvotes: 11

Views: 17923

Answers (4)

StuR
StuR

Reputation: 12218

I'm providing a new answer to this as the way this is calculated in technical analysis/indicators (binance, tradingview, etc) slightly varies from the answers already posted here.

The difference is that the SMA (Simple Moving Average) is used as a starting point to calculate the EMA.

For a list of candles, ticks, prices, where the period or interval is 5 we should expect:

  • 1st Tick - undefined
  • 2nd Tick - undefined
  • 3rd Tick - undefined
  • 4th Tick - undefined
  • 5th Tick - SMA (sum of first 5 ticks / period)
  • 6th Tick - EMA (((price - prevEMA) * exponent) + prevEMA)

Calculate Exponential Moving Average for technical analysis:

const calcEMA = (prices) => {
  let sum = 0
    let averages = []
    let prevEMA = undefined
    let tickIndex = 1

    for (const price of prices) {

      if (tickIndex < period) {
        tickIndex++
          sum = sum + price
          averages.push(undefined)
      } else {

        if (prevEMA) {
          // EMA
          prevEMA = ((price - prevEMA) * exponent) + prevEMA
        } else {
          // SMA
          prevEMA = ((sum + price) / period)
        }

        averages.push(prevEMA)

      }
    }
  return averages
}

calcEMA([
    81.59, 81.06, 82.87, 83.0, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36, 85.53, 86.54, 86.89, 87.77, 87.29,
])

Upvotes: 0

4UmNinja
4UmNinja

Reputation: 540

I like recursion, so here's an example of an EMA function that uses it. No need to maintain arrays.

function weightMultiplier(N) { return 2 / (N + 1) }

function ema(tIndex, N, array) {
    if (!array[tIndex-1] || (tIndex) - (N) < 0) return undefined;
    const k = weightMultiplier(N);
    const price = array[tIndex];
    const yEMA = ema(tIndex-1, N, array) || array[tIndex-1]
    return (price - yEMA) * k + yEMA
}

Upvotes: 2

Redu
Redu

Reputation: 26161

The following can be another way of implementing the EMA.

var getEMA = (a,r) => a.reduce((p,n,i) => i ? p.concat(2*n/(r+1) + p[p.length-1]*(r-1)/(r+1)) : p, [a[0]]),
      data = [15,18,12,14,16,11,6,18,15,16],
     range = 3;

console.log(getEMA(data,range));

Upvotes: 6

Daniel Reina
Daniel Reina

Reputation: 6327

I don't know if I completely understood what you need, but I will give you the code for a function that returns an array with the EMA computed for each index > 0 (the first index doesn't have any previous EMA computed, and will return the first value of the input).

function EMACalc(mArray,mRange) {
  var k = 2/(mRange + 1);
  // first item is just the same as the first item in the input
  emaArray = [mArray[0]];
  // for the rest of the items, they are computed with the previous one
  for (var i = 1; i < mArray.length; i++) {
    emaArray.push(mArray[i] * k + emaArray[i - 1] * (1 - k));
  }
  return emaArray;
}

This should do it.

Upvotes: 26

Related Questions