seagatewholesale.com

A Comprehensive Guide to Implementing a Moving Average Distance Strategy

Written on

Chapter 1: Introduction to Moving Averages

Moving averages are among the most straightforward indicators in trading. Despite their limitations, they have consistently proven effective over time. This guide walks you through a contrarian distance strategy from start to finish using Python.

I have recently published a new book following the success of my previous work. This book delves into advanced trend-following indicators and strategies, complete with a GitHub repository for ongoing code updates. It features an optimized color palette for printing. If this piques your interest, you can visit the Amazon link below, or reach out to me on LinkedIn for a PDF version.

Trend Following Strategies in Python: How to Use Indicators to Follow the Trend

Amazon.com: Trend Following Strategies in Python: How to Use Indicators to Follow the Trend.: 9798756939620: Kaabar…

www.amazon.com

Chapter 2: Retrieving Historical OHLC Data

One of the most popular trading platforms among retail traders is MetaTrader5. This robust software includes its programming language and boasts substantial community support, allowing users to export both short-term and long-term FX data.

To begin, download MetaTrader5 from its official site. After setting up a demo account, we can import the necessary library in Python to retrieve OHLC data.

A library is a collection of structured functions that can be imported into our Python environment. To install the MetaTrader5 library, simply open your Python prompt and type:

pip install MetaTrader5

This command will add the library to your local Python setup. Next, we'll import it along with other essential libraries:

import datetime # For date handling

import pytz # For time zone management

import pandas as pd # For DataFrame manipulation

import MetaTrader5 as mt5 # To import OHLC data

import matplotlib.pyplot as plt # For plotting charts

import numpy as np # For array manipulation

Here, each alias (like plt for matplotlib.pyplot) simplifies our code by allowing us to reference libraries with shorter names. You can find the official documentation for the MetaTrader5 library here.

We can choose which timeframe to import data from; for instance, we can work with 30-minute and hourly bars:

# Selecting the 30-minute timeframe

frame_M30 = mt5.TIMEFRAME_M30

# Selecting the hourly timeframe

frame_H1 = mt5.TIMEFRAME_H1

Next, we define a variable to capture the current date, which will help our algorithm determine when to stop importing data:

# Defining the current date

now = datetime.datetime.now()

It’s advisable to execute these code snippets sequentially to fully grasp each step. Below is a function to specify which assets we want to analyze. For simplicity, we'll only consider two currency pairs: EURUSD and USDCHF.

def asset_list(asset_set):

if asset_set == 'FX':

assets = ['EURUSD', 'USDCHF']

return assets

Now, let’s establish a connection to MetaTrader5, set the current date, and extract the desired data. The parameters for year, month, and day will be determined by us to specify the start date for data retrieval. Note that I’ve set the timezone to Europe/Paris; you should adjust it to your local timezone for more accurate results.

def get_quotes(time_frame, year=2005, month=1, day=1, asset="EURUSD"):

if not mt5.initialize():

print("initialize() failed, error code =", mt5.last_error())

quit()

timezone = pytz.timezone("Europe/Paris")

utc_from = datetime.datetime(year, month, day, tzinfo=timezone)

utc_to = datetime.datetime(now.year, now.month, now.day + 1, tzinfo=timezone)

rates = mt5.copy_rates_range(asset, time_frame, utc_from, utc_to)

rates_frame = pd.DataFrame(rates)

return rates_frame

Lastly, we will clean the results to create a tidy array. The following function retrieves historical data since January 2019:

def mass_import(asset, horizon):

if horizon == 'M30':

data = get_quotes(frame_M30, 2019, 1, 1, asset=assets[asset])

data = data.iloc[:, 1:5].values

data = data.round(decimals=5)

return data

To import the EURUSD OHLC historical data, we use the following code:

# Choosing the horizon

horizon = 'M30'

# Creating an array for EURUSD with M30 data since 2019

EURUSD = mass_import(0, horizon)

Now we have the EURUSD OHLC data from 2019.

Chapter 3: Understanding Moving Averages

Moving averages help confirm trends and maintain our position within them. Their simplicity and effectiveness in technical analysis have made them a staple for traders. We can leverage them to identify support and resistance levels, stops and targets, and to discern the overall market trend.

EURUSD with its 200-period simple moving average.

As the term suggests, a moving average is the arithmetic mean of a set of values, commonly used in statistics and various aspects of daily life. Mathematically, it can be expressed as:

Mathematical representation of a moving average.

Observations show that moving averages can offer significant dynamic support and resistance levels, which are useful for placing orders if the market retraces.

The following code outlines how to create a moving average function:

def adder(Data, times):

for i in range(1, times + 1):

new = np.zeros((len(Data), 1), dtype=float)

Data = np.append(Data, new, axis=1)

return Data

def deleter(Data, index, times):

for i in range(1, times + 1):

Data = np.delete(Data, index, axis=1)

return Data

def jump(Data, jump):

Data = Data[jump:,]

return Data

def ma(Data, lookback, close, where):

Data = adder(Data, 1)

for i in range(len(Data)):

try:

Data[i, where] = (Data[i - lookback + 1:i + 1, close].mean())

except IndexError:

pass

return Data

The function below calculates the moving average on the array named my_data for a lookback period of 200, placing the results in an additional column:

my_data = ma(my_data, 200, 3, 4)

If you're interested in expanding your knowledge of technical indicators and strategies, consider checking out my book:

The Book of Trading Strategies

Amazon.com: The Book of Trading Strategies: 9798532885707: Kaabar, Sofien: Books

www.amazon.com

Chapter 4: Developing the Distance Strategy

The price's distance from its moving average can signal potential corrections, making this a mean-reversion strategy based on the relative distances between two variables. A bullish signal is triggered when the Distance Indicator reaches 0, anticipating a move back toward the moving average, while a bearish signal occurs at 100.

To implement this, follow the syntax below:

lookback = 60

my_data = adder(my_data, 10)

def stochastic(Data, lookback, close, where, genre='High-Low'):

Data = adder(Data, 1)

if genre == 'High-Low':

for i in range(len(Data)):

try:

Data[i, where] = (Data[i, close] - min(Data[i - lookback + 1:i + 1, 2])) / (max(Data[i - lookback + 1:i + 1, 1]) - min(Data[i - lookback + 1:i + 1, 2]))

except ValueError:

pass

Data[:, where] = Data[:, where] * 100

Data = jump(Data, lookback)

return Data

The following function calculates the distance indicator:

def distance_indicator(Data, lookback, close, where):

Data = adder(Data, 2)

Data = ma(Data, lookback, close, where)

Data[:, where + 1] = Data[:, close] - Data[:, where]

Data = stochastic(Data, lookback, where + 1, where + 2, genre='Normalization')

Data = deleter(Data, where, 2)

return Data

Signal chart demonstrating the distance indicator.

The signal function below indicates that a buy order can be initiated when the indicator hits 0, while a sell order is suggested when it reaches 100:

def signal(Data, indicator, buy, sell):

Data = adder(Data, 2)

for i in range(len(Data)):

if Data[i, indicator] == 0.0000 and all(Data[i - j, buy] == 0 for j in range(1, 5)):

Data[i, buy] = 1

elif Data[i, indicator] == 100.0000 and all(Data[i - j, sell] == 0 for j in range(1, 5)):

Data[i, sell] = -1

return Data

Signal chart for trading signals.

For more articles on trading strategies, consider subscribing to my daily newsletter, which includes my Medium articles, additional trading strategies, coding lessons, and a free PDF copy of my first book. You can expect 5-7 articles weekly with a paid subscription and 1-2 articles weekly with the free plan.

Chapter 5: Final Thoughts

Remember always to conduct back-tests. It's crucial to maintain skepticism about others' strategies. What works for me might not suit you. I advocate for self-directed learning; grasp the concepts, intuition, and conditions of the strategy, and then develop your own approach to back-test and refine it before going live.

I also recently launched an NFT collection aimed at supporting various humanitarian and medical causes. The Society of Light is a limited collection where a portion of each sale is donated to charity. Here are some benefits of purchasing these NFTs:

  • High-potential gain: I'm focusing remaining sales proceeds on marketing to maximize secondary market value, with a portion of royalties donated to the charity.
  • Art collection and portfolio diversification: Owning avatars representing good deeds is rewarding. Investing doesn't have to be purely profit-driven; it can also benefit others.
  • Flexible donations: Allocate funds to various charities as you see fit.
  • A free copy of my book in PDF: Buyers of any NFT will receive a complimentary copy of my latest book.
Promoting NFT collection for charity support.

Consider supporting this cause by purchasing an NFT.

Share the page:

Twitter Facebook Reddit LinkIn

-----------------------

Recent Post:

Understanding Dissociation: Are You Aware of Your State?

Explore the complexities of dissociation and how it can affect awareness and perception of one's reality.

Finding Balance: The Importance of Process and Results in Goal Achievement

Explore the ongoing debate between focusing on processes versus results for successful goal achievement.

Monstrous Encounters: Surviving the World's Scariest Creatures

Explore the terrifying monsters from various cultures and learn how to survive encounters with them.