Subscribe to the newsletter!
Subscribing you will be able to read a weekly summary with the new posts and updates.
We'll never share your data with anyone else.

Coding the Moving Average in Python

Posted by Daniel Cano

Edited on May 15, 2024, 5:56 p.m.



Introduction

The moving average is one of the most commonly used technical indicators for trend analysis in time series. However, many people use it without understanding how it works. In this article, you will learn how to calculate various types of moving averages to understand their behavior, strengths, and weaknesses.

What is a moving average?

A moving average is simply the calculation of an arithmetic mean over a sample of data that evolves over time. This means that for the time point t and a period of the moving average n, you should sum the values of a sample that includes the last n values up to t, and then divide the total by the number of values in the sample (n). This way, the equation looks as follows:

media = sum(muestra[t-n:t])/n

When applying this calculation to a sample of more than n values, you will start by using a sample containing the first n values. However, for the next iteration, the first value of the sample will be replaced with the next value in the time series (n+1), and this process will iterate over the entire time series. This is called Moving Average. It is worth noting that the average cannot be obtained for the first n-1 values unless the average is taken over a shorter period.

Simple Moving Average (SMA)

This is the simplest of them all and gives the same weight to all values. This is the calculation of the arithmetic mean of the previous formula. From here, the pandas module will be used for data manipulation; all calculations can be done without using it, but it will be less efficient. The following code shows how to calculate a simple moving average using pandas:

import pandas as pd



data = pd.DataFrame({'a':[1, 2, 3, 4, 5, 6, 7, 8, 9], 

                    'b':[9, 8, 7, 6, 5, 4, 3, 2, 1]})



data['c'] = data['a'].rolling(3).mean()

The pandas.DataFrame is composed of columns a and b. In this case, in the last line of code, a moving average is applied to column a and stored in column c. To calculate the indicator, two functions will be used: rolling and mean. The first is to iterate over samples of 3 values, in this case, and the second to calculate the arithmetic mean. In the following table, you can appreciate the result of the calculation and observe what was mentioned before. The first two values ​​could not be calculated since a sufficiently large sample cannot be formed to meet the period of the average.

0    NaN

1    NaN

2    2.0

3    3.0

4    4.0

5    5.0

6    6.0

7    7.0

8    8.0

Name: c, dtype: float64

 

Exponential Moving Average (EMA)

The exponential moving average assigns exponential weights, following the following formula.

media[t] = muestra[t]*(1+n) + media[t-1]*(1-(1+n))

To iterate the average while applying the new weighting method, the ewm function will be used instead of rolling, with some additional parameters. The same pandas.DataFrame used in the previous example for the base data will be used.

data['c'] = data['a'].ewm(span=3, adjust=False, min_periods=3).mean()

The result will differ slightly from those obtained with SMA but are very similar.

0         NaN

1         NaN

2    2.250000

3    3.125000

4    4.062500

5    5.031250

6    6.015625

7    7.007812

8    8.003906

Name: c, dtype: float64

 

Linear Weighted Moving Average (LWMA)

The linear weighted moving average, also known as cumulative weighted moving average, applies the following formula.

media[t] = (muestra[t]*n + muestra[t-1]*(n-1) + ... + muestra[t-n]*(1))/(1 + 2 + ... + n)

Or, equivalently.

pesos = [i+1 for i in range(n)]

media[t] = sum([valor*(i+1)/sum(pesos) for i, valor in enumerate(muestra[t-n:t])])

The last price has the highest weight, which will be n/n! and the weight of the last price will be 1/n! where n! is the combinatorial number, in case someone is not familiar with it. The following code shows how to apply the formula to a pandas.DataFrame, but, in this case, a new library will be needed: numpy.

import numpy as np



pesos= np.arange(1,3+1)

data['c'] = data['a'].rolling(3).apply(

                          lambda valores: np.dot(valores, pesos)/pesos.sum(), 

                          raw=True)

The above code applied to the data from the first example returns the following:

0         NaN

1         NaN

2    2.333333

3    3.333333

4    4.333333

5    5.333333

6    6.333333

7    7.333333

8    8.333333

Name: c, dtype: float64

 

Comparison

When we compare all the methods of calculating the moving average that we have seen, it is clear that the EMA is the fastest moving average to react to the turns of time series, and the SMA is the slowest. Which one to use will depend on the time series and each individual's preferences.

 

Conclusion

Moving averages are one of the simplest and most commonly used trend indicators. Depending on what they are calculated on, they can be used in different ways. For example, when applied to trading, they can be used for trend classification or as support and resistance.