MACD and EMA Trend Strategy: A Full Algorithmic Backtest in Python

Full Transcript — Download SRT & Markdown

00:00
Speaker A
Hi, and welcome back. In this video, I will show you a simple entry signal using the exponential moving average and the MACD.
00:06
Speaker A
We'll be using the moving average to detect the trend and the MACD to choose entry positions.
00:11
Speaker A
Signals we expect from this algorithm are displayed in red and green triangles on this chart; we can see that the algorithm detected the trend correctly and is also picking some good entry positions.
00:22
Speaker A
This is another example where in a clean downtrend, the algorithm is very efficient at picking tradeable entries.
00:28
Speaker A
So, in the following few minutes, I will explain the details of the indicator and I will also show you how you can code this approach in Python, plug it in a strategy for a backtest.
00:37
Speaker A
If you are interested in the coding part, you can download the code for free from the link in the description of this video, get the code, run your own backtest, and experiment with some modifications.
00:46
Speaker A
And since the purpose of this video is definitely not to bait you into watching through, if you are expecting a super performance strategy, the results are kind of frustrating.
00:55
Speaker A
These are limited to 5.5% annual return and a sharp ratio of 1.45.
01:00
Speaker A
And in the best case, a return of 27.6% per year.
01:05
Speaker A
Of course, I took commissions into account during the backtest based on Forex data.
01:09
Speaker A
So, why am I showing a not very performant strategy? Well, mainly because I have seen a similar strategy being manually backtested by a colleague of mine, and it actually looked very convincing.
01:20
Speaker A
However, manual testing is prone to human bias and selective memory, which leads to inaccurate backtesting; moreover, it's also time-consuming, imagine you are trying out thousands of trades, so at the end it's kind of limited.
01:33
Speaker A
While the automated backtesting removes bias, can test thousands of trades, and in general is more reliable.
01:39
Speaker A
The strategy uses two rules; the first one is to detect the trend based on the moving average.
01:45
Speaker A
So, if the last five candles are trading above the moving average curve, we are in an uptrend; if they are trading below the moving average, we are in a downtrend; however, in both cases, the full body of the candle must be above or below the curve, meaning both the open and close prices of each candle should be either above or below the moving average curve.
02:05
Speaker A
In an uptrend, we only allow long positions, and in a downtrend, we only allow short positions.
02:10
Speaker A
When an uptrend is confirmed, we are looking for a long opportunity, so we will wait for a retracement of the price.
02:18
Speaker A
Which can be detected as the MACD histogram crosses or did cross below a negative threshold within the most recent candles; so if any of the most recent candles did cross below the MACD threshold, we have a retracement; in this backtest, I took seven candles window.
02:38
Speaker A
And now, when we have a retracement, we wait until the MACD line crosses above the signal line while both are still below zero; this means that the retracement is over and the trend is probably going to continue, so that cross is our trigger, we enter long at the candle close.
02:54
Speaker A
In the opposite direction, we are in a short setup, the MACD histogram has to cross above a positive threshold, and the MACD line needs to cross below the signal line while both are in the positive part, we enter a short position.
03:07
Speaker A
So, in brief, we are going along the trend, minimizing risk, and we are also trying to improve our risk-reward ratio using the MACD to choose our entry positions.
03:16
Speaker A
Now, let's move on to the coding part and see what we can do with the backtest.
03:20
Speaker A
So, this is our Jupyter notebook file that you can download from the link in the description of the video; in this cell, I'm importing libraries, so we're going to need Pandas TA, technical analysis, Pandas, NumPy, datetime, YFinance to get the data, and the backtesting package.
03:34
Speaker A
So, these are the variables we're going to use; I'm using the one-hour time frame, for now I'm testing EURUSD; the number of back candles when we are testing with the MACD is backcandles_prev; then we have the risk-reward ratio, which is set to one by default.
03:49
Speaker A
And this is the swing window variable, which is the window within which we're going to check for a minimum and a maximum to set the stop loss.
03:55
Speaker A
So now we can set the start and end dates of our test; then I'm going to refurbish an older function that we were using to fetch the data; so this function takes a symbol, takes a start and end date, and the interval or the time frame, and it's going to probe YFinance to get the data.
04:13
Speaker A
Now, one thing we should be aware of, if you're putting stocks here, for example, if I put instead of the EURUSD, I put Amazon, for example, going to get the data, we try to plot the candles, it looks like we have some gaps or some bad data; so just make sure whenever you're using something, get the proper data and verify that the data you're working with is what you intend to use.
04:36
Speaker A
So, for now, I'm going back to Forex, and then if we plot these candles again, we can see that we have a better data in this case; so, anyway, just make sure your data is correct before you try and backtest this.
04:49
Speaker A
So, back to our functions, so we have the fetch data function, then we have the EMA trend signal; this is the function that takes a DataFrame and number of back candles, backcandles_prev, which means it's going to test how many back candles are above or below the moving average curve to return a signal, which is plus one in case it's bullish, minus one bearish, and zero otherwise.
05:12
Speaker A
Then we're going to put everything into a function named build_features for the DataFrame; it's going to compute the exponential moving average 200 and then it's going to compute the MACD as well, and this is where the entry signal is computed; so, I've tried many different logics, so there is one here using the MACD, this one is using the MACD as well, and this one is the last one, which in my opinion is the best; I left these in comments here so you can switch them on, switch this one off and so on, check the different logics, or just customize these to your liking.
05:47
Speaker A
So, at the end, we have the precomputed signal in the DataFrame; I'll be running this cell, calling the function fetch data, then build features, then I'm printing where we have signals; as we can see, the pre_signal here, we have the EMA signal is bearish, also the MACD signal is bearish, so in total, the total signal is bearish, and so on, so whenever we have bullish, bullish, it's going to yield a bullish; so, in total, we have 67 signals for a total trading period of 400 days.
06:08
Speaker A
Now, I added this cell just as an experiment as well; whenever we have a regime change, whenever we have a trend change, we're switching from minus one, for example, to plus one, we're going to ignore the first signal, we're going to replace it by zero; the reason is because the change incurs choppiness in the market, the noise is increasing at that point until we have established a clear trend, we refrain from trading; so in this case, we dropped the number of signals from 67 to 58 signals in total.
06:39
Speaker A
Now, in this part, I've defined different strategies, different exit strategies and different risk strategies, just to make sure that we are giving the indicator or the entry indicator a maximum of the chances.
06:54
Speaker A
Now, by the way, if you take a look at the last part, which is plotting the candles and the signals, it looks really good; if we take a look at this triangle, for example, it is followed by a few hours of an uptrend, it's not much, but there's a movement upwards; this one, for example, is also followed by an uptrend; we have three different signals here at a certain support level, if you notice, but then it's also climbing upwards; this one is also followed by an upward direction and so on.
07:23
Speaker A
By the way, I chose this randomly, this is starting from the start up to 500 candles.
07:33
Speaker A
Now we can try 500 up to 1000 candles.
07:42
Speaker A
Here we have a bearish signal, and as you can see, for few hours later, the price went really down, so this one was a good signal; we have just one signal in this window, we can try one more window from 1000 up to 1500.
08:01
Speaker A
So we're verifying, so this is a clear downtrend, we have a bearish signal here, a bearish signal here with good entry positions, this one is also a good one, so it's followed by few hours of down; so visually, actually, the indicator is not bad, it's looking really well.
08:20
Speaker A
But does it really fit for a systematic trading approach for a simple exit strategy?
08:30
Speaker A
Now, this is what we're going to discover.
08:32
Speaker A
To make this story short, I'm not going to go through all the details of the strategies.
08:44
Speaker A
I'll just tell you the differences in between these; so the first one is using, of course, the MACD and the EMA, and it's putting the stop loss at the swing window, within the swing window, so that's the either the high or the lowest point of the previous candles within the swing window variable; we have a risk-reward ratio for the take profit, but also we have a break-even part; so whenever a trade is winning half the take profit, the intended take profit, we're moving the stop loss to the entry position, to the entry price level; this way, we can break even in case the price reverts back.
09:19
Speaker A
So, that's what break-even means in this case for the strategy; then we have another one, we have a normal swing window strategy without any break-even; for experimentation, we have a swing or ATR, so whichever is wider, because I've noticed sometimes the swing high or a swing low is very close to the entry position, and so the stop loss is very tight; I wanted to avoid this, so I added also the ATR distance as well, and I'm taking the maximum in between these two, either the swing distance or the ATR, whichever is greater.
10:00
Speaker A
Then I also tried the ATR distance or a certain percentage, so the stop loss is just a percent of the price, above or below the price, depending on which direction we are trading; and finally, I've used a trail stop using the ATR distance as a starting point.
10:13
Speaker A
These are the different strategies I've been trying; then I'm also running an optimization over the risk-reward ratio parameters, so it's either one, 1.5, 2 up to 3, and then the swing window grid as well, between 3 and 9 candles.
10:25
Speaker A
And so the reason I'm showing you all of these strategies and all the optimization is that when you do this manually, that's impossible to, to do; you can't repeat this operation that many times in order to optimize your strategy and your parameters; this is only doable when you are coding and using such numerical tools.
10:55
Speaker A
And this is it, basically; now we just have to call the functions that were defined here, for example, we have optimize and heatmap, and it's going to run for a certain strategy, we provide the name of the class here for the particular strategy, then we check the results.
11:17
Speaker A
The results are the optimized results, and you can see it's going to take a bit of time in order to optimize all the parameters.
11:30
Speaker A
If you want to just run a simple backtest using the default parameters, you can also define the backtest here, and then run bt.run, and it's going to run the strategy as is.
11:40
Speaker A
So, here we can see that we have 2% returns for this particular strategy; if we try to do it for the trailing stop, for example.
11:50
Speaker A
I'm going to run it for the trail stop, just optimizing the ATR coefficient, like the starting stop loss distance parameter; so this is the only parameter we are optimizing here, so it's just the ATR multiplier; you can see that we can reach 6.65% with a sharp ratio of 1.45, and the rest of the ratios are seen here.
12:07
Speaker A
So the win rate is around 42%, and the best trade is 3%, worst trade is minus 0.9%; it's actually not bad because it's kind of a safe way of trading, it's not losing much.
12:23
Speaker A
The maximum drawdown, let me check the maximum drawdown, it's minus 3.6%; so compare this to the returns, it's not as bad.
12:33
Speaker A
We could try and add some leverage to boost our returns, so margin is equal to, let's say, 1 over 5 in this case.
12:41
Speaker A
I'm going to run this again, and the optimization, and now we have 34.4% in returns and an annual return of 27% with a sharp ratio of 1.22; it's actually not very bad; the drawdown, maximum drawdown of minus 16%, and the win rate of 42% still.
13:04
Speaker A
So, I think we could increase a bit the leverage if you want to take more risk to boost your results.
13:14
Speaker A
But this is not very safe; I mean, the good thing about this strategy is that it's safe, as we have noticed, it has very limited drawdown versus the returns, and this is what we are leveraging here.
13:24
Speaker A
Remember, this was obtained only with 47 trades, so that's not enough; we need to get more data and test the strategy on different assets for robustness.
13:34
Speaker A
However, whenever you test it on a different asset, just make sure that the threshold of the MACD is adapted, because this one is going to change depending on the asset itself; let me show you where you need to figure this out; it's the histogram threshold for 10 to minus 6 in the case of EURUSD, and it's in the function build_features.
13:58
Speaker A
Now there is a way to link it to the ATR, it's more dynamic, and you can compute the threshold as a multiplier constant multiplied by the ATR value, this way it can adapt to different assets automatically, but I prefer to keep it manual in order to know what is happening, and we can increase it or decrease it, we could optimize it as well to make the indicator more or less selective, depending on the strategy and the approach you want to trade with.
14:20
Speaker A
And this will be it for this one.
14:26
Speaker A
I hope you guys liked it and found the information interesting or helpful.
14:33
Speaker A
I hope you learned something new today.
14:35
Speaker A
So please leave a like, drop a comment, if you have any ideas how to improve the MACD strategies, because I've never had a lot of chance with this particular indicator.
14:50
Speaker A
Any ideas you have, you can drop them in the comments section.
14:55
Speaker A
Thank you so much for your support, thank you for staying that long.
15:00
Speaker A
Until our next one, trade safe and see you next time.

Get More with the Söz AI App

Transcribe recordings, audio files, and YouTube videos — with AI summaries, speaker detection, and unlimited transcriptions.

Or transcribe another YouTube video here →