# How I Made a Weighted Moving Average Trading Strategy Using Python (Rules, Backtest)

This article will explain how to backrest a Weighted Moving Average in Python. In the first part, there will be a brief introduction and explanation of this indicator. Subsequently, we will implement a Python example to calculate the result of the trading strategy. Finally, we will implement a for-loop with our strategy.

## What is a weighted moving average?

A Weighted Moving Average is a statistical estimator that calculates an average in a range of days. It puts more weight on recent data.

Imagine that two days ago, a company released its financial statements with positive results; its stock price will increase because of the new information. Under this new scenario, the closing price before the earnings release will not be as important as the new one. Therefore, trying to assign more weight to new information will be more relevant.

## Illustration of a weighted moving average

Let’s calculate the following Weighted Moving Average (4-day):

On a chart the different averages look like this:

In column 3 from the previous table, we see how to estimate a WMA(4) by hand.

Let’s explain the last row. The multiplication of 0.6×22 is the first coefficient in the previous formula and the value from Price of day eleven.

The multiplication of 0.25*18 represents the second coefficient and the value from Price of day ten.

While 0.1*20 represents the third coefficient and the value from Price of day nine, 0.05*20 represents the last coefficient and the value from Price of day eight.

The previous plot shows the evolution of Price, WMA, and SMA(4). We see how WMA(4) is a better fit for the closing price.

## A practical example of a weighted moving average

In this tutorial, we will use data from yfinance. The financial instrument to use is SPY, while the start and end periods are 01/01/20 and 31/12/2020:

## A weighted moving average trading strategy

The strategy to implement will be a crossover weighted moving average; there will be two Weighted Moving Averages, a short and a long WMA. The length period will be 5 and 10 days, respectively. The purpose here is to show how it’s done, not to make a tradable trading strategy.

The idea of this strategy is to have a short-term indicator that will show the trend and a long-term indicator that will show the long-term trend.

This strategy will generate long and short positions, following these trading rules:

• When the short-term WMA(4) is higher than the long-term WMA(10).

Sell (short):

• When the long-term WMA(10) is higher than the short-term WMA(20).

Importing Libraries

Let’s import the libraries:

The Python libraries (packages) comprise functions, classes, and other collections of elements. For example, the library yfinance retrieves historical financial data from Yahoo Finance in Python. On the other hand, it is necessary to go to the Yahoo Finance website to manually download the data, and then import it in Python; therefore, the user will spend more time.

We employ yf.Ticker to retrieve information from the financial symbol. Then, we implement stock.history for downloading financial data. The upcoming image shows the code implementation and the first five rows from the dataset:

Now, let’s examine the last three rows:

## Estimate returns of the trading strategy

The daily return shows how much a financial instrument changes from one day to the next. Its formula:

In Python, the estimation is:

## Example of how to use rolling and apply in pandas

In pandas, there is no direct method for estimating the Weighted Moving Average. It is necessary to use .rolling and .apply; these components facilitate the implementation of custom functions.

To illustrate the following image, let’s create a dictionary (example) and pass its values to a pandas DataFrame (pexample). The .rolling(window=3).apply(lambda x: x.sum()) means that we will generate a new series. The elements of this series will be the sum of the last previous values of pexample[“Example”].

For instance, the third element in pexample[“rolling_sum“] is 1 + 2”3=6. While the fourth element is 2+3+4=9, etc.

## Estimate WMA in Python

In this section, we will create two Weighted Moving Averages. The WMAs will have the following weights:

First weights: w1 = [0.6, 0.25, 0.15, 0.05]

Second weights: w2 = [0.18181818, 0.16363636, … , 0.03636364, 0.01818182]

In the following image, list(range(10, 0, -1)) is a vector with elements from 1 to 10.

To explain in more detail what does .rolling(len(w1)).apply(lambda x: (w1*x).sum()/np.sum(w1), raw=True), let’s calculate by hand the first two elements of WMA:

• From stock_data[”Close”], we get its first four elements 306.295227, 303.975861, 305.135620, and 304.277588 and multiply them by w1:
1. 0.6*306.295227 +0.25*303.975861 +0.15*305.135620 +0.05*304.277588)/ (0.6 + 0.25 + 0.15 + 0.05)= 305.481261
• From stock_data[”Close”], we get the rows two, three, four and five (303.975861, 305.135620, 304.277588, and 305.899231) and multiply them by w1:
1. 0.6*303.975861 + 0.25*305.135620 + 0.15*304.277588 + 0.05*305.899231/(0.6 + 0.25 + 0.15 + 0.05) = 304.386687

## How to calculate trading signals

The next step is to apply the trading rules:

• When wma1 > wma2

Sell (short selling):

• When wma2 <= wma1

The np.where(wma1 > wma2, 1, -1) command enables us to implement both conditions. When wma1 > wma2, the corresponding value in the series will be one (1); otherwise, when wma1 <= wma2, the value becomes minus one (-1).

## How to calculate strategy performance

In the forthcoming chart, we will calculate the returns from the strategy. We will achieve this by multiplying stock_data[”Close”].pct_change() * stock_data[”Signal”].shift(1). Remember that stock_data[”Signal”] is a series denoting (buy=1,sell=-1).

To illustrate, if the return of a particular day is 0.01 (1%) and the signal is 1, the calculation will result in 0.01 * 1= 0.01, representing a long position. Conversely, if the return of a particular day is 0.01 (1%) and the signal is -1, the calculation will result in 0.01*-1=-0.01, representing a long position.

## How to plot strategy performance

The following image shows the strategy performance:

Part 3: for-loop

In this section, we will implement the same strategy using the following stocks:

BHP: BHP Group Limited

RIO: Rio Tinto Group

Examples 1 for-loop

The previous code prints the elements from 0 to 4. In total 5 elements.

Example 2 for-loop

Strategy and for-loop

The previous code will print “For Loop”; then, it will print the number of elements 0 and 1; finally, it will print the name of the stock (stock_list[i]).

The following image shows how to implement the strategy in a for-loop for BHP and RIO. In green is highlighted the code that we implemented in the previous section.

fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(12, 4)) is creating the framework to make the charts; stock_list are the two financial instruments; finally, axes[i] help to plot both charts.

I’ve got an Msc from Heriot-Watt University, Edinburgh (1996), in addition a to a business administration degree the Norwegian School of Management (BI – 1994). Did my mandatory military service in between. After university, I worked two years as an auditor (1996-1998). I co-founded Aksjeforum.com in 1998/99 - one of the first websites about trading and investing in Norway. It was later acquired by Digi.no in 2001. From 2001 until 2018 I was a full-time independent and automated day trader, mainly via Echotrade LLC (USA), trading successfully to become a FIRE. I passed the Series 7 exam in 2001, but it has since lapsed. Since 2018 until today full-time investor.