Smoothing Time Series with the Holt Filter: A Gentle Introduction

Unraveling the Math, Code, and Practical Applications of a Simple Yet Powerful Smoothing Technique

Thomas Konstantinovsky
The Pythoneers
6 min readAug 18, 2024

--

If you’ve ever worked with time series data, you’ve likely encountered the challenge of smoothing out noisy fluctuations to reveal an underlying trend. This is where the Holt Filter comes in — a straightforward yet powerful tool designed to smooth signals while accounting for trends. In this post, I’ll do my best to guide you through the basics of the Holt Filter, from its mathematical formulation to Python implementation. Finally, I’ll show you how to apply it to real-world data.

Understanding the Holt Filter

The Holt Filter, also known as Holt’s linear trend method, is an extension of simple exponential smoothing that allows us to smooth time series data with an underlying trend. Unlike basic smoothing techniques that only focus on the present value, the Holt Filter also considers the rate of change, or trend, in the data. This makes it especially useful when you need to forecast future values or smooth data with an upward or downward trajectory.

Filter Formal Defenition

The Holt Filter uses two key equations: one for the level (which represents the smoothed value) and another for the trend (which represents the rate of change).

Formal Defenition of the Holt Filter

Now, for some, this may look intimidating and unclear, but the intuition behind each variable is relatively straightforward; let us see what each variable stands for.

Definition of Each Variable

Intuition Behind the Equations

Level Equation:

Think of the level ŷ_t as your best guess for the current “true” value of the series. The smoothing factor α helps balance between the actual observed value y_t and what you expected the value to be based on the last estimate plus the previous trend. If α is high, you trust the current observation more; if low, you rely more on your past estimates.

Trend Equation:

The trend ŷ_t represents how fast the series is increasing or decreasing. The smoothing factor β determines how much you update your trend estimate based on the difference between the new level and the previous level. A high β means you’re quick to adapt to changes in the trend, while a low β indicates you prefer a more stable trend.

Forecast Equation:

The forecast equation combines the current level and trend to predict future values. It’s like projecting your current understanding of the series into the future!

Python Implementation of the Holt Filter

def holt_filter(y, alpha, beta):
n = len(y)
level = [y[0]] # your signals initial level
trend = [y[1] - y[0]] # estimated initial trend (can be replaced with custom value)
smoothed = [level[0] + trend[0]] # forcast equation list

for t in range(1, n):# iterate over each time step
new_level = alpha * y[t] + (1 - alpha) * (level[t-1] + trend[t-1]) # estimate level
new_trend = beta * (new_level - level[t-1]) + (1 - beta) * trend[t-1] # estimate trend

level.append(new_level)
trend.append(new_trend)
smoothed.append(new_level + new_trend)

return smoothed

Real-World Application Example: Smoothing Stock Prices

Let’s dive into a more meaningful real-world example: smoothing stock price data. Stock prices are often noisy, with daily fluctuations that make it challenging to identify trends. By applying the Holt Filter, we can smooth out these short-term fluctuations and reveal the underlying trend in the stock prices.

An Example of a Noisy Signal: Notice the Green Line has Many Fluctuations, but in this Example, It's Not Enough to Mask the overall trend. Nevertheless, It Still Will Benefit a Lot from Smoothing, Especially When We Start to Analyze a Large Number of Such Signals.

We’ll use historical stock price data for this example. First, I’ll show you how to fetch and preprocess the data, apply the Holt Filter, and then analyze the results by tuning the parameters α and β.

To quickly and easily access this data, you simply need to install the “yfinance” python package running the pip install yfinance command in your jupyter notebook or conda shell.

import yfinance as yf
import matplotlib.pyplot as plt

# fetch a snap shot from historical stock price data for Apple Inc. (AAPL)
data = yf.download('AAPL', start='2020-01-01', end='2022-01-01')
prices = data['Close'].values # extract the closing prices

plt.figure(figsize=(15, 6))
plt.plot(prices, label='Original Stock Prices')
plt.title('AAPL Stock Prices (2020-2022)')
plt.xlabel('Days')
plt.ylabel('Price')
plt.legend()
plt.grid(lw=2,ls=':')
plt.show()
The Snapshot of data download using yfinance

Applying the Holt Filter

Now, let’s apply the Holt Filter to smooth the stock prices. We’ll start with a default set of parameters and then experiment with different values for α and β.

def holt_filter(y, alpha, beta):# this is our function from before
n = len(y)
level = [y[0]]
trend = [y[1] - y[0]]
smoothed = [level[0] + trend[0]]

for t in range(1, n):
new_level = alpha * y[t] + (1 - alpha) * (level[t-1] + trend[t-1])
new_trend = beta * (new_level - level[t-1]) + (1 - beta) * trend[t-1]

level.append(new_level)
trend.append(new_trend)
smoothed.append(new_level + new_trend)

return smoothed

# here we apply the Holt Filter with initial parameters
smoothed_prices = holt_filter(prices, alpha=0.5, beta=0.3)

plt.figure(figsize=(15, 6))
plt.plot(prices, label='Original Stock Prices',lw=3,alpha=0.8)
plt.plot(smoothed_prices, label='Smoothed Prices (α=0.5, β=0.3)', linestyle='--',lw=2,color='red')
plt.title('Holt Filter Applied to AAPL Stock Prices')
plt.xlabel('Days')
plt.ylabel('Price')
plt.legend()
plt.grid(lw=2,ls=':')
plt.show()
Here in red, we can see the smoothed signal, where we can see the smoothing effect here with these parameters is quite soft

Tuning the Parameters

The effectiveness of the Holt Filter depends heavily on the choice of α and β. Let’s explore how different combinations of these parameters affect the smoothing process.

Low α, Low β:
Here, both the level and trend adapt slowly to new data, resulting in a smoother but less responsive trend line.

smoothed_prices_1 = holt_filter(prices, alpha=0.2, beta=0.1)

plt.figure(figsize=(15, 6))
plt.plot(prices, label='Original Stock Prices',lw=3,alpha=0.8)
plt.plot(smoothed_prices_1, label='Smoothed Prices (α=0.2, β=0.1)', linestyle='--',lw=2,color='red')
plt.title('Holt Filter Applied to AAPL Stock Prices')
plt.xlabel('Days')
plt.ylabel('Price')
plt.legend()
plt.grid(lw=2,ls=':')
plt.show()
Low α, Low β

High α, Low β:
The level responds quickly to new data, but the trend changes slowly. This configuration might smooth out noise effectively while still capturing significant changes.

High α, Low β
  1. High α, High β:
    Both the level and trend adapt quickly, which could lead to a trend line that closely follows the original data but might overfit to noise.
High α, High β

Analyzing the Results

By comparing the different plots, you can observe how the choice of α and β impacts the smoothness and trend responsiveness of the Holt Filter. A lower α and β yield a smoother curve that is less sensitive to daily fluctuations, which might be desirable if you are only interested in the long-term trend. On the other hand, higher values of α and β will allow the filter to react more quickly to changes in the data, which can be useful for detecting new trends earlier.

Conclusion

The Holt Filter is a versatile and practical method for anyone working with time series data. Whether you’re analyzing stock prices, temperature readings, or any other type of sequential data, this method can help you smooth out the noise while keeping track of underlying trends.

What makes the Holt Filter particularly powerful is its ability to account for both the current value (level) and the trend, giving you a more accurate and responsive way to forecast and interpret your data. As we’ve seen, tuning the parameters α and β allows you to adjust the filter to your specific needs, whether you want a smoother curve that emphasizes the long-term trend or a more responsive one that quickly adapts to changes.

By understanding the mathematical logic behind the Holt Filter and experimenting with its implementation in Python, I hope you can better harness its capabilities in your own projects and endeavours.

I hope this post has demystified the Holt Filter for you and provided practical insights into how to apply it effectively. If you have any questions or thoughts, feel free to share them in the comments — I’d love to hear from you!

--

--

Thomas Konstantinovsky
The Pythoneers

A Data Scientist fascinated with uncovering the mysterious of the world