Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 35

Moving Averages with Pandas

Recommended resources

Hello! Welcome back.

In our last lesson, you mastered the crucial skill of resampling time-series data, allowing you to create any timeframe you need for your analysis. Now that we have our data prepared and structured, we can begin to extract meaningful insights from it.

Today, we'll take our first step into true quantitative analysis. The learning outcome is to calculate basic indicators like moving averages using pandas. This is a fundamental skill for any aspiring quantitative trader and a necessary building block for your goal of developing trading bots. While ICT focuses primarily on pure price action, understanding how to programmatically calculate indicators is the same core skill you will later use to detect more complex ICT patterns like Fair Value Gaps and order blocks.

From Price Data to Market Insights

Raw price data is just a sequence of numbers. To make sense of it, we create indicators. One of the most fundamental and widely used indicators is the moving average. Its purpose is to smooth out price fluctuations and help identify the underlying trend of the market. Think of it as reducing the "noise" of candle-to-candle volatility to see the bigger picture.

We will focus on two main types:

  1. Simple Moving Average (SMA): The average price over a specific number of periods. Every data point in the window is weighted equally.
  2. Exponential Moving Average (EMA): A type of moving average that gives more weight to recent prices, making it more responsive to new information and reducing lag.

For a trader, the choice between SMA and EMA often comes down to a trade-off between smoothness (SMA) and responsiveness (EMA).


Calculating a Simple Moving Average (SMA)

The SMA is the most straightforward type of moving average. To calculate a 10-period SMA, you simply sum the closing prices of the last 10 candles and divide by 10.

In pandas, this is achieved with the .rolling() method. This method creates a "rolling window" of a specified size that moves over your data, allowing you to perform a calculation on the data within that window at each step.

To see this in action, let's watch a video that demonstrates the process.

Moving Average (Rolling Average) in Pandas and Python - Set Window Size, Change Center of Data

The video 'Moving Average (Rolling Average) in Pandas and Python' from the datagy channel provides a clear, step-by-step guide to using the .rolling() function.

Please watch the segment from 01:51 to 04:08. The presenter will explain how to use the .rolling() method, the importance of the window parameter, and how to chain it with .mean() to calculate the final SMA.

As you saw, the syntax is clean and intuitive. Here is the complete pattern applied to a familiar OHLCV DataFrame:

import pandas as pd
import yfinance as yf # We'll use yfinance to get some real data

# Let's fetch some recent hourly data for EUR/USD
# Note: You may need to run 'pip install yfinance' in your terminal
data = yf.download('EURUSD=X', period='10d', interval='1h')

# --- SMA Calculation ---
# We want to calculate a 20-period SMA on the 'Close' price.
# 1. Select the 'Close' price column: data['Close']
# 2. Create a rolling window of size 20: .rolling(window=20)
# 3. Calculate the mean of each window: .mean()
sma_20 = data['Close'].rolling(window=20).mean()

# Now, let's add this back to our DataFrame as a new column
data['SMA20'] = sma_20

# Display the last few rows to see our new column
# Notice the first 19 rows of 'SMA20' will be NaN (Not a Number)
# because you need 20 periods of data to calculate the first SMA.
print(data.tail())

Calculating an Exponential Moving Average (EMA)

The EMA is often preferred in trading because it reacts more quickly to recent price changes. The calculation is more complex, but the key idea is that the most recent price gets the most weight, and the weight of older prices decays exponentially.

Fortunately, pandas handles this complexity for us with the .ewm() method, which stands for "exponentially weighted moving." Instead of a window, its key parameter is span, which is conceptually similar to the window size of an SMA.

This article provides a good textual explanation of the EMA and its implementation.

Python for Finance, Part 3: Moving Average Trading Strategy

The article 'Python for Finance, Part 3: Moving Average Trading Strategy' from LearnDataSci explains the concept of EMA and how it reduces lag.

Read the section that begins with 'One way to reduce the lag...'. Focus on the conceptual difference between SMA and EMA, and look at the code example that uses .ewm(span=20, adjust=False).mean().

The adjust=False parameter mentioned in the article is often used to match the calculation method used by many trading platforms.

Let's add a 50-period EMA to our DataFrame:

# --- EMA Calculation ---
# To calculate a 50-period EMA on the 'Close' price.
# 1. Select the 'Close' price column: data['Close']
# 2. Apply the exponentially weighted function with a span of 50: .ewm(span=50, adjust=False)
# 3. Calculate the mean: .mean()
ema_50 = data['Close'].ewm(span=50, adjust=False).mean()

# Add it to our DataFrame
data['EMA50'] = ema_50

# Display the tail again to see both MAs
print(data.tail())
Test your understanding!

You want to add a long-term trend filter to your analysis using a 200-period Simple Moving Average. How would you calculate this and add it to your data DataFrame in a new column called 'SMA200'?

Show answer
data['SMA200'] = data['Close'].rolling(window=200).mean()

It's that simple. You just change the window size to 200. This single line of code calculates the average of the last 200 closing prices for every candle in your dataset.


Practical Application: Building a MACD Indicator

To solidify your understanding, let's build a real technical indicator from scratch using the skills you just learned. The Moving Average Convergence Divergence (MACD) is a popular momentum indicator built entirely from EMAs.

It consists of three parts:

  1. MACD Line: The 12-period EMA minus the 26-period EMA.
  2. Signal Line: A 9-period EMA of the MACD Line itself.
  3. Histogram: The MACD Line minus the Signal Line (we'll cover this when we get to visualization).

This is a perfect exercise, as it requires you to calculate multiple EMAs and then perform arithmetic between them. The following video walks through exactly how to do this.

Building a MACD Indicator in Python

The video 'Building a MACD Indicator in Python' by Financial Python is a practical demonstration of applying EMA calculations to create a more complex indicator.

Please watch from 03:02 to 07:45. The presenter will guide you through: Calculating the 12-period and 26-period EMAs. Subtracting them to create the MACD line. Calculating the 9-period EMA of the MACD line to create the Signal line.

Let's implement this on our own data DataFrame.

# --- MACD Calculation ---

# 1. Calculate the 12-period and 26-period EMAs
ema_12 = data['Close'].ewm(span=12, adjust=False).mean()
ema_26 = data['Close'].ewm(span=26, adjust=False).mean()

# 2. Calculate the MACD Line
data['MACD'] = ema_12 - ema_26

# 3. Calculate the Signal Line (a 9-period EMA of the MACD line)
data['Signal_Line'] = data['MACD'].ewm(span=9, adjust=False).mean()

# Display the final DataFrame with all our calculated indicators
print("DataFrame with SMA, EMA, and MACD components:")
print(data[['Close', 'SMA20', 'EMA50', 'MACD', 'Signal_Line']].tail(10))

By following these steps, you've gone from raw price data to a DataFrame enriched with multiple, standard technical indicators. This is a massive step forward in your ability to programmatically analyze market data.


Conclusion

In this lesson, you've bridged the gap from data preparation to data analysis. You now have the foundational skill to calculate any rolling or expanding indicator, which is a cornerstone of building automated trading strategies.

Key Takeaways:

  • A moving average smooths price data to help identify trends.
  • Use .rolling(window).mean() to calculate a Simple Moving Average (SMA).
  • Use .ewm(span=N).mean() to calculate an Exponential Moving Average (EMA).
  • EMAs are generally more responsive to recent price changes than SMAs.
  • You can combine these simple calculations to build more complex indicators like the MACD.

Preview for the Next Lesson:
Looking at a table of numbers is useful, but a chart is worth a thousand data points. In our next lesson, "Create basic price visualizations using a plotting library," we will bring our analysis to life. You will learn how to plot the price data and overlay the moving averages and MACD lines you calculated today, creating the exact kind of charts you're used to seeing on your trading platform.