Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing exponential moving average in Java

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;
}
like image 364
Naftuli Kay Avatar asked Feb 08 '12 20:02

Naftuli Kay


People also ask

How do you calculate exponential moving average in Java?

Calculating the smoothing factor If you would like to calculate the value of the factor for a 21 day EMA, then the calculation would be as follows: Smoothing Factor = 2 / (21 + 1) = 0.0909090909090909.. Notice that the number will always be less than 1.

How are simple moving averages implemented?

A simple moving average (SMA) is an arithmetic moving average calculated by adding recent prices and then dividing that figure by the number of time periods in the calculation average.

Is exponential smoothing or moving average better?

For a given average age (i.e., amount of lag), the simple exponential smoothing (SES) forecast is somewhat superior to the simple moving average (SMA) forecast because it places relatively more weight on the most recent observation--i.e., it is slightly more "responsive" to changes occuring in the recent past.


2 Answers

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.

like image 71
Donal Fellows Avatar answered Sep 19 '22 15:09

Donal Fellows


I am having a hard time understanding your questions, but I will try to answer anyway.

1) If your algorithm found 0.25 instead of 0.36, then it is wrong. It is wrong because it assumes a monotonic increase or decrease (that is "always going up" or "always going down"). Unless you average ALL your data, your data points---as you present them---are nonlinear. If you really want to find the maximum value between two points in time, then slice your array from t_min to t_max and find the max of that subarray.

2) Now, the concept of "moving averages" is very simple: imagine that I have the following list: [1.4, 1.5, 1.4, 1.5, 1.5]. I can "smooth it out" by taking the average of two numbers: [1.45, 1.45, 1.45, 1.5]. Notice that the first number is the average of 1.5 and 1.4 (second and first numbers); the second (new list) is the average of 1.4 and 1.5 (third and second old list); the third (new list) the average of 1.5 and 1.4 (fourth and third), and so on. I could have made it "period three" or "four", or "n". Notice how the data is much smoother. A good way to "see moving averages at work" is to go to Google Finance, select a stock (try Tesla Motors; pretty volatile (TSLA)) and click on "technicals" at the bottom of the chart. Select "Moving Average" with a given period, and "Exponential moving average" to compare their differences.

Exponential moving average is just another elaboration of this, but weights the "older" data less than the "new" data; this is a way to "bias" the smoothing toward the back. Please read the Wikipedia entry.

So, this is more a comment than an answer, but the little comment box was just to tiny. Good luck.

like image 22
Escualo Avatar answered Sep 16 '22 15:09

Escualo