Implementing exponential moving average in Java

Naftuli Kay picture Naftuli Kay · Feb 8, 2012 · Viewed 25.5k times · Source

I essentially have an array of values like this:

0.25, 0.24, 0.27, 0.26, 0.29, 0.34, 0.32, 0.36, 0.32, 0.28, 0.25, 0.24, 0.25

The above array is oversimplified, I'm collecting 1 value per millisecond in my real code and I need to process the output on an algorithm I wrote to find the closest peak before a point in time. My logic fails because in my example above, 0.36 is the real peak, but my algorithm would look backwards and see the very last number 0.25 as the peak, as there's a decrease to 0.24 before it.

The goal is to take these values and apply an algorithm to them which will "smooth" them out a bit so that I have more linear values. (ie: I'd like my results to be curvy, not jaggedy)

I've been told to apply an exponential moving average filter to my values. How can I do this? It's really hard for me to read mathematical equations, I deal much better with code.

How do I process values in my array, applying an exponential moving average calculation to even them out?

float[] mydata = ...
mySmoothedData = exponentialMovingAverage(mydata, 0.5);

float[] exponentialMovingAverage(float[] input, float alpha) {
    // what do I do here?
    return result;
}

Answer

Donal Fellows picture Donal Fellows · Feb 8, 2012

To compute an exponential moving average, you need to keep some state around and you need a tuning parameter. This calls for a little class (assuming you're using Java 5 or later):

class ExponentialMovingAverage {
    private double alpha;
    private Double oldValue;
    public ExponentialMovingAverage(double alpha) {
        this.alpha = alpha;
    }

    public double average(double value) {
        if (oldValue == null) {
            oldValue = value;
            return value;
        }
        double newValue = oldValue + alpha * (value - oldValue);
        oldValue = newValue;
        return newValue;
    }
}

Instantiate with the decay parameter you want (may take tuning; should be between 0 and 1) and then use average(…) to filter.


When reading a page on some mathmatical recurrence, all you really need to know when turning it into code is that mathematicians like to write indexes into arrays and sequences with subscripts. (They've a few other notations as well, which doesn't help.) However, the EMA is pretty simple as you only need to remember one old value; no complicated state arrays required.