THE 1.000.000 DOLLAR ALGO TRADING STRATEGY (Patreon)
Downloads
Missing 1 file, as this post has not yet been imported.
Content
The Machette strategy Intro
Hi there and welcome to yet another test I did of a trading algorithm. This time i was tipped of by Patreon community member Diego. He was pointing me to this strategy that is called the Machette strategy.
And if you thought I went out with a banger algorithm last year, then beleive me if I say that you also really want to try this out yourself too after this video.
Youtube video link here: https://youtu.be/UZwPXLQORk8
2024.02.MacheteV8b Algo strategy
For this year I want to test out more strategies that are proposed by community members or Youtube comments. And this one was the first one of the bunch that I tested.
This Freqtrade strategy, named MacheteV8b, is a complex and comprehensive algorithm designed for cryptocurrency trading. I call these complex algos, black box algo's because only the developers know which ideas lie exactly after every rule they coded. Especially if they do not leave any documentation in their code fo themselve or any other developer.
Now ofcourse I could put a lot of effort and time into reverse engineering all the code. But I first want to try out if the algo performs well before investing my energy into it. Only after I know if it's worth my time I will take more time to figure things out.
Nonetheles with the help of a friend of mine we took a high level view over the code to see what is the general idea of this strategy.
The strategy
One of the locations of this file is this github directory: https://github.com/PeetCrypto/freqtrade-stuff/blob/main/MacheteV8b.py
Now in the code it is not show who is the author so I cannot give him or her the credits he or shes deserves. But you always can give a star to the repo you found this in. Just to show your appreciation.
Now, let's break down its key components to understand the strategy:
- Indicator Libraries: The strategy imports various technical analysis libraries like TA-Lib, Finta, and custom indicators from the technical package. These libraries are used for calculating technical indicators.
- Strategy Parameters:Buy Parameters: There are multiple boolean parameters (True/False) indicating whether a specific buy signal function should be used. This modular approach allows toggling different buy strategies on and off.
Sell Parameters: Similar to buy parameters, it includes various settings for when to sell, like conditions based on rate of change (roc), time, and others.
ROI Table: Specifies the return on investment at different times. For instance, a 0.279 ROI is targeted initially, decreasing over time.
Stoploss: Defines the stop-loss limit. In this case, it's set to -0.1, meaning a trade will be closed if it reaches a 10% loss. - Dynamic ROI and Custom Stoploss: The strategy uses dynamic ROI (return on investment) and custom stoploss settings to optimize trade exits. This adds flexibility in realizing profits and limiting losses based on market conditions.
- Buy Trend Determination: Multiple methods (like get_buy_signal_awesome_macd, get_buy_signal_adx_momentum, etc.) define the criteria for buy signals. These methods use a variety of indicators such as MACD, ADX, RSI, etc., to determine optimal buying points. The final buy signal is a combination of these methods under certain conditions.
See cells below for additional text
- Sell Trend Determination: The populate_sell_trend method defines the selling conditions. It uses indicators like SSL Channels and Ichimoku (Tenkan and Kijun Sen) to identify sell signals.
- Indicator Calculation: The populate_indicators method is where all the necessary indicators for buy and sell logic are calculated. This method extensively uses data manipulation and technical indicators.
- Custom Indicators: There are custom indicators like RMI, SSLChannels_ATR, and SROC defined at the end of the script, which are used in various buy/sell signal calculations.
- Plot Configuration: The strategy includes settings for visualizing certain indicators on charts, which is useful for analysis and debugging.
- Informative Pairs: The strategy can use additional data from other pairs/timeframes for its calculations.
So overall, MacheteV8b is a comprehensive strategy that combines a variety of technical indicators and conditions to make buy and sell decisions.
It looks like it's tailored for advanced users familiar with technical analysis and cryptocurrency markets. The modular nature of the buy and sell signal functions allows for extensive customization and optimization through hyperparameters. But you'll have to be an experienced coder to adjust these rules without breaking any code here.
My apopogies for being a little bit quick here with this high level explanations and sorry for not explaining each and every rule in the code. But I'm sure you'll understand that nobody will watch a guy read out and explain over 800 lines of code in a video for hours and hours...
And I actually think that most of you are just curious to see what the backtest results are that I got from testing this algo on 50 cryptocurrency pairs for over 4 years of backtesting data.
So let's right to it.
In between part
If I do have to tell you anything about the algorithm at a lower level, then I find the populate_buy_trend function a particular interesting section.
The populate_buy_trend method and the various get_buy_signal_* methods in the Freqtrade strategy script are essential for determining when to execute a buy order based on a combination of technical indicators and conditions.
populate_buy_trend Method
This method aggregates various buy signal conditions to determine the overall buy signal for the strategy.
- It uses a logical OR (|) to combine multiple buy signal conditions. If any one of these conditions is True, the method considers generating a buy signal.
- It checks additional general conditions like sslUp_inf being greater than sslDown_inf, indicating an upward SSL channel trend, and the presence of an upward trend (up_trend_inf) and a long go signal (go_long_inf).
- And If all these conditions are satisfied, the method indicates a buy signal.
Each get_buy_signal_* method represents a specific buy strategy based on various technical indicators. These methods return a Boolean value that indicates whether the conditions for that strategy are met.
If you have watched some of my posts or video's, then you see that a lot of names appear to look familiar.
This is true since this method seems to incorporate all these strategies into one super algo to create multiple buying signals. Depending on the specific strategy.
get_buy_signal_awesome_macd:
- Combines the MACD (Moving Average Convergence Divergence) and AO (Awesome Oscillator) indicators.
- A buy signal is generated when both MACD and AO are positive, and AO has just crossed from negative to positive.
get_buy_signal_adx_momentum:
- Uses ADX (Average Directional Index) to assess the strength of a trend, along with the Momentum indicator.
- A buy signal occurs when ADX is above 25 (strong trend), Momentum is positive, and the Plus Directional Indicator (Plus_DI) is both above 25 and greater than the Minus Directional Indicator (Minus_DI).
get_buy_signal_adx_smas:
- This strategy looks for crossovers of short and long Simple Moving Averages (SMAs) in a strong trend environment (ADX > 25).
get_buy_signal_asdts_rockwelltrading:
- Based on MACD indicators, it generates a buy signal when MACD is positive, the MACD histogram is increasing, and MACD is above its signal line.
get_buy_signal_averages_strategy:
- Uses Exponential Moving Averages (EMAs). A buy signal is produced when the short-term EMA crosses above the medium-term EMA.
get_buy_signal_hlhb:
- Utilizes a combination of RSI, EMA, and ADX. It looks for the crossover of EMA5 and EMA10 with RSI crossing above 50 in a strong trend (ADX > 25).
Also the sell trend section of the Freqtrade strategy script is quite comprehensive, encompassing the logic for processing sell signals, custom stoploss, dynamic ROI, and a method for obtaining the current price of a trading pair.
I will not go deep into this section but if you think this algo is for you. Then it would be certainly worth to invest some time into this section to find out how these mechanisms work.
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(
(self.get_buy_signal_awesome_macd(dataframe) == True)
| (self.get_buy_signal_adx_momentum(dataframe) == True)
| (self.get_buy_signal_adx_smas(dataframe) == True)
| (self.get_buy_signal_asdts_rockwelltrading(dataframe) == True)
| (self.get_buy_signal_averages_strategy(dataframe) == True)
| (self.get_buy_signal_fisher_hull(dataframe) == True)
| (self.get_buy_signal_gettin_moist(dataframe) == True)
| (self.get_buy_signal_hlhb(dataframe) == True)
| (self.get_buy_signal_macd_strategy_crossed(dataframe) == True)
| (self.get_buy_signal_macd_strategy(dataframe) == True)
| (self.get_buy_signal_pmax(dataframe) == True)
| (self.get_buy_signal_quickie(dataframe) == True)
| (self.get_buy_signal_scalp(dataframe) == True)
| (self.get_buy_signal_simple(dataframe) == True)
| (self.get_buy_signal_strategy001(dataframe) == True)
| (self.get_buy_signal_technical_example_strategy(dataframe) == True)
| (self.get_buy_signal_tema_rsi_strategy(dataframe) == True)
) &
(dataframe['sslUp_inf'] > dataframe['sslDown_inf']) &
(dataframe['up_trend_inf'] > 0) &
(dataframe['go_long_inf'] > 0)
# NOTE: I keep the volume checks of feels like it has not much benifit when trading leverage tokens, maybe im wrong!?
#(dataframe['vfi'] < 0.0) &
#(dataframe['volume'] > 0)
,'buy'] = 1
return dataframe
def get_buy_signal_awesome_macd(self, dataframe: DataFrame):
signal = (
(self.buy_should_use_get_buy_signal_awesome_macd.value == True) &
(dataframe['macd'] > 0) &
(dataframe['ao'] > 0) &
(dataframe['ao'].shift() < 0)
)
return signal
def get_buy_signal_adx_momentum(self, dataframe: DataFrame):
signal = (
(self.buy_should_use_get_buy_signal_adx_momentum.value == True) &
(dataframe['adx'] > 25) &
(dataframe['mom'] > 0) &
(dataframe['plus_di'] > 25) &
(dataframe['plus_di'] > dataframe['minus_di'])
)
return signal
def get_buy_signal_adx_smas(self, dataframe: DataFrame):
signal = (
(self.buy_should_use_get_buy_signal_adx_smas.value == True) &
(dataframe['adx'] > 25) &
(qtpylib.crossed_above(dataframe['short'], dataframe['long']))
)
return signal
def get_buy_signal_asdts_rockwelltrading(self, dataframe: DataFrame):
signal = (
(self.buy_should_use_get_buy_signal_asdts_rockwelltrading.value == True) &
(dataframe['macd'] > 0) &
(dataframe['macdhist'].shift(1) < dataframe['macdhist']) &
(dataframe['macd'] > dataframe['macdsignal'])
)
return signal
def get_buy_signal_averages_strategy(self, dataframe: DataFrame):
signal = (
(self.buy_should_use_get_buy_signal_averages_strategy.value == True) &
qtpylib.crossed_above(dataframe['maShort'], dataframe['maMedium'])
)
return signal
def get_buy_signal_fisher_hull(self, dataframe: DataFrame):
signal = (
(self.buy_should_use_get_buy_signal_fisher_hull.value == True) &
(dataframe['hma'] < dataframe['hma'].shift()) &
(dataframe['cci'] <= -50.0) &
(dataframe['fisher_rsi'] < -0.5)
)
return signal
def get_buy_signal_gettin_moist(self, dataframe: DataFrame):
signal = (
(self.buy_should_use_get_buy_signal_gettin_moist.value == True) &
(dataframe['primed']) &
(dataframe['moist']) &
(dataframe['throbbing']) &
(dataframe['ready-to-go'])
)
return signal
def get_buy_signal_hlhb(self, dataframe: DataFrame):
signal = (
(self.buy_should_use_get_buy_signal_hlhb.value == True) &
(qtpylib.crossed_above(dataframe['rsi_10'], 50)) &
(qtpylib.crossed_above(dataframe['ema5'], dataframe['ema10'])) &
(dataframe['adx'] > 25)
)
return signal
def get_buy_signal_macd_strategy_crossed(self, dataframe: DataFrame):
signal = (
(self.buy_should_use_get_buy_signal_macd_strategy_crossed.value == True) &
qtpylib.crossed_above(dataframe['macd'], dataframe['macdsignal']) &
(dataframe['cci'] <= -50.0)
)
return signal
def get_buy_signal_macd_strategy(self, dataframe: DataFrame):
signal = (
(self.buy_should_use_get_buy_signal_macd_strategy.value == True) &
(dataframe['macd'] > dataframe['macdsignal']) &
(dataframe['cci'] <= -50.0)
)
return signal
def get_buy_signal_pmax(self, dataframe: DataFrame):
signal = (
(self.buy_should_use_get_buy_signal_pmax.value == True) &
(qtpylib.crossed_above(dataframe['ZLEMA'], dataframe['pm_10_3_10_9']))
)
return signal
def get_buy_signal_quickie(self, dataframe: DataFrame):
signal = (
(self.buy_should_use_get_buy_signal_quickie.value == True) &
(dataframe['adx'] > 30) &
(dataframe['tema'] < dataframe['bb_middleband']) &
(dataframe['tema'] > dataframe['tema'].shift(1)) &
(dataframe['sma_200'] > dataframe['close'])
)
return signal
def get_buy_signal_scalp(self, dataframe: DataFrame):
signal = (
(self.buy_should_use_get_buy_signal_scalp.value == True) &
(dataframe['open'] < dataframe['ema_low']) &
(dataframe['adx'] > 30) &
(
(dataframe['fastk'] < 30) &
(dataframe['fastd'] < 30) &
(qtpylib.crossed_above(dataframe['fastk'], dataframe['fastd']))
)
)
return signal
def get_buy_signal_simple(self, dataframe: DataFrame):
signal = (
(self.buy_should_use_get_buy_signal_simple.value == True) &
(dataframe['macd'] > 0) # over 0
& (dataframe['macd'] > dataframe['macdsignal']) # over signal
& (dataframe['bb_upperband'] > dataframe['bb_upperband'].shift(1)) # pointed up
& (dataframe['rsi_7'] > 70) # optional filter, need to investigate
)
return signal
def get_buy_signal_strategy001(self, dataframe: DataFrame):
signal = (
(self.buy_should_use_get_buy_signal_strategy001.value == True) &
qtpylib.crossed_above(dataframe['ema50'], dataframe['ema100']) &
(dataframe['ha_close'] < dataframe['ema20']) &
(dataframe['ha_open'] > dataframe['ha_close']) # red bar
)
return signal
def get_buy_signal_technical_example_strategy(self, dataframe: DataFrame):
signal = (
(self.buy_should_use_get_buy_signal_technical_example_strategy.value == True) &
(dataframe['cmf'] < 0)
)
return signal
def get_buy_signal_tema_rsi_strategy(self, dataframe: DataFrame):
signal = (
(self.buy_should_use_get_buy_signal_tema_rsi_strategy.value == True) &
(qtpylib.crossed_above(dataframe['rsi'], 30)) & # Signal: RSI crosses above 30
(dataframe['tema'] <= dataframe['bb_middleband']) & # Guard: tema below BB middle
(dataframe['tema'] > dataframe['tema'].shift(1))
)
return signalBacktest results
If you have read my earlier posts then you know I use a certain methodology for testing out these algorithms. Otherwise I cannot compare the end results between these strategies with each other. And this time it is not different.
Now because this algo has an informative timeframe on the 1 hour. I could not test higher timeframes than that. But I do not think that this would gaven me eny better results.
This algo is created to work best on the 15 minute timeframe and it sure does not dissapoint on that same timeframe.
At first I could not beleive my eyes. I always thought that the results of the last tested 'Obelisk Ichimoku Zema' could not be beaten. How naive of me to think that...
Apparently there are still hidden gems lying here and there on the Internet to be discovered. And this is one of them.
This strategy could attain a theoretical one million dollar over the 15 minute backtesting period.
Which is an absolute insane amount!!!
It has a 75 percent win rate with an average 6 win streak over 2 losses after another.
With this you can beleive that the Calmar, Sortino, Sharpe and other ratios are also off the charts. Also 80 percent of the trading pairs seem to respond well to this algo.
I will not even mention the insane amounts you hypothetically got when you traded on the other timeframes here.
And therefore a bit warning before I continue the story.
It could be that this code greatly suffers from look-ahead-bias. Which means that it can see into the future because of the full dataset it gets for backtesting. If the algo already knows this future information, it could act on this in the best possible way. Like having a glass ball to look into the future.
Which, under normal circumstances is not possible ofcourse.
By just glancing over the code you cannot discover that and more investigations to find this out are needed. You can also test this algo out by forward testing it by doing a dry run for a couple of weeks or months. Be aware that the moment you start a trading bot with this algo is also important and that can cause losses on the short term.
However if you look at the way the account balance has been growing over the last couple of years. You could not tell that this specific algorithm suffers much from bear markets. Even at those moments the balance seems to be growing.
But it really takes off during the last bull run. To an extreme hight of over one million dollar.
The really good winrate seems to play a big role in these profits. At the same moment the profit curve goes parabolic, the amount of cumulative winning trades also rises. While the losing trade line stays relatively stable, as well as the draws line.
And because of this performance, the drawdown also stays relatively low. It has some peaks of over 8 percent but on average the drawdown is around 3,5 percent.
Another plot that I'd like to show you is the average profit line.
Maybe I should not include the data before 2021 in this plot, because that is so low in comparison to the 2022 parabolic curve.
But it shows you how extreme the averave and total weekly profits were in the last bull market.
The average profit with this algo, with my settings and crypto pairs was sometimes over 2000 dollar.
And at an extreme point there were weeks that this algo could attain 120.000 dollars profit in these conditions. Now who doesn't want to make almost 3 times a Dutch modals years income in a week.
Mind you that there are also losing weeks. With extremes of 4000 dollar losses.
The next chart I want to show you is the win loss ratio. This chart shows you the weeks where there were wins, in blue, over losses, in red.
This chart is an another view of the cumulative wins and losses chart I showed earlier But here they are compared with each other. The previous chart showed you already that there were more wins than losses.
However in this graph I can point really well in which period the winrate was really good. That was in the period just before the last bull markets top. Where everything went parabolic.
Also you can see on this graph that there were also weeks in 2019 with good win ratios, that were not clearly visible in the previous charts.
As you can understand by now, we have a very special trading strategy in our hands.
One that performs well in Bull and bear markets. Where the winrates are high and profitable and the losses sometimes occur and have almost no impact on our account balance.
Comparing the performance of this algorithm with the earlier tested algos, specially the best one that I found in 2023, makes those profits seem like pocket money.
The result of this trading algo is even three times higher than the result of the number two on the list.
Also comparing the individual performance metrics between this algo and the previous results is making me think if I should use yet another layout for these chart. Because some of the other results are barely visible on some of these plots.
Look at the profit percentage plot. Maybe I should make this plot logarithmic or so...
It is that good...
End score and League position
It should be no surprise anymore that this algorithm takes up first spot in the Strategy League.
It has an insane score of 550 points and Im wondering if I have to readjust the complete scoring mechanism again. But let's see that if I test other algo strategies later.
The last couple of strategies I tested last year were absolute bangers. But this year also starts off with a smasher.
Is it because of the coming bull run and is it a sign from above, or do we just have plain luck here?
Who knows..?
Anyway, as you have seen, I have not been lying at the start of this video.
If you test out this algo and want to share the results with the community, that would be great! This is the way we can crosscheck if this is a truly great algo.
Many thanks for reading and I will see you in the next video,
Goodbye..!
