Introduction
Sometimes you need to calculate the moving average of a quantity. In this article, I describe wrapper classes that help you calculate the moving average. There are various methods to calculate moving average like the simple moving average, the weighted moving average and the exponential moving average. Due to time constraints, I have implemented only the first two.
Background
There is a very good article on Moving Averages on Wikipedia. However, I will go ahead and describe it very briefly.
When you are measuring an average, you are measuring the mean value of the quantity over the whole range of data. Sometimes it is useful to measure only the average of the last N sample values. For example, a trader might be interested to know the average price of a certain stock in the last seven days and he/she wants this value every day. This would be done by calculating the moving average. Every time a new sample is added to the data, we need to throw away the oldest sample, add the new sample to the data and compute the average.
The weighted moving average is a modified version of the simple moving average where each sample can be assigned a weight depending on the application or analysis. Typically, the most recent sample is assigned the highest weight and the least recent sample assigned the lowest weight.
The exponential weighted moving average is another version of the weighted moving average where the weights increase or decrease exponentially.
I have two C++ wrapper classes - CSimpleMovingAverage
for simple moving average and CWeightedMovingAverage
for weighted moving average. Both classes derive from CMovingAverage
so that they present a uniform interface. This way someone can add more complex moving averages to the "library".
Using the Code
In order to use the CSimpleMovingAverage
or CWeightedMovingAverage
, you must first create the object like this:
CSimpleMovingAverage movingAvgCtr;
Both classes implement only two methods which are quite self explanatory:
virtual void AddSample(const float a_fSample) = 0;
virtual float GetAverage() const = 0;
By default, the classes will measure the average over the most recent 10 samples. Suppose you want to have a bigger sample interval, you can pass the desired sample size to the constructor:
CSimpleMovingAverage movingAvgCtr(20);
Now to start getting the average, you will need to add the samples using the AddSample
method:
movingAvgCtr.AddSample(44.5);
You can get the moving average at any point in time by using the GetAverage()
method.
Implementation Details
Internally the samples are maintained using an STL queue container. Since after acquiring N samples we need to throw away the least recent sample and add the new sample, I found the queue's push, pop, front and back operations very intuitive while coding.
Points of Interest
The reason I wrote up this code is because when I needed it I could not find any C++ code on the web. I know these classes are lacking in some aspects. In CWeightedMovingAverage
, I assign the most recent sample the highest weight, someone may want to do the reverse and assign the least recent sample the highest weight (Why? It depends on the application, unfortunately my understanding of statistics is not good, so I don't know). And of course, the exponential moving average is also missing from the library.
One of my weak points is that I do not write enough automated test cases. In main.cpp, I have written a minimalistic test case which I used to verify the correctness of the code. I got weird values for weighted moving averages when I included negative sample values in the data. I am not sure if it is a bug in the code or if they are expected results?
History
- 28th April, 2009: Initial post