The ‘ClucMay72018’ algo trading strategy (Patreon)
Content
Hello, and welcome to another post, where I will discuss the ClucMay72018 algorithmic trading strategy. Again, this strategy is available from the Freqtrade site and you can download it following this link.
And at first I had some dissapointing results when I was testing this algo strategy for crypto’s.
I also had some serious issues when I was testing this strategy. Not to mention the many times I tried to optimize only the ROI and stop loss. My PC froze, the optmization timed out, I had segmentation faults, worker processes unexpectedly terminated or other causes. In the end I could only optimize this strategy with only 40 epochs and a time range of only a year. Otherwise my PC just freaked out…
I saved all the output from these efforts on my PC and will make them available for my Patrons so that they can check on what happened and maybe reproduce or improve my efforts to analyse this strategy.
But after I finally got some optimization results and backtested the original best scoring timeframe and timespan again I really got some serious improvements on this strategy. You have to watch this video till the end to see how spectacular these results are.
The strategy
Let me start first with the usual analysis of the strategies code. As said, this code comes from the Freqtrade website and was originally made or collected by the Berlinguyinca. So all credits of providing us with this strategy goes to him.
# --- Do not remove these libs ---
from freqtrade.strategy import IStrategy
from typing import Dict, List
from functools import reduce
from pandas import DataFrame
# --------------------------------
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
from typing import Dict, List
from functools import reduce
from pandas import DataFrame, DatetimeIndex, merge
# --------------------------------
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
import numpy # noqa
The first four import statements import standard Python libraries and the IStrategy interface from the freqtrade.strategy module.
The IStrategy interface is used to define custom trading strategies that can be implemented by the freqtrade bot.
The next set of import statements import additional libraries and modules used by the script. The talib.abstract module provides a set of technical analysis functions, while the freqtrade.vendor.qtpylib.indicators module provides a collection of custom indicators for use in trading strategies.
Finally, the numpy library is also imported.
The script also defines two identical import statements for the typing and functools modules, which are used to support type hints and functional programming features in Python.
class ClucMay72018(IStrategy):
"""
author@: Gert Wohlgemuth
works on new objectify branch!
"""
INTERFACE_VERSION: int = 3
# Minimal ROI designed for the strategy.
# This attribute will be overridden if the config file contains "minimal_roi"
minimal_roi = {
"0": 0.01
}
# Optimal stoploss designed for the strategy
# This attribute will be overridden if the config file contains "stoploss"
stoploss = -0.05
# Optimal timeframe for the strategy
timeframe = '5m'
Freqtrade strategy files always have the following elements present. It is dependend on the developer if , and how much the strategy makes use of these settings. In this case the strategy is designed to achieve a minimum ROI of 1% and the stoploss is set to -5%.
This means that for each faulty trade, where stop loss gets hit, there has to be at least 5 good trades based on ROI to get break even again.
And finally the strategy is designed to work with 5-minute candlestick data.
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe['rsi'] = ta.RSI(dataframe, timeperiod=5)
rsiframe = DataFrame(dataframe['rsi']).rename(columns={'rsi': 'close'})
dataframe['emarsi'] = ta.EMA(rsiframe, timeperiod=5)
macd = ta.MACD(dataframe)
dataframe['macd'] = macd['macd']
dataframe['adx'] = ta.ADX(dataframe)
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
dataframe['bb_lowerband'] = bollinger['lower']
dataframe['bb_middleband'] = bollinger['mid']
dataframe['bb_upperband'] = bollinger['upper']
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=50)
return dataframe
Now one of the most interesting parts start.
Here the indicators are defined that will be used and will determine how buy and sell settings are defined.
Let’s go over them line by line:
The method takes two arguments: a DataFrame of candlestick data, and a metadata dictionary.
The first line of the method adds the Relative Strength Index (RSI) technical indicator to the DataFrame, using a timeperiod of 5.
The next line creates a new DataFrame containing only the RSI data and renames the column to ‘close’.
The third line of the method adds an Exponential Moving Average (EMA) technical indicator to the new DataFrame created in the previous step, using a timeperiod of 5. This EMA is based on the RSI data.
The fourth line adds the Moving Average Convergence Divergence (MACD) technical indicator to the original DataFrame.
The fifth line adds the Average Directional Index (ADX) technical indicator to the original DataFrame.
The sixth line calculates the Bollinger Bands technical indicator using the typical price of the candlestick data, with a window of 20 and a standard deviation of 2. The lower, middle, and upper bands are added to the DataFrame.
The seventh line adds another EMA to the DataFrame, this time with a timeperiod of 50 and based on the closing price of the candlestick data.
Finally, the method returns the updated DataFrame with all the added technical indicators.
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Based on TA indicators, populates the buy signal for the given dataframe
:param dataframe: DataFrame
:return: DataFrame with buy column
"""
dataframe.loc[
(
(dataframe['close'] < dataframe['ema100']) &
(dataframe['close'] < 0.985 * dataframe['bb_lowerband']) &
(dataframe['volume'] < (dataframe['volume'].rolling(window=30).mean().shift(1) * 20))
),
'enter_long'] = 1
return dataframe
Then there is the buy signal function and for some reason a lot of indicators were defined in the previous section, lik the rsi, macd, adx. But they are actually not used at all for creating buy or sell signals
The criteria for buying a crypto pair are when:
The closing price of the candlestick is less than the 100-period Exponential Moving Average (EMA).
The closing price is less than 98.5% of the lower Bollinger Band value.
The volume of the candlestick is less than 20 times the 30-period rolling average of the volume, shifted back one period. This is a crude measure of trading volume being below average.
The second line of the method sets the ‘enter_long’ column of the selected rows to 1, indicating a buy signal.
Finally, the method returns the updated DataFrame with the ‘enter_long’ column populated with buy signals.
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Based on TA indicators, populates the sell signal for the given dataframe
:param dataframe: DataFrame
:return: DataFrame with buy column
"""
dataframe.loc[
(
(dataframe['close'] > dataframe['bb_middleband'])
),
'exit_long'] = 1
return dataframe
This exit signal function is pretty simple. It tells the bot to exit the trade if the close price is higher than the bollinger bands middle band.
So what I assume that this strategy does is that it uses a kind of oversold mechanism, using the lower bollinger band and a very low volume as a trigger for buying a position. With the EMA100 as the baseline indicator that the pair is in a downward movement.
Funny enough, or is it just coincidence, I told in my last video that a scalping strategy like the BinHV45 strategy is, should have some sort of indicator to determine the circumstances the strategy works best in. And this code does exactly what I mean.
It first determines the major trend where it works well in and then, when the best circumstances arise, the strategy does its work. And apparently this Clucmay code works best under bearish circumstances.
Now let’s test this strategy to see if I’m actually right or wrong…
Initial backtest
So as I said in the beginning. I had a lot of trouble backtesting and optimizing this strategy. And at first I did not want to take all the effort to further investigate this one because the initial backtest results did not make me very enthousiastic.
The best timeframe was the 5 minute timeframe. And it was only the best timeframe because it suffered the least amount of losses. A best result with 22 percent loss is not something to be proud of.
And exactly as predicted the stoploss setting again proves to be the big spoiler here. A winrate of 79 percent is something to be proud of, but not at the expence of the 21 percent of major losing trades in total.
So something had to be done to find out if adjusting the roi and stop loss settings could improve things. The code did not have any other buy or sell parameters to improve so I just sticked with roi and stoploss.
Hyperparameter optimization
So optimizing such simple parameters on such a low timeframe proved to be too much for my machine.
The computer errored out on me quite a few times and sometimes I had to hard reset my PC because it completely froze up on me. Apparently the computer I have is a little bit low on capacity to make these calculations and now I have something on my wishlist for the future.
Anyway, I tuned the timerange and epochs parameters so that I still could get an optimization result. Just to complete my process, and I did not expect much of it anymore at that time.
So in the end I only had the timerange set to 202201 to 202301 and only 10 epochs where I managed to get an optimization.
Again I did not expect much anymore so I backtested over the last three years to see if it could manage to get any gains.
But I was just flabbergasted to see the results I got.
With the stoploss set pretty large and also the three default ROI settings this strategy performs just super good.
With still a winrate of 66 percent, a drawdown of only 23 percent and very high Calmar, Sortino and Sharpe ratio’s it got some unbeleivable results. Not to mention that 76 percent of all the top 50 coins from 2022 were susceptible to this strategy.
Now the exit signal is the major sources of losses and the new roi and stop loss settings prove to be more optimized. Especially the crazy amount of profits of the roi got me triggered to investigate this further.
Maybe this is too much curve fitting or something else is going on. Like the strange behaviour of the trailing stop loss in backtest settings.
Ps. you might wonder where the roi and stoploss settings are in this video. I’ll post the json output and all other output on my Patreon page. So that you can download and check it out for yourself.
Some further investigations
Now there is another unfortunate thing before I continue my analysis and that is that the plotting files for this strategy are more than 1 gigabyte large. That’s way to much to handle for my browser (yes a new PC might help). So I can only show you a blank screen. Nonetheless I will add these to the complete fileset anyway. For those who do have a powerfull enough computer to open the html file.
So I tried another way to determine where these huge profits came from and I backtested different timeperiods with these settings.
Comparing the results of the different time periods and comparing to the market volatility of the complete cryptocurrency market. I can only assume that in the period 2021 – 2022 there was a lot of market volatility that causet a lot of buy triggers to the down side. And luckily also enough upside volatility to make money from these downward direction buying decisions.
This is a chart on the daily timeframe so the movements on the 5 minute timeframe could be even more extreme then shown here.
During the more dull periods like the complete 2018 to 2020 periode it did not made much money. And also did not lose much as wel as you can see on the drawdown.
Nonetheless, more granular investigation is necessary to find out what exactly happens at each trade and if the bollinger band or ema itself can also be optimized. The fact is that in all these backtests, which I’ll add to my dataset for my patreons, the winrate is higher than 50%. This makes it also a possible strategy that gives you a good feeling when you see that it regularly makes winning trades. Which is a big psychological factor I might say.
Strategy league
So with these optimized results and its sudden change from a losing to a very well performing strategy, where does it end on the strategy league?
I cannot deny the fact that this strategy suddenly scores so well on so many factors.
It is also a great surprise to see this strategy enter on the highest spot on my league. It might not have the highest profits but on all other factors it seems to score very good. So good that it has top spot at the moment.
It is highly possible that the optimization might suffer from overfitting. However I only adjusted the stop loss and roi settings though. And all other indicators use default settings and are not specific to this strategy at all. So only well timed take profits and good stop loss settings make this strategy perform very well at the moment.
To me it looks like it is a strategy that could also work well in combination with another strategy that guards well on upside market movements. If these movements get way into the overbought conditions then a change to this strategy might be a good idea. But as always, this has to be investigated further.
But for now a new number one and it is certainly a surprising one.
And I am curious if somebody will take the time to make further attempts to analyse this system and add these results to the comment section of the video. Do you get the same spectacular results or totally different ones and is it a total failure in your situation. I am very curious and like to see some confirmation here.
But for now I think I am ready with the tests of this system and await your responses.
Thank you for watching and I’ll see you in the next video!
Goodbye!
Ps. FIles are available in this post: https://www.patreon.com/posts/80711943