Creating an Effective Moving Average Cross Trading Strategy in Python
Written on
Chapter 1: Introduction to Moving Averages
The moving average cross strategy is a fundamental trend-following approach that utilizes different-period moving averages to indicate possible trend reversals. While this strategy seems intuitive, it is essential to substantiate our instincts with quantitative analysis.
For those interested in deepening their knowledge, I’ve published a book titled "Contrarian Trading Strategies in Python." This book is packed with advanced contrarian indicators and strategies and includes a GitHub repository for the continuously updated code. You can purchase the PDF version for €9.99 via PayPal. Please remember to include your email in the note so that you receive it at the correct address. Afterward, make sure to download it via Google Drive.
Moving Averages Explained
Moving averages are crucial for affirming and capitalizing on trends. Their popularity stems from their simplicity and effective contribution to analytical processes. Traders utilize them to identify support and resistance levels, set stop-loss and target prices, and grasp the prevailing market trend. This adaptability makes moving averages an essential element in any trader's toolkit.
As the term implies, a moving average is simply the arithmetic mean calculated from a series of observations. In mathematical terms, it is represented as the sum of all observations divided by the total number of observations. The following code illustrates how to implement a moving average in Python:
# Function to add a specified number of columns to an array
def adder(Data, times):
for i in range(1, times + 1):
new_col = np.zeros((len(Data), 1), dtype=float)
Data = np.append(Data, new_col, axis=1)
return Data
# Function to remove a specified number of columns starting from an index
def deleter(Data, index, times):
for i in range(1, times + 1):
Data = np.delete(Data, index, axis=1)return Data
# Function to delete a number of rows from the beginning
def jump(Data, jump):
Data = Data[jump:, ]
return Data
# Example of adding 3 empty columns to an array
my_ohlc_array = adder(my_ohlc_array, 3)
# Example of deleting the 2 columns after the column indexed at 3
my_ohlc_array = deleter(my_ohlc_array, 3, 2)
# Example of deleting the first 20 rows
my_ohlc_array = jump(my_ohlc_array, 20)
# Function to calculate the moving average
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:
passdata = jump(data, lookback)
return data
# Call the moving average function on 'my_data'
my_data = ma(my_data, 200, 3, 4)
For a deeper understanding of market trends and future directions, check out my weekly market sentiment report.
Chapter 2: Implementing the Cross Strategy
In the realm of moving averages, two significant concepts are widely recognized:
- The Golden Cross: This occurs when a short-term moving average crosses above a long-term moving average, signaling a potential bullish trend.
- The Death Cross: This happens when a short-term moving average crosses below a long-term moving average, indicating a possible bearish trend.
The core idea of our trading strategy is to code both the golden and death crosses. However, one must consider which periods to choose. Options include combinations like 50 and 200, 10 and 30, or 100 and 500. With numerous possibilities, we will use a 50 and 100-period lookback for our example.
def signal(data, short_ma, long_ma, buy, sell):
data = adder(data, 10)
for i in range(len(data)):
if data[i, short_ma] > data[i, long_ma] and data[i - 1, short_ma] < data[i - 1, long_ma]:
data[i, buy] = 1if data[i, short_ma] < data[i, long_ma] and data[i - 1, short_ma] > data[i - 1, long_ma]:
data[i, sell] = -1return data
# Execute the moving average calculations and signal function
my_data = ma(my_data, short_ma, 3, 4)
my_data = ma(my_data, long_ma, 3, 5)
signal(my_data, 4, 5, 6, 7)
However, one significant drawback of these strategies is the lag, which can lead to buying at peaks and selling at troughs.
Chapter 3: Conclusion and Best Practices
In conclusion, my aim is to enhance the domain of objective technical analysis by advocating for transparent techniques and strategies that require back-testing before implementation. This will help elevate the credibility of technical analysis, often perceived as subjective.
When assessing any trading technique or strategy, I recommend adhering to the following steps:
- Maintain a critical mindset and eliminate emotional biases.
- Conduct back-testing using realistic simulations and conditions.
- If viable, optimize the strategy and perform forward testing.
- Always account for transaction costs and slippage in your tests.
- Incorporate risk management and position sizing into your assessments.
Lastly, even after following these guidelines, it is essential to remain vigilant and monitor the strategy, as market conditions can change, potentially rendering the strategy ineffective.
This video demonstrates how to code a simple moving average (SMA) crossover trading strategy using Python, providing a visual guide to the coding process.
This video showcases the backtesting of a moving average crossover trading system in Python, illustrating how to evaluate its effectiveness.