Home Creators Posts Import Register Favorites Logout
haven't archived this post yet. have a subscription? use the importer!

Downloads

  • 2024.02.MacheteV8b.7z

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:

  1. 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.
  2. 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.
  3. 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.
  4. 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
  1. 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.
  2. 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.
  3. 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.
  4. Plot Configuration: The strategy includes settings for visualizing certain indicators on charts, which is useful for analysis and debugging.
  5. 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 signal

Backtest 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..!


Comments

Business Proposal

Hello, Youtube says: Private video Sign in if you've been granted access to this video. I have signed up, but still not success.

Wojtek Chruścicki

I have a problem with missing modules in docker, do you have a video explaining how to add them?

Dan

Any clue why the key is missing from the data frame? 2024-01-21 19:12:49 - freqtrade.strategy.interface - WARNING - Unable to analyze candle (OHLCV) data for pair AMP/USDT: 'MA_9_10' 2024-01-21 19:12:49 - freqtrade.strategy.strategy_wrapper - ERROR - Unexpected error 'MA_9_10' calling > Traceback (most recent call last): File "/home/ftuser/.local/lib/python3.11/site-packages/pandas/core/indexes/base.py", line 3791, in get_loc return self._engine.get_loc(casted_key) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "index.pyx", line 152, in pandas._libs.index.IndexEngine.get_loc File "index.pyx", line 181, in pandas._libs.index.IndexEngine.get_loc File "pandas/_libs/hashtable_class_helper.pxi", line 7080, in pandas._libs.hashtable.PyObjectHashTable.get_item File "pandas/_libs/hashtable_class_helper.pxi", line 7088, in pandas._libs.hashtable.PyObjectHashTable.get_item KeyError: 'MA_9_10' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/freqtrade/freqtrade/strategy/strategy_wrapper.py", line 27, in wrapper return f(*args, **kwargs) ^^^^^^^^^^^^^^^^^^ File "/freqtrade/freqtrade/strategy/interface.py", line 873, in _analyze_ticker_internal dataframe = self.analyze_ticker(dataframe, metadata) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/freqtrade/freqtrade/strategy/interface.py", line 851, in analyze_ticker dataframe = self.advise_indicators(dataframe, metadata) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/freqtrade/freqtrade/strategy/interface.py", line 1378, in advise_indicators return self.populate_indicators(dataframe, metadata) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/freqtrade/user_data/strategies/MacheteV8b.py", line 202, in populate_indicators dataframe = self.get_buy_signal_indicators(dataframe, metadata) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/freqtrade/user_data/strategies/MacheteV8b.py", line 303, in get_buy_signal_indicators dataframe = PMAX(dataframe, period=10, multiplier=3, length=10, MAtype=9, src=2) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/ftuser/.local/lib/python3.11/site-packages/technical/indicators/indicators.py", line 1159, in PMAX df["basic_ub"] = df[mavalue] + (multiplier * df[atr]) ~~^^^^^^^^^ File "/home/ftuser/.local/lib/python3.11/site-packages/pandas/core/frame.py", line 3893, in __getitem__ indexer = self.columns.get_loc(key) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/ftuser/.local/lib/python3.11/site-packages/pandas/core/indexes/base.py", line 3798, in get_loc raise KeyError(key) from err KeyError: 'MA_9_10'

Dan

uncomment the following from you compose build: context: . dockerfile: "./Dockerfile.custom" Create the docker file.custom and add: FROM freqtradeorg/freqtrade:stable USER ftuser RUN pip install finta Then run below command to have it install finite docker compose build --pull

Damion Davy

Facing the same issue as @Dan

Dutch Algotrading

That was a mistake from my side. I planned the video for tonight but somehow I forgot to set the same 'premiere time' for the post. It all works now.

Dan

same folder as docker-compose or add the folder to "./*folder*/Dockerfile.custom"

Dan

I happens for every crypto. that just happens to be the one I copied

Dan

I removed everything except BTC/USDT and there was no error. but after waiting a while, the chart wouldn't not show any candles. I then added all the pair back to the whitelist (same as your backtests) and still no error and no candles. If I delete the database file, and run again and no errors and no candle data. not really sure what's going on. I changed the strategy in docker-compose to SampleStrategy and I get candle data but nothing with MacheteV8b. I don't understand how removing all pairs except BTC got rid of the error as it is now running with all pairs it previously had and new database file with no errors but no candle data. Freqtrade log only shows up to 2024-01-21 20:15:35 - freqtrade.configuration.configuration - INFO - Using pairlist from configuration.

Leif Kasüschke

I think I have discovered the error. The strategy uses the PMAX method from the Freqtrade 'technical.indicators' library. This has been updated and no longer offers the mode used by the strategy (https://github.com/freqtrade/technical/blob/main/technical/indicators/indicators.py). In line 303 of the strategy, the mode is set to 9 (dataframe = PMAX(dataframe, period=10, multiplier=3, length=10, MAtype=9, src=2). However, only an MAtype from 1 to 8 can be set. I tentatively set the mode to TEMA (6) and it worked. Additionally, the last number in line 542 has to be changed from 9 to, for example, 6. ((qtpylib.crossed_above(dataframe['ZLEMA'], dataframe['pm_10_3_10_6']))

Dan

That worked for me. I may try later in the week to pull an older version of Freqtrade and test to see the difference in outcome

GrantandSarah

Do you include fees in your backtesting config? On these strategies with a lot of trades at a low average ROI the fee could make a huge difference.

Koprix

Hey guys, try this: dataframe['ZLEMA'] = tema(dataframe, period=10) ->dataframe['MA_9_10'] = dataframe['close'].rolling(window=10).mean() dataframe = PMAX(dataframe, period=10, multiplier=3, length=10, MAtype=9, src=2) @Dutch Algotrading did you use it like that? Tks

Fernando Zamudio Quintero

Hello. How can I get an older version of freqtrade, since the strategy file has ‘old’ elements like use_sell_signal, sell_profit_only, populate_buy_trend, populate_sell_trend, etc.?

Koprix

did you install the lib bellow? pip install git+https://github.com/freqtrade/technical did you replace zema with dema? i think after that should work, for spot or futures i did add leverage too to test :). plus you need to change all the old typos on the config for the new syntax for the newer version on freqtrader.

Mitja Kukovec

Please share your config.json with us as a reference for configuration.

Dutch Algotrading

For the record. I'm still using FT 2023.7 instead of the newest version. Also I have an installed version and no Docker. That could also be the difference between a working version and the troubles you unfortunately have.

Dutch Algotrading

From my head: Download the FT repository, do a 'git tag' to see all major versions, then do 'git checkout [verson]'. And you have the older FT release.

Mahmut Polat

Hello everyone, I am getting the following error."freqtrade impossible to load strategy MacheteV8bThis class does not exist or contains Python ... The file location is correct, other strategies work the same way, but this strategy gives an error. Does anyone know the reason?

Koprix

what are you running when starting the bot? freqtrade trade --config path/to/config.json --strategy-path path/to/strategyfolder --strategy strategyname

Mitja Kukovec

I am one of your Patrons, and I must be missing something obvious. The attached file 2024.02.MacheteV8b.7z does not contain the config.json file.

Koprix

Be aware this code have leverage added by me.

Kha Trương Ngọc

I'm not sure if there's anything wrong. I tested your code, and there were no entries entered for 1500 days of backtesting.

Koprix

strange for me works, maybe it's the config file the "options" you have.....

Dutch Algotrading

Fee is automatically calculated. Thats why it is not possible to test without an internet connection (it fetches current fees)

Kha Trương Ngọc

Can you share your config? My current config works well with other strategies, but I'm not sure why it's not working with this one.

Jason Chan

Hello, any ideas on how to combine ML model such as Transformer and LSTM with this stratedgy

DeJohn Franklin

ok how to get this strategy to work. The finta module won't load

Dutch Algotrading

Do you use Docker or Installed ? Docker does not contain the finta image. See also comments above for tips how to solve this.

Dutch Algotrading

I ran it straight out of the box without problems (except turning buy into entry etc.). However I still use 2023.7 and installed base (no Docker)

Jason Chan

No worries at all. How about using PCA to reduce the dimensions of features, and using more powerful GPUs like A100 ? In your opinion, will they improve the performance of this strategy?

Koprix

i will try that, i know some codes have don't have updated index, and needs to be tune. but tks ^^

Koprix

i would say it's normal, i keep it simple because i want for the strategy to be use, and since config file takes priority when testing, that's why i try to keep it clean. but i will create a new container and try what Dutch Algotrading said "2023.7 and installed base (no Docker)". I don't use docker, is on the container on proxmox.

Niclas Thies

For me its working. Solution: You need to make your own docker image that has finta installed. Luckily you can build on top of the standard freqtrade docker image. First make a Dockerfile with these two lines in it FROM freqtradeorg/freqtrade:stable RUN pip install finta Then build the image (calling the new image myfreqtrade) by running the command docker build -t myfreqtrade Finally change the docker-compose.yml file to run your image by changing the line image: freqtradeorg/freqtrade:stable to image: myfreqtrade And that should be that. Source: https://stackoverflow.com/questions/68002640/how-to-install-a-python-module-in-a-docker-container

Business Proposal

I had the same problem. The strategy file must be in the folder user_data/strategies/ OR You have to specify the strategy folder when you run freqtrade from the command line like this: freqtrade trade --strategy-path path/to/strategyfolder --strategy MacheteV8b

Dutch Algotrading

And in addition I will make a video on this whole process so to visualise these steps. Seems this is a subject that many can benefit from. Hopefully in the next couple of days.

Mitja Kukovec

I can confirm that FT version 2023.7, using Docker, runs this strategy without a problem.

Mitja Kukovec

I can confirm that FT version 2023.7, using Docker, runs this strategy without a problem.

Mitja Kukovec

I can confirm that FT version 2023.7, using Docker, runs this strategy without a problem.

Mitja Kukovec

I can confirm that FT version 2023.7, using Docker, runs this strategy without a problem.

Mahmut Polat

I tried everything but I couldn't solve the Finta problem. Can anyone who solved it help me?

Alex

Are you guys getting any good results from this strategy when running it for last year? It looks pretty disappointing to me

Michael

I fixed the finta issue, etc.. but now I'm getting this for all my 50 staticpaires : freqtrade.strategy.interface - WARNING - Empty candle (OHLCV) data for pairs!

Michael

Any ideas?

Dutch Algotrading

Maybe you can add a print(dataframe) in the indicators or buy/sell methods. THis way you can see if there is a dataframe created with the information. Otherwise try other pairs or longer datasets. THis error usually means that some indicator data is missing due to nog enough backtesting data. Hope this helps.

Michael

Thank you D€D

frederic auricombe

Hello, I've tried to make a backtest but get trouble in strategy code with 'zema' deprecated asking me to replace it by 'dema' and even with this update I've got an ERROR - Fatal exception! KeyError: MA_9_10... I supposed it's about Moving Average.

Nikos

Hi Frederic, i run docker on macOS Sonoma M2 and I have the same issues. If i come up with something i'll get back to you.

Nikos

It seems that the "PMAX" indicator is not working properly. I used the code below but now i get similar errors for "tema". I'm not a developer so the below might be misleading: def PMAX(dataframe, period = 10, multiplier = 3, length=12, MAtype=1, src=1): """ Function to compute PMAX Args : df : Pandas DataFrame which contains ['date', 'open', 'high', 'low', 'close', 'volume'] columns period : Integer indicates the period of computation in terms of number of candles multiplier : Integer indicates value to multiply the ATR length: moving averages length MAtype: type of the moving average Returns : df : Pandas DataFrame with new columns added for True Range (TR), ATR (ATR_$period) PMAX (pm_$period_$multiplier_$length_$Matypeint) PMAX Direction (pmX_$period_$multiplier_$length_$Matypeint) """ df = dataframe.copy() mavalue = 'MA_' + str(MAtype) + '_' + str(length) atr = 'ATR_' + str(period) df[atr]=ta.ATR(df , timeperiod = period) pm = 'pm_' + str(period) + '_' + str(multiplier) + '_' + str(length) + '_' + str(MAtype) pmx = 'pmX_' + str(period) + '_' + str(multiplier) + '_' + str(length) + '_' + str(MAtype) # MAtype==1 --> EMA # MAtype==2 --> DEMA # MAtype==3 --> T3 # MAtype==4 --> SMA # MAtype==5 --> VIDYA # MAtype==6 --> TEMA # MAtype==7 --> WMA # MAtype==8 --> VWMA # MAtype==9 --> zema if src == 1: masrc=df["close"] elif src == 2: masrc = (df["high"] + df["low"]) / 2 elif src == 3: masrc = (df["high"] + df["low"]+ df["close"] + df["open"]) / 4 if MAtype==1: df[mavalue]= ta.EMA(masrc , timeperiod = length) elif MAtype==2: df[mavalue]= ta.DEMA(masrc , timeperiod = length) elif MAtype==3: df[mavalue]= ta.T3(masrc , timeperiod = length) elif MAtype==4: df[mavalue]= ta.SMA(masrc , timeperiod = length) elif MAtype==5: df[mavalue]= VIDYA(df , length= length) elif MAtype==6: df[mavalue]= ta.TEMA(masrc , timeperiod = length) elif MAtype==7: df[mavalue]= ta.WMA(df , timeperiod = length) elif MAtype==8: df[mavalue]= vwma(df , length) elif MAtype==9: df[mavalue]= dema(df , period=length) # Compute basic upper and lower bands df['basic_ub'] = df[mavalue] + (multiplier * df[atr]) df['basic_lb'] = df[mavalue] - (multiplier * df[atr]) # Compute final upper and lower bands df['final_ub'] = 0.00 df['final_lb'] = 0.00 for i in range(period, len(df)): df['final_ub'].iat[i] = df['basic_ub'].iat[i] if df['basic_ub'].iat[i] < df['final_ub'].iat[i - 1] or df[mavalue].iat[i - 1] > df['final_ub'].iat[i - 1] else df['final_ub'].iat[i - 1] df['final_lb'].iat[i] = df['basic_lb'].iat[i] if df['basic_lb'].iat[i] > df['final_lb'].iat[i - 1] or df[mavalue].iat[i - 1] < df['final_lb'].iat[i - 1] else df['final_lb'].iat[i - 1] # Set the Pmax value df[pm] = 0.00 for i in range(period, len(df)): df[pm].iat[i] = df['final_ub'].iat[i] if df[pm].iat[i - 1] == df['final_ub'].iat[i - 1] and df[mavalue].iat[i] <= df['final_ub'].iat[i] else \ df['final_lb'].iat[i] if df[pm].iat[i - 1] == df['final_ub'].iat[i - 1] and df[mavalue].iat[i] > df['final_ub'].iat[i] else \ df['final_lb'].iat[i] if df[pm].iat[i - 1] == df['final_lb'].iat[i - 1] and df[mavalue].iat[i] >= df['final_lb'].iat[i] else \ df['final_ub'].iat[i] if df[pm].iat[i - 1] == df['final_lb'].iat[i - 1] and df[mavalue].iat[i] < df['final_lb'].iat[i] else 0.00 # Mark the trend direction up/down df[pmx] = np.where((df[pm] > 0.00), np.where((df[mavalue] < df[pm]), 'down', 'up'), np.NaN) # Remove basic and final bands from the columns df.drop(['basic_ub', 'basic_lb', 'final_ub', 'final_lb'], inplace=True, axis=1) df.fillna(0, inplace=True) return PMAX

frederic auricombe

Hi Nikos, Thanks for your tries. It works if you downgrade to version 2023.7 as mention on the last post about compatibility problem with some platform using strategy MacheteV8b. You need also to reload your dataset because it seems the format has also changed between. I'll will try with your PMAX function but it's hard to reverse Engineering a code you didn't write. I wondering if the compatibility is related to the OS platform like Sonoma/M2 whatever you are using docker like me or python directly or if it only related only to docker level?

frederic auricombe

After debug, it's come from dema() which certainly not return the same number of columns than zema(). you've just to add a dummy line like bellow and it works but I don't know if the logics remain accurate ;-).. # get_buy_signal_pmax dataframe['ZLEMA'] = dema(dataframe, period=10) dataframe['MA_9_10'] = dema(dataframe, period=10) dataframe = PMAX(dataframe, period=10, multiplier=3, length=10, MAtype=9, src=2)

Nikos

First of all, It worked! Thanks a lot for your response Frederic! Hm.. regarding the logic we need to better look into it!

Tal Zion

Hi guys, tried to run it but got this error. Using macOS and running the script of the FreqTrade repo Any help is highly appreciated. ``` Traceback (most recent call last): File "freqtrade/freqtrade/strategy/strategy_wrapper.py", line 27, in wrapper return f(*args, **kwargs) File "freqtrade/freqtrade/strategy/interface.py", line 873, in _analyze_ticker_internal dataframe = self.analyze_ticker(dataframe, metadata) File "freqtrade/freqtrade/strategy/interface.py", line 851, in analyze_ticker dataframe = self.advise_indicators(dataframe, metadata) File "freqtrade/freqtrade/strategy/interface.py", line 1378, in advise_indicators return self.populate_indicators(dataframe, metadata) File "freqtrade/user_data/strategies/MacheteV8b.py", line 202, in populate_indicators dataframe = self.get_buy_signal_indicators(dataframe, metadata) File "freqtrade/user_data/strategies/MacheteV8b.py", line 303, in get_buy_signal_indicators dataframe = PMAX(dataframe, period=10, multiplier=3, length=10, MAtype=9, src=2) File "freqtrade/.venv/lib/python3.10/site-packages/technical/indicators/indicators.py", line 1159, in PMAX df["basic_ub"] = df[mavalue] + (multiplier * df[atr]) File "freqtrade/.venv/lib/python3.10/site-packages/pandas/core/frame.py", line 3893, in __getitem__ indexer = self.columns.get_loc(key) File "freqtrade/.venv/lib/python3.10/site-packages/pandas/core/indexes/base.py", line 3798, in get_loc raise KeyError(key) from err KeyError: 'MA_9_10' freqtrade.strategy.interface - WARNING - Unable to analyze candle (OHLCV) data for pair DOGE/USDT: 'MA_9_10' ```

frederic auricombe

Hello, After debug the 3 top strategies on last freqtrade version 2024.01. here are the modifications that make it works and remove also warning messages for futur compatibility... Here are the diff command between old-new working file. I can provide source file but I don't know how to make an attachment in this thread?

frederic auricombe

diff MacheteV8b.py.org MacheteV8b.py 13c13 < from technical.indicators import PMAX, zema --- > from technical.indicators import PMAX, dema 151,152c150,151 < 'buy': 'limit', < 'sell': 'limit', --- > 'entry': 'limit', > 'exit': 'limit', 302,303c301,302 < dataframe['ZLEMA'] = zema(dataframe, period=10) < dataframe = PMAX(dataframe, period=10, multiplier=3, length=10, MAtype=9, src=2) --- > dataframe['DEMA'] = dema(dataframe, period=10) > dataframe = PMAX(dataframe, period=10, multiplier=3, length=10, MAtype=2, src=2) 381,383c380,382 < dataframe['future_green'] = ichimoku['cloud_green'].shift(displacement).fillna(0).astype('int') * 2 < dataframe['chikou_high'] = ((dataframe['chikou_span'] > dataframe['senkou_a']) & (dataframe['chikou_span'] > dataframe['senkou_b'])).shift(displacement).fillna(0).astype('int') < dataframe['go_long'] = ((dataframe['tenkan_sen'] > dataframe['kijun_sen']) & (dataframe['close'] > dataframe['leading_senkou_span_a']) & (dataframe['close'] > dataframe['leading_senkou_span_b']) & (dataframe['future_green'] > 0) & (dataframe['chikou_high'] > 0)).fillna(0).astype('int') * 3 --- > dataframe['future_green'] = ichimoku['cloud_green'].shift(displacement).replace(np.nan,0).astype('int') * 2 > dataframe['chikou_high'] = ((dataframe['chikou_span'] > dataframe['senkou_a']) & (dataframe['chikou_span'] > dataframe['senkou_b'])).shift(displacement).replace(np.nan,0).astype('int') > dataframe['go_long'] = ((dataframe['tenkan_sen'] > dataframe['kijun_sen']) & (dataframe['close'] > dataframe['leading_senkou_span_a']) & (dataframe['close'] > dataframe['leading_senkou_span_b']) & (dataframe['future_green'] > 0) & (dataframe['chikou_high'] > 0)).replace(np.nan,0).astype('int') * 3 542c541 < (qtpylib.crossed_above(dataframe['ZLEMA'], dataframe['pm_10_3_10_9'])) --- > (qtpylib.crossed_above(dataframe['DEMA'], dataframe['pm_10_3_10_2'])) 789c788 < df.fillna(0, inplace=True) --- > df.replace(np.nan,0)

frederic auricombe

diff Obelisk_Ichimoku_ZEMA_v1.py.org Obelisk_Ichimoku_ZEMA_v1.py

frederic auricombe

diff Obelisk_Ichimoku_ZEMA_v1.py.org Obelisk_Ichimoku_ZEMA_v1.py 73,74c86,87 < zema_len_buy = IntParameter(30, 90, default=72, space='buy', optimize=True) < zema_len_sell = IntParameter(30, 90, default=51, space='sell', optimize=True) --- > dema_len_buy = IntParameter(30, 90, default=72, space='buy', optimize=True) > dema_len_sell = IntParameter(30, 90, default=51, space='sell', optimize=True) 119c132 < ).shift(displacement).fillna(0).astype('int') --- > ).shift(displacement).replace(np.nan,0).astype('int') 123c136 < ).shift(displacement).fillna(0).astype('int') --- > ).shift(displacement).replace(np.nan,0).astype('int') 179c192 < dataframe['trending'].fillna(method='ffill', inplace=True) --- > dataframe['trending'].ffill() 183c196 < dataframe['bear_trending'].fillna(method='ffill', inplace=True) --- > dataframe['bear_trending'].ffill() 190c203 < dataframe[f'zema_{len}'] = ftt.zema(dataframe, period=len) --- > dataframe[f'dema_{len}'] = ftt.dema(dataframe, period=len) 192,195c205,208 < dataframe[f'zema_{self.zema_len_buy.value}'] = ftt.zema(dataframe, period=self.zema_len_buy.value) < dataframe[f'zema_{self.zema_len_sell.value}'] = ftt.zema(dataframe, period=self.zema_len_sell.value) < dataframe[f'zema_buy'] = ftt.zema(dataframe, period=self.zema_len_buy.value) * self.low_offset.value < dataframe[f'zema_sell'] = ftt.zema(dataframe, period=self.zema_len_sell.value) * self.high_offset.value --- > dataframe[f'dema_{self.dema_len_buy.value}'] = ftt.dema(dataframe, period=self.dema_len_buy.value) > dataframe[f'dema_{self.dema_len_sell.value}'] = ftt.dema(dataframe, period=self.dema_len_sell.value) > dataframe[f'dema_buy'] = ftt.dema(dataframe, period=self.dema_len_buy.value) * self.low_offset.value > dataframe[f'dema_sell'] = ftt.dema(dataframe, period=self.dema_len_sell.value) * self.high_offset.value 222c235 < zema = f'zema_{self.zema_len_buy.value}' --- > dema = f'dema_{self.dema_len_buy.value}' 227c240 < & (dataframe['close'] < (dataframe[zema] * self.low_offset.value)) --- > & (dataframe['close'] < (dataframe[dema] * self.low_offset.value)) 232c245 < zema = f'zema_{self.zema_len_sell.value}' --- > dema = f'dema_{self.dema_len_sell.value}' 236c249 < (dataframe['close'] > (dataframe[zema] * self.high_offset.value)) --- > (dataframe['close'] > (dataframe[dema] * self.high_offset.value)) 281,282c294,295 < 'zema_buy': { 'color': 'blue' }, < 'zema_sell': { 'color': 'orange' }, --- > 'dema_buy': { 'color': 'blue' }, > 'dema_sell': { 'color': 'orange' },

frederic auricombe

diff SMAOffsetProtectOptV1.py.org SMAOffsetProtectOptV1.py 125c125 < ignore_roi_if_buy_signal = True --- > ignore_roi_if_entry_signal = True 128c128 < timeframe = '5m' --- > timeframe = '30m' 175c175 < def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: --- > def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 203c203 < def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: --- > def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:

frederic auricombe

I could perhaps post updated files on Telegram or Discord group? What is efficient way ?

frederic auricombe

Got 117% profit with MacheteV8b on the last 1 year period data with 30 pairs and 83% profit with Obelisk_Ichimoku_ZEMA_v1.py on ... with hyperopt runs before. hth

Dutch Algotrading

I can also post the updated file to the post so that everything sticks together and all have one frame of reference.

frederic auricombe

## MacheteV8b.py with fix for docker freqtrade 2024.01 from typing import Dict, List, Optional, Tuple from datetime import datetime, timedelta from cachetools import TTLCache from pandas import DataFrame, Series import numpy as np ## Indicator libs import talib.abstract as ta from finta import TA as fta import technical.indicators as ftt from technical.indicators import hull_moving_average from technical.indicators import PMAX, dema from technical.indicators import cmf ## FT stuffs from freqtrade.strategy import IStrategy, merge_informative_pair, stoploss_from_open, IntParameter, DecimalParameter, CategoricalParameter import freqtrade.vendor.qtpylib.indicators as qtpylib from freqtrade.exchange import timeframe_to_minutes from freqtrade.persistence import Trade from skopt.space import Dimension """ NOTE: docker-compose run --rm freqtrade hyperopt -c user_data/config-backtesting.json --strategy IchimokuHaulingV8a --hyperopt-loss SortinoHyperOptLossDaily --spaces roi buy sell --timerange=1624940400-1630447200 -j 4 -e 1000 """ class MacheteV8b(IStrategy): # Buy hyperspace params: buy_params = { "buy_should_use_get_buy_signal_adx_momentum": False, # value loaded from strategy "buy_should_use_get_buy_signal_adx_smas": True, # value loaded from strategy "buy_should_use_get_buy_signal_asdts_rockwelltrading": False, # value loaded from strategy "buy_should_use_get_buy_signal_averages_strategy": False, # value loaded from strategy "buy_should_use_get_buy_signal_awesome_macd": True, # value loaded from strategy "buy_should_use_get_buy_signal_fisher_hull": False, # value loaded from strategy "buy_should_use_get_buy_signal_gettin_moist": True, # value loaded from strategy "buy_should_use_get_buy_signal_hlhb": True, # value loaded from strategy "buy_should_use_get_buy_signal_macd_strategy": False, # value loaded from strategy "buy_should_use_get_buy_signal_macd_strategy_crossed": False, # value loaded from strategy "buy_should_use_get_buy_signal_pmax": False, # value loaded from strategy "buy_should_use_get_buy_signal_quickie": True, # value loaded from strategy "buy_should_use_get_buy_signal_scalp": True, # value loaded from strategy "buy_should_use_get_buy_signal_simple": False, # value loaded from strategy "buy_should_use_get_buy_signal_strategy001": False, # value loaded from strategy "buy_should_use_get_buy_signal_technical_example_strategy": False, # value loaded from strategy "buy_should_use_get_buy_signal_tema_rsi_strategy": False, # value loaded from strategy } # Sell hyperspace params: sell_params = { "cstp_bail_how": "roc", # value loaded from strategy "cstp_bail_roc": -0.032, # value loaded from strategy "cstp_bail_time": 1108, # value loaded from strategy "cstp_bb_trailing_input": "bb_lowerband_neutral_inf", # value loaded from strategy "cstp_threshold": -0.036, # value loaded from strategy "cstp_trailing_max_stoploss": 0.054, # value loaded from strategy "cstp_trailing_only_offset_is_reached": 0.06, # value loaded from strategy "cstp_trailing_stop_profit_devider": 2, # value loaded from strategy "droi_pullback": True, # value loaded from strategy "droi_pullback_amount": 0.005, # value loaded from strategy "droi_pullback_respect_table": False, # value loaded from strategy "droi_trend_type": "any", # value loaded from strategy } # ROI table: minimal_roi = { "0": 0.238, "99": 0.132, "265": 0.029, "559": 0 } # Stoploss: stoploss = -0.315 # Trailing stop: trailing_stop = True trailing_stop_positive = 0.192 trailing_stop_positive_offset = 0.209 trailing_only_offset_is_reached = True # Max Open Trades: max_open_trades = 10 # value loaded from strategy # buy signal buy_should_use_get_buy_signal_awesome_macd = CategoricalParameter([True, False], default=buy_params['buy_should_use_get_buy_signal_awesome_macd'], space='buy', optimize=True) buy_should_use_get_buy_signal_adx_momentum = CategoricalParameter([True, False], default=buy_params['buy_should_use_get_buy_signal_adx_momentum'], space='buy', optimize=True) buy_should_use_get_buy_signal_adx_smas = CategoricalParameter([True, False], default=buy_params['buy_should_use_get_buy_signal_adx_smas'], space='buy', optimize=True) buy_should_use_get_buy_signal_asdts_rockwelltrading = CategoricalParameter([True, False], default=buy_params['buy_should_use_get_buy_signal_asdts_rockwelltrading'], space='buy', optimize=True) buy_should_use_get_buy_signal_averages_strategy = CategoricalParameter([True, False], default=buy_params['buy_should_use_get_buy_signal_averages_strategy'], space='buy', optimize=True) buy_should_use_get_buy_signal_fisher_hull = CategoricalParameter([True, False], default=buy_params['buy_should_use_get_buy_signal_fisher_hull'], space='buy', optimize=True) buy_should_use_get_buy_signal_gettin_moist = CategoricalParameter([True, False], default=buy_params['buy_should_use_get_buy_signal_gettin_moist'], space='buy', optimize=True) buy_should_use_get_buy_signal_hlhb = CategoricalParameter([True, False], default=buy_params['buy_should_use_get_buy_signal_hlhb'], space='buy', optimize=True) buy_should_use_get_buy_signal_macd_strategy_crossed = CategoricalParameter([True, False], default=buy_params['buy_should_use_get_buy_signal_macd_strategy_crossed'], space='buy', optimize=True) buy_should_use_get_buy_signal_macd_strategy = CategoricalParameter([True, False], default=buy_params['buy_should_use_get_buy_signal_macd_strategy'], space='buy', optimize=True) buy_should_use_get_buy_signal_pmax = CategoricalParameter([True, False], default=buy_params['buy_should_use_get_buy_signal_pmax'], space='buy', optimize=True) buy_should_use_get_buy_signal_quickie = CategoricalParameter([True, False], default=buy_params['buy_should_use_get_buy_signal_quickie'], space='buy', optimize=True) buy_should_use_get_buy_signal_scalp = CategoricalParameter([True, False], default=buy_params['buy_should_use_get_buy_signal_scalp'], space='buy', optimize=True) buy_should_use_get_buy_signal_simple = CategoricalParameter([True, False], default=buy_params['buy_should_use_get_buy_signal_simple'], space='buy', optimize=True) buy_should_use_get_buy_signal_strategy001 = CategoricalParameter([True, False], default=buy_params['buy_should_use_get_buy_signal_strategy001'], space='buy', optimize=True) buy_should_use_get_buy_signal_technical_example_strategy = CategoricalParameter([True, False], default=buy_params['buy_should_use_get_buy_signal_technical_example_strategy'], space='buy', optimize=True) buy_should_use_get_buy_signal_tema_rsi_strategy = CategoricalParameter([True, False], default=buy_params['buy_should_use_get_buy_signal_tema_rsi_strategy'], space='buy', optimize=True) # Dynamic ROI droi_trend_type = CategoricalParameter(['rmi', 'ssl', 'candle', 'any'], default=sell_params['droi_trend_type'], space='sell', optimize=True) droi_pullback = CategoricalParameter([True, False], default=sell_params['droi_pullback'], space='sell', optimize=True) droi_pullback_amount = DecimalParameter(0.005, 0.02, default=sell_params['droi_pullback_amount'], space='sell') droi_pullback_respect_table = CategoricalParameter([True, False], default=sell_params['droi_pullback_respect_table'], space='sell', optimize=True) # Custom Stoploss cstp_threshold = DecimalParameter(-0.05, 0, default=sell_params['cstp_threshold'], space='sell') cstp_bail_how = CategoricalParameter(['roc', 'time', 'any'], default=sell_params['cstp_bail_how'], space='sell', optimize=True) cstp_bail_roc = DecimalParameter(-0.05, -0.01, default=sell_params['cstp_bail_roc'], space='sell') cstp_bail_time = IntParameter(720, 1440, default=sell_params['cstp_bail_time'], space='sell') cstp_trailing_only_offset_is_reached = DecimalParameter(0.01, 0.06, default=sell_params['cstp_trailing_only_offset_is_reached'], space='sell') cstp_trailing_stop_profit_devider = IntParameter(2, 4, default=sell_params['cstp_trailing_stop_profit_devider'], space='sell') cstp_trailing_max_stoploss = DecimalParameter(0.02, 0.08, default=sell_params['cstp_trailing_max_stoploss'], space='sell') cstp_bb_trailing_input = CategoricalParameter(['bb_lowerband_trend', 'bb_lowerband_trend_inf', 'bb_lowerband_neutral', 'bb_lowerband_neutral_inf', 'bb_upperband_neutral_inf'], default=sell_params['cstp_bb_trailing_input'], space='sell', optimize=True) # nested hyperopt class class HyperOpt: # defining as dummy, so that no error is thrown about missing # sell indicator space when hyperopting for all spaces @staticmethod def indicator_space() -> List[Dimension]: return [] custom_trade_info = {} custom_current_price_cache: TTLCache = TTLCache(maxsize=100, ttl=300) # 5 minutes # run "populate_indicators" only for new candle process_only_new_candles = False # Experimental settings (configuration will overide these if set) use_sell_signal = True sell_profit_only = False ignore_roi_if_buy_signal = False startup_candle_count = 500#149 use_dynamic_roi = True timeframe = '15m' informative_timeframe = '1h' # Optional order type mapping order_types = { 'entry': 'limit', 'exit': 'limit', 'stoploss': 'market', 'stoploss_on_exchange': False } plot_config = { 'main_plot': { 'chikou_span_inf': {'color': 'green'}, 'tenkan_sen_inf': {'color': 'blue'}, 'kijun_sen_inf': {'color': 'red'}, 'senkou_a_inf': { 'color': 'green', 'fill_to': 'senkou_b', 'fill_label': 'Kumo', 'fill_color': 'rgba(51, 255, 117, 0.2)', }, 'senkou_b_inf': {'color': 'red'}, 'leading_senkou_span_a_inf': {'color': 'green'}, 'leading_senkou_span_b_inf': {'color': 'red'}, 'sslUp_inf': {'color': 'green'}, 'sslDown_inf': {'color': 'red'} }, 'subplots': { 'summary': { 'cloud_green_inf': {}, 'cloud_red_inf': {}, 'future_green_inf': {}, 'chikou_high_inf': {}, 'go_long_inf': {} } } } def informative_pairs(self): pairs = self.dp.current_whitelist() informative_pairs = [(pair, self.informative_timeframe) for pair in pairs] return informative_pairs # # Processing indicators # def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: self.custom_trade_info[metadata['pair']] = self.populate_trades(metadata['pair']) if not self.dp: return dataframe dataframe = self.get_buy_signal_indicators(dataframe, metadata) informative_tmp = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.informative_timeframe) informative = self.get_market_condition_indicators(informative_tmp.copy(), metadata) informative = self.get_custom_stoploss_indicators(informative, metadata) dataframe = merge_informative_pair(dataframe, informative, self.timeframe, self.informative_timeframe, ffill=True) dataframe.rename(columns=lambda s: s.replace("_{}".format(self.informative_timeframe), "_inf"), inplace=True) # Slam some indicators into the trade_info dict so we can dynamic roi and custom stoploss in backtest if self.dp.runmode.value in ('backtest', 'hyperopt'): self.custom_trade_info[metadata['pair']]['roc_inf'] = dataframe[['date', 'roc_inf']].copy().set_index('date') self.custom_trade_info[metadata['pair']]['atr_inf'] = dataframe[['date', 'atr_inf']].copy().set_index('date') self.custom_trade_info[metadata['pair']]['sroc_inf'] = dataframe[['date', 'sroc_inf']].copy().set_index('date') self.custom_trade_info[metadata['pair']]['ssl-dir_inf'] = dataframe[['date', 'ssl-dir_inf']].copy().set_index('date') self.custom_trade_info[metadata['pair']]['rmi-up-trend_inf'] = dataframe[['date', 'rmi-up-trend_inf']].copy().set_index('date') self.custom_trade_info[metadata['pair']]['candle-up-trend_inf'] = dataframe[['date', 'candle-up-trend_inf']].copy().set_index('date') self.custom_trade_info[metadata['pair']]['bb_lowerband_trend_inf'] = dataframe[['date', 'bb_lowerband_trend_inf']].copy().set_index('date') self.custom_trade_info[metadata['pair']]['bb_lowerband_trend_inf'] = dataframe[['date', 'bb_lowerband_trend_inf']].copy().set_index('date') self.custom_trade_info[metadata['pair']]['bb_lowerband_neutral_inf'] = dataframe[['date', 'bb_lowerband_neutral_inf']].copy().set_index('date') self.custom_trade_info[metadata['pair']]['bb_lowerband_neutral_inf'] = dataframe[['date', 'bb_lowerband_neutral_inf']].copy().set_index('date') self.custom_trade_info[metadata['pair']]['bb_upperband_neutral_inf'] = dataframe[['date', 'bb_upperband_neutral_inf']].copy().set_index('date') return dataframe def get_buy_signal_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: # get_buy_signal_awesome_macd dataframe['adx'] = ta.ADX(dataframe, timeperiod=14) dataframe['ao'] = qtpylib.awesome_oscillator(dataframe) macd = ta.MACD(dataframe) dataframe['macd'] = macd['macd'] dataframe['macdsignal'] = macd['macdsignal'] dataframe['macdhist'] = macd['macdhist'] # get_buy_signal_adx_momentum #dataframe['adx'] = ta.ADX(dataframe, timeperiod=14) dataframe['plus_di'] = ta.PLUS_DI(dataframe, timeperiod=25) dataframe['minus_di'] = ta.MINUS_DI(dataframe, timeperiod=25) dataframe['sar'] = ta.SAR(dataframe) dataframe['mom'] = ta.MOM(dataframe, timeperiod=14) # get_buy_signal_adx_smas #dataframe['adx'] = ta.ADX(dataframe, timeperiod=14) dataframe['short'] = ta.SMA(dataframe, timeperiod=3) dataframe['long'] = ta.SMA(dataframe, timeperiod=6) # get_buy_signal_asdts_rockwelltrading #macd = ta.MACD(dataframe) #dataframe['macd'] = macd['macd'] #dataframe['macdsignal'] = macd['macdsignal'] #dataframe['macdhist'] = macd['macdhist'] # get_buy_signal_averages_strategy dataframe['maShort'] = ta.EMA(dataframe, timeperiod=8) dataframe['maMedium'] = ta.EMA(dataframe, timeperiod=21) # get_buy_signal_fisher_hull dataframe['hma'] = hull_moving_average(dataframe, 14, 'close') dataframe['cci'] = ta.CCI(dataframe, timeperiod=14) dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14) rsi = 0.1 * (dataframe['rsi'] - 50) dataframe['fisher_rsi'] = (np.exp(2 * rsi) - 1) / (np.exp(2 * rsi) + 1) # get_buy_signal_gettin_moist dataframe['color'] = dataframe['close'] > dataframe['open'] #macd = ta.MACD(dataframe) #dataframe['macd'] = macd['macd'] #dataframe['macdsignal'] = macd['macdsignal'] #dataframe['macdhist'] = macd['macdhist'] dataframe['rsi_7'] = ta.RSI(dataframe, timeperiod=7) dataframe['roc_6'] = ta.ROC(dataframe, timeperiod=6) dataframe['primed'] = np.where(dataframe['color'].rolling(3).sum() == 3,1,0) dataframe['in-the-mood'] = dataframe['rsi_7'] > dataframe['rsi_7'].rolling(12).mean() dataframe['moist'] = qtpylib.crossed_above(dataframe['macd'], dataframe['macdsignal']) dataframe['throbbing'] = dataframe['roc_6'] > dataframe['roc_6'].rolling(12).mean() dataframe['ready-to-go'] = np.where(dataframe['close'] > dataframe['open'].rolling(12).mean(), 1,0) # get_buy_signal_hlhb dataframe['hl2'] = (dataframe["close"] + dataframe["open"]) / 2 dataframe['rsi_10'] = ta.RSI(dataframe, timeperiod=10, price='hl2') dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5) dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10) #dataframe['adx'] = ta.ADX(dataframe) # get_buy_signal_macd_strategy_crossed #macd = ta.MACD(dataframe) #dataframe['macd'] = macd['macd'] #dataframe['macdsignal'] = macd['macdsignal'] #dataframe['macdhist'] = macd['macdhist'] #dataframe['cci'] = ta.CCI(dataframe) # get_buy_signal_macd_strategy #macd = ta.MACD(dataframe) #dataframe['macd'] = macd['macd'] #dataframe['macdsignal'] = macd['macdsignal'] #dataframe['macdhist'] = macd['macdhist'] #dataframe['cci'] = ta.CCI(dataframe) # get_buy_signal_pmax dataframe['DEMA'] = dema(dataframe, period=10) dataframe = PMAX(dataframe, period=10, multiplier=3, length=10, MAtype=2, src=2) # get_buy_signal_quickie #macd = ta.MACD(dataframe) #dataframe['macd'] = macd['macd'] #dataframe['macdsignal'] = macd['macdsignal'] #dataframe['macdhist'] = macd['macdhist'] dataframe['tema'] = ta.TEMA(dataframe, timeperiod=9) dataframe['sma_200'] = ta.SMA(dataframe, timeperiod=200) dataframe['sma_50'] = ta.SMA(dataframe, timeperiod=200) #dataframe['adx'] = ta.ADX(dataframe) bollinger = qtpylib.bollinger_bands(dataframe['close'], window=20, stds=2) dataframe['bb_lowerband'] = bollinger['lower'] dataframe['bb_middleband'] = bollinger['mid'] dataframe['bb_upperband'] = bollinger['upper'] # get_buy_signal_scalp dataframe['ema_high'] = ta.EMA(dataframe, timeperiod=5, price='high') dataframe['ema_close'] = ta.EMA(dataframe, timeperiod=5, price='close') dataframe['ema_low'] = ta.EMA(dataframe, timeperiod=5, price='low') stoch_fast = ta.STOCHF(dataframe, 5, 3, 0, 3, 0) dataframe['fastd'] = stoch_fast['fastd'] dataframe['fastk'] = stoch_fast['fastk'] #dataframe['adx'] = ta.ADX(dataframe) # get_buy_signal_simple #macd = ta.MACD(dataframe) #dataframe['macd'] = macd['macd'] #dataframe['macdsignal'] = macd['macdsignal'] #dataframe['macdhist'] = macd['macdhist'] #dataframe['rsi_7'] = ta.RSI(dataframe, timeperiod=7) #bollinger = qtpylib.bollinger_bands(dataframe['close'], window=12, stds=2) #dataframe['bb_lowerband'] = bollinger['lower'] #dataframe['bb_upperband'] = bollinger['upper'] #dataframe['bb_middleband'] = bollinger['mid'] # get_buy_signal_strategy001 dataframe['ema20'] = ta.EMA(dataframe, timeperiod=20) dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50) dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100) heikinashi = qtpylib.heikinashi(dataframe) dataframe['ha_open'] = heikinashi['open'] dataframe['ha_close'] = heikinashi['close'] # get_buy_signal_technical_example_strategy dataframe['cmf'] = cmf(dataframe, 21) # get_buy_signal_tema_rsi_strategy #dataframe['rsi'] = ta.RSI(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['tema'] = ta.TEMA(dataframe, timeperiod=9) return dataframe def get_market_condition_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: displacement = 30 ichimoku = ftt.ichimoku(dataframe, conversion_line_period=20, base_line_periods=60, laggin_span=120, displacement=displacement) dataframe['chikou_span'] = ichimoku['chikou_span'] dataframe['tenkan_sen'] = ichimoku['tenkan_sen'] dataframe['kijun_sen'] = ichimoku['kijun_sen'] dataframe['senkou_a'] = ichimoku['senkou_span_a'] dataframe['senkou_b'] = ichimoku['senkou_span_b'] dataframe['leading_senkou_span_a'] = ichimoku['leading_senkou_span_a'] dataframe['leading_senkou_span_b'] = ichimoku['leading_senkou_span_b'] dataframe['cloud_green'] = ichimoku['cloud_green'] * 1 dataframe['cloud_red'] = ichimoku['cloud_red'] * -1 ssl = SSLChannels_ATR(dataframe, 10) dataframe['sslDown'] = ssl[0] dataframe['sslUp'] = ssl[1] #dataframe['vfi'] = fta.VFI(dataframe, period=14) # Summary indicators dataframe['future_green'] = ichimoku['cloud_green'].shift(displacement).replace(np.nan,0).astype('int') * 2 dataframe['chikou_high'] = ((dataframe['chikou_span'] > dataframe['senkou_a']) & (dataframe['chikou_span'] > dataframe['senkou_b'])).shift(displacement).replace(np.nan,0).astype('int') dataframe['go_long'] = ((dataframe['tenkan_sen'] > dataframe['kijun_sen']) & (dataframe['close'] > dataframe['leading_senkou_span_a']) & (dataframe['close'] > dataframe['leading_senkou_span_b']) & (dataframe['future_green'] > 0) & (dataframe['chikou_high'] > 0)).replace(np.nan,0).astype('int') * 3 dataframe['max'] = dataframe['high'].rolling(3).max() dataframe['min'] = dataframe['low'].rolling(6).min() dataframe['upper'] = np.where(dataframe['max'] > dataframe['max'].shift(),1,0) dataframe['lower'] = np.where(dataframe['min'] < dataframe['min'].shift(),1,0) dataframe['up_trend'] = np.where(dataframe['upper'].rolling(5, min_periods=1).sum() != 0,1,0) dataframe['dn_trend'] = np.where(dataframe['lower'].rolling(5, min_periods=1).sum() != 0,1,0) return dataframe def get_custom_stoploss_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: bollinger_neutral = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=1) dataframe['bb_lowerband_neutral'] = bollinger_neutral['lower'] dataframe['bb_middleband_neutral'] = bollinger_neutral['mid'] dataframe['bb_upperband_neutral'] = bollinger_neutral['upper'] bollinger_trend = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2) dataframe['bb_lowerband_trend'] = bollinger_trend['lower'] dataframe['bb_middleband_trend'] = bollinger_trend['mid'] dataframe['bb_upperband_trend'] = bollinger_trend['upper'] dataframe['atr'] = ta.ATR(dataframe, timeperiod=14) dataframe['roc'] = ta.ROC(dataframe, timeperiod=9) dataframe['rmi'] = RMI(dataframe, length=24, mom=5) ssldown, sslup = SSLChannels_ATR(dataframe, length=21) dataframe['sroc'] = SROC(dataframe, roclen=21, emalen=13, smooth=21) dataframe['ssl-dir'] = np.where(sslup > ssldown,'up','down') dataframe['rmi-up'] = np.where(dataframe['rmi'] >= dataframe['rmi'].shift(),1,0) dataframe['rmi-up-trend'] = np.where(dataframe['rmi-up'].rolling(5).sum() >= 3,1,0) dataframe['candle-up'] = np.where(dataframe['close'] >= dataframe['close'].shift(),1,0) dataframe['candle-up-trend'] = np.where(dataframe['candle-up'].rolling(5).sum() >= 3,1,0) return dataframe # # Processing buy signals # 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['DEMA'], dataframe['pm_10_3_10_2'])) ) 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 signal # # Processing sell signals # def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe.loc[ (qtpylib.crossed_above(dataframe['sslDown_inf'], dataframe['sslUp_inf'])) & ( (qtpylib.crossed_below(dataframe['tenkan_sen_inf'], dataframe['kijun_sen_inf'])) |(qtpylib.crossed_below(dataframe['close_inf'], dataframe['kijun_sen_inf'])) ) #& # 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) ,'sell'] = 1 return dataframe # # Custom Stoploss # def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, current_rate: float, current_profit: float, **kwargs) -> float: trade_dur = int((current_time.timestamp() - trade.open_date_utc.timestamp()) // 60) if self.config['runmode'].value in ('live', 'dry_run'): dataframe, last_updated = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe) sroc = dataframe['sroc_inf'].iat[-1] bb_trailing = dataframe[self.cstp_bb_trailing_input.value].iat[-1] # If in backtest or hyperopt, get the indicator values out of the trades dict (Thanks @JoeSchr!) else: sroc = self.custom_trade_info[trade.pair]['sroc_inf'].loc[current_time]['sroc_inf'] bb_trailing = self.custom_trade_info[trade.pair][self.cstp_bb_trailing_input.value].loc[current_time][self.cstp_bb_trailing_input.value] if current_profit < self.cstp_threshold.value: if self.cstp_bail_how.value == 'roc' or self.cstp_bail_how.value == 'any': # Dynamic bailout based on rate of change if (sroc/100) <= self.cstp_bail_roc.value: return 0.001 if self.cstp_bail_how.value == 'time' or self.cstp_bail_how.value == 'any': # Dynamic bailout based on time if trade_dur > self.cstp_bail_time.value: return 0.001 if current_profit < self.cstp_trailing_only_offset_is_reached.value: if current_rate <= bb_trailing: return 0.001 else: return -1 desired_stoploss = current_profit / self.cstp_trailing_stop_profit_devider.value return max(min(desired_stoploss, self.cstp_trailing_max_stoploss.value), 0.025) # # Dynamic ROI # def min_roi_reached_dynamic(self, trade: Trade, current_profit: float, current_time: datetime, trade_dur: int) -> Tuple[Optional[int], Optional[float]]: minimal_roi = self.minimal_roi _, table_roi = self.min_roi_reached_entry(trade_dur) # see if we have the data we need to do this, otherwise fall back to the standard table if self.custom_trade_info and trade and trade.pair in self.custom_trade_info: if self.config['runmode'].value in ('live', 'dry_run'): dataframe, last_updated = self.dp.get_analyzed_dataframe(pair=trade.pair, timeframe=self.timeframe) rmi_trend = dataframe['rmi-up-trend_inf'].iat[-1] candle_trend = dataframe['candle-up-trend_inf'].iat[-1] ssl_dir = dataframe['ssl-dir_inf'].iat[-1] # If in backtest or hyperopt, get the indicator values out of the trades dict (Thanks @JoeSchr!) else: rmi_trend = self.custom_trade_info[trade.pair]['rmi-up-trend_inf'].loc[current_time]['rmi-up-trend_inf'] candle_trend = self.custom_trade_info[trade.pair]['candle-up-trend_inf'].loc[current_time]['candle-up-trend_inf'] ssl_dir = self.custom_trade_info[trade.pair]['ssl-dir_inf'].loc[current_time]['ssl-dir_inf'] min_roi = table_roi max_profit = trade.calc_profit_ratio(trade.max_rate) pullback_value = (max_profit - self.droi_pullback_amount.value) in_trend = False if self.droi_trend_type.value == 'rmi' or self.droi_trend_type.value == 'any': if rmi_trend == 1: in_trend = True if self.droi_trend_type.value == 'ssl' or self.droi_trend_type.value == 'any': if ssl_dir == 'up': in_trend = True if self.droi_trend_type.value == 'candle' or self.droi_trend_type.value == 'any': if candle_trend == 1: in_trend = True # Force the ROI value high if in trend if (in_trend == True): min_roi = 100 # If pullback is enabled, allow to sell if a pullback from peak has happened regardless of trend if self.droi_pullback.value == True and (current_profit < pullback_value): if self.droi_pullback_respect_table.value == True: min_roi = table_roi else: min_roi = current_profit / 2 else: min_roi = table_roi return trade_dur, min_roi # Change here to allow loading of the dynamic_roi settings def min_roi_reached(self, trade: Trade, current_profit: float, current_time: datetime) -> bool: trade_dur = int((current_time.timestamp() - trade.open_date_utc.timestamp()) // 60) if self.use_dynamic_roi: _, roi = self.min_roi_reached_dynamic(trade, current_profit, current_time, trade_dur) else: _, roi = self.min_roi_reached_entry(trade_dur) if roi is None: return False else: return current_profit > roi # Get the current price from the exchange (or local cache) def get_current_price(self, pair: str, refresh: bool) -> float: if not refresh: rate = self.custom_current_price_cache.get(pair) # Check if cache has been invalidated if rate: return rate ask_strategy = self.config.get('ask_strategy', {}) if ask_strategy.get('use_order_book', False): ob = self.dp.orderbook(pair, 1) rate = ob[f"{ask_strategy['price_side']}s"][0][0] else: ticker = self.dp.ticker(pair) rate = ticker['last'] self.custom_current_price_cache[pair] = rate return rate # # Custom trade info # def populate_trades(self, pair: str) -> dict: # Initialize the trades dict if it doesn't exist, persist it otherwise if not pair in self.custom_trade_info: self.custom_trade_info[pair] = {} # init the temp dicts and set the trade stuff to false trade_data = {} trade_data['active_trade'] = False # active trade stuff only works in live and dry, not backtest if self.config['runmode'].value in ('live', 'dry_run'): # find out if we have an open trade for this pair active_trade = Trade.get_trades([Trade.pair == pair, Trade.is_open.is_(True),]).all() # if so, get some information if active_trade: # get current price and update the min/max rate current_rate = self.get_current_price(pair, True) active_trade[0].adjust_min_max_rates(current_rate) return trade_data # # Custom indicators # def RMI(dataframe, *, length=20, mom=5): """ Source: https://github.com/freqtrade/technical/blob/master/technical/indicators/indicators.py#L912 """ df = dataframe.copy() df['maxup'] = (df['close'] - df['close'].shift(mom)).clip(lower=0) df['maxdown'] = (df['close'].shift(mom) - df['close']).clip(lower=0) df.replace(np.nan,0) df["emaInc"] = ta.EMA(df, price='maxup', timeperiod=length) df["emaDec"] = ta.EMA(df, price='maxdown', timeperiod=length) df['RMI'] = np.where(df['emaDec'] == 0, 0, 100 - 100 / (1 + df["emaInc"] / df["emaDec"])) return df["RMI"] def SSLChannels_ATR(dataframe, length=7): """ SSL Channels with ATR: https://www.tradingview.com/script/SKHqWzql-SSL-ATR-channel/ Credit to @JimmyNixx for python """ df = dataframe.copy() df['ATR'] = ta.ATR(df, timeperiod=14) df['smaHigh'] = df['high'].rolling(length).mean() + df['ATR'] df['smaLow'] = df['low'].rolling(length).mean() - df['ATR'] df['hlv'] = np.where(df['close'] > df['smaHigh'], 1, np.where(df['close'] < df['smaLow'], -1, np.NAN)) df['hlv'] = df['hlv'].ffill() df['sslDown'] = np.where(df['hlv'] < 0, df['smaHigh'], df['smaLow']) df['sslUp'] = np.where(df['hlv'] < 0, df['smaLow'], df['smaHigh']) return df['sslDown'], df['sslUp'] def SROC(dataframe, roclen=21, emalen=13, smooth=21): df = dataframe.copy() roc = ta.ROC(df, timeperiod=roclen) ema = ta.EMA(df, timeperiod=emalen) sroc = ta.ROC(ema, timeperiod=smooth) return sroc

frederic auricombe

## Obelisk_Ichimoku_ZEMA_v1.py with fix for docker freqtrade 2024.01 # --- Do not remove these libs --- from freqtrade.strategy import IStrategy, merge_informative_pair, DecimalParameter, IntParameter from pandas import DataFrame import talib.abstract as ta import freqtrade.vendor.qtpylib.indicators as qtpylib # -------------------------------- import pandas as pd import numpy as np import technical.indicators as ftt from freqtrade.exchange import timeframe_to_minutes import logging logger = logging.getLogger(__name__) # Obelisk_Ichimoku_ZEMA v1 - 2021-05-20 # # EXPERIMENTAL # # RUN AT YOUR OWN RISK # # by Obelisk # https://github.com/brookmiles/ def ssl_atr(dataframe, length = 7): df = dataframe.copy() df['smaHigh'] = df['high'].rolling(length).mean() + df['atr'] df['smaLow'] = df['low'].rolling(length).mean() - df['atr'] df['hlv'] = np.where(df['close'] > df['smaHigh'], 1, np.where(df['close'] < df['smaLow'], -1, np.NAN)) df['hlv'] = df['hlv'].ffill() df['sslDown'] = np.where(df['hlv'] < 0, df['smaHigh'], df['smaLow']) df['sslUp'] = np.where(df['hlv'] < 0, df['smaLow'], df['smaHigh']) return df['sslDown'], df['sslUp'] class Obelisk_Ichimoku_ZEMA_v1(IStrategy): # Optimal timeframe for the strategy timeframe = '5m' # generate signals from the 1h timeframe informative_timeframe = '1h' # WARNING: ichimoku is a long indicator, if you remove or use a # shorter startup_candle_count your backtest results will be unreliable startup_candle_count = 500 # NOTE: this strat only uses candle information, so processing between # new candles is a waste of resources as nothing will change process_only_new_candles = True # Buy hyperspace params: buy_params = { "dema_len_buy": 80, # value loaded from strategy "low_offset": 1.119, # value loaded from strategy } # Sell hyperspace params: sell_params = { "dema_len_sell": 83, # value loaded from strategy "high_offset": 1.07, # value loaded from strategy } # ROI table: minimal_roi = { "0": 0.11, "26": 0.083, "48": 0.038, "149": 0 } # Stoploss: stoploss = -0.348 # Trailing stop: trailing_stop = True trailing_stop_positive = 0.017 trailing_stop_positive_offset = 0.113 trailing_only_offset_is_reached = True # Max Open Trades: max_open_trades = 10 # value loaded from strategy low_offset = DecimalParameter(0.80, 1.20, default=1.004, space='buy', optimize=True) high_offset = DecimalParameter(0.80, 1.20, default=0.964, space='sell', optimize=True) dema_len_buy = IntParameter(30, 90, default=72, space='buy', optimize=True) dema_len_sell = IntParameter(30, 90, default=51, space='sell', optimize=True) def informative_pairs(self): pairs = self.dp.current_whitelist() informative_pairs = [(pair, self.informative_timeframe) for pair in pairs] return informative_pairs def slow_tf_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: displacement = 30 ichimoku = ftt.ichimoku(dataframe, conversion_line_period=20, base_line_periods=60, laggin_span=120, displacement=displacement ) dataframe['chikou_span'] = ichimoku['chikou_span'] # cross indicators dataframe['tenkan_sen'] = ichimoku['tenkan_sen'] dataframe['kijun_sen'] = ichimoku['kijun_sen'] # cloud, green a > b, red a < b dataframe['senkou_a'] = ichimoku['senkou_span_a'] dataframe['senkou_b'] = ichimoku['senkou_span_b'] dataframe['leading_senkou_span_a'] = ichimoku['leading_senkou_span_a'] dataframe['leading_senkou_span_b'] = ichimoku['leading_senkou_span_b'] dataframe['cloud_green'] = ichimoku['cloud_green'] * 1 dataframe['cloud_red'] = ichimoku['cloud_red'] * -1 dataframe.loc[:, 'cloud_top'] = dataframe.loc[:, ['senkou_a', 'senkou_b']].max(axis=1) dataframe.loc[:, 'cloud_bottom'] = dataframe.loc[:, ['senkou_a', 'senkou_b']].min(axis=1) # DANGER ZONE START # NOTE: Not actually the future, present data that is normally shifted forward for display as the cloud dataframe['future_green'] = (dataframe['leading_senkou_span_a'] > dataframe['leading_senkou_span_b']).astype('int') * 2 dataframe['future_red'] = (dataframe['leading_senkou_span_a'] < dataframe['leading_senkou_span_b']).astype('int') * 2 # The chikou_span is shifted into the past, so we need to be careful not to read the # current value. But if we shift it forward again by displacement it should be safe to use. # We're effectively "looking back" at where it normally appears on the chart. dataframe['chikou_high'] = ( (dataframe['chikou_span'] > dataframe['cloud_top']) ).shift(displacement).replace(np.nan,0).astype('int') dataframe['chikou_low'] = ( (dataframe['chikou_span'] < dataframe['cloud_bottom']) ).shift(displacement).replace(np.nan,0).astype('int') # DANGER ZONE END dataframe['atr'] = ta.ATR(dataframe, timeperiod=14) ssl_down, ssl_up = ssl_atr(dataframe, 10) dataframe['ssl_down'] = ssl_down dataframe['ssl_up'] = ssl_up dataframe['ssl_ok'] = ( (ssl_up > ssl_down) ).astype('int') * 3 dataframe['ssl_bear'] = ( (ssl_up < ssl_down) ).astype('int') * 3 dataframe['ichimoku_ok'] = ( (dataframe['tenkan_sen'] > dataframe['kijun_sen']) & (dataframe['close'] > dataframe['cloud_top']) & (dataframe['future_green'] > 0) & (dataframe['chikou_high'] > 0) ).astype('int') * 4 dataframe['ichimoku_bear'] = ( (dataframe['tenkan_sen'] < dataframe['kijun_sen']) & (dataframe['close'] < dataframe['cloud_bottom']) & (dataframe['future_red'] > 0) & (dataframe['chikou_low'] > 0) ).astype('int') * 4 dataframe['ichimoku_valid'] = ( (dataframe['leading_senkou_span_b'] == dataframe['leading_senkou_span_b']) # not NaN ).astype('int') * 1 dataframe['trend_pulse'] = ( (dataframe['ichimoku_ok'] > 0) & (dataframe['ssl_ok'] > 0) ).astype('int') * 2 dataframe['bear_trend_pulse'] = ( (dataframe['ichimoku_bear'] > 0) & (dataframe['ssl_bear'] > 0) ).astype('int') * 2 dataframe['trend_over'] = ( (dataframe['ssl_ok'] == 0) | (dataframe['close'] < dataframe['cloud_top']) ).astype('int') * 1 dataframe['bear_trend_over'] = ( (dataframe['ssl_bear'] == 0) | (dataframe['close'] > dataframe['cloud_bottom']) ).astype('int') * 1 dataframe.loc[ (dataframe['trend_pulse'] > 0), 'trending'] = 3 dataframe.loc[ (dataframe['trend_over'] > 0) , 'trending'] = 0 dataframe['trending'].ffill() dataframe.loc[ (dataframe['bear_trend_pulse'] > 0), 'bear_trending'] = 3 dataframe.loc[ (dataframe['bear_trend_over'] > 0) , 'bear_trending'] = 0 dataframe['bear_trending'].ffill() return dataframe def fast_tf_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: if self.config['runmode'].value == 'hyperopt': for len in range(30, 91): dataframe[f'dema_{len}'] = ftt.dema(dataframe, period=len) else: dataframe[f'dema_{self.dema_len_buy.value}'] = ftt.dema(dataframe, period=self.dema_len_buy.value) dataframe[f'dema_{self.dema_len_sell.value}'] = ftt.dema(dataframe, period=self.dema_len_sell.value) dataframe[f'dema_buy'] = ftt.dema(dataframe, period=self.dema_len_buy.value) * self.low_offset.value dataframe[f'dema_sell'] = ftt.dema(dataframe, period=self.dema_len_sell.value) * self.high_offset.value return dataframe def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: assert (timeframe_to_minutes(self.timeframe) == 5), "Run this strategy at 5m." if self.timeframe == self.informative_timeframe: dataframe = self.slow_tf_indicators(dataframe, metadata) else: assert self.dp, "DataProvider is required for multiple timeframes." informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.informative_timeframe) informative = self.slow_tf_indicators(informative.copy(), metadata) dataframe = merge_informative_pair(dataframe, informative, self.timeframe, self.informative_timeframe, ffill=True) # don't overwrite the base dataframe's OHLCV information skip_columns = [(s + "_" + self.informative_timeframe) for s in ['date', 'open', 'high', 'low', 'close', 'volume']] dataframe.rename(columns=lambda s: s.replace("_{}".format(self.informative_timeframe), "") if (not s in skip_columns) else s, inplace=True) dataframe = self.fast_tf_indicators(dataframe, metadata) return dataframe def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dema = f'dema_{self.dema_len_buy.value}' dataframe.loc[ (dataframe['ichimoku_valid'] > 0) & (dataframe['bear_trending'] == 0) & (dataframe['close'] < (dataframe[dema] * self.low_offset.value)) , 'buy'] = 1 return dataframe def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dema = f'dema_{self.dema_len_sell.value}' dataframe.loc[ ( (dataframe['close'] > (dataframe[dema] * self.high_offset.value)) ) , 'sell'] = 1 return dataframe def confirm_trade_exit(self, pair: str, trade: 'Trade', order_type: str, amount: float, rate: float, time_in_force: str, sell_reason: str, current_time: 'datetime', **kwargs) -> bool: if sell_reason in ('roi',): dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) current_candle = dataframe.iloc[-1] if current_candle is not None: current_candle = current_candle.squeeze() # don't sell during ichimoku uptrend if current_candle['trending'] > 0: return False return True plot_config = { # Main plot indicators (Moving averages, ...) 'main_plot': { 'senkou_a': { 'color': 'green', 'fill_to': 'senkou_b', 'fill_label': 'Ichimoku Cloud', 'fill_color': 'rgba(0,0,0,0.2)', }, # plot senkou_b, too. Not only the area to it. 'senkou_b': { 'color': 'red', }, 'tenkan_sen': { 'color': 'blue' }, 'kijun_sen': { 'color': 'orange' }, # 'chikou_span': { 'color': 'lightgreen' }, 'ssl_up': { 'color': 'green' }, # 'ssl_down': { 'color': 'red' }, # 'ema50': { 'color': 'violet' }, # 'ema200': { 'color': 'magenta' }, 'dema_buy': { 'color': 'blue' }, 'dema_sell': { 'color': 'orange' }, }, 'subplots': { "Trend": { 'trending': {'color': 'green'}, 'bear_trending': {'color': 'red'}, }, "Bull": { 'trend_pulse': {'color': 'blue'}, 'trending': {'color': 'orange'}, 'trend_over': {'color': 'red'}, }, "Bull Signals": { 'ichimoku_ok': {'color': 'green'}, 'ssl_ok': {'color': 'red'}, }, "Bear": { 'bear_trend_pulse': {'color': 'blue'}, 'bear_trending': {'color': 'orange'}, 'bear_trend_over': {'color': 'red'}, }, "Bear Signals": { 'ichimoku_bear': {'color': 'green'}, 'ssl_bear': {'color': 'red'}, }, "Misc": { 'ichimoku_valid': {'color': 'green'}, }, } }

frederic auricombe

## SMAOffsetProtectOptV1.py with fix for docker freqtrade 2024.01 # --- Do not remove these libs --- from freqtrade.strategy.interface import IStrategy from typing import Dict, List from functools import reduce from pandas import DataFrame # -------------------------------- import talib.abstract as ta import numpy as np import freqtrade.vendor.qtpylib.indicators as qtpylib import datetime from technical.util import resample_to_interval, resampled_merge from datetime import datetime, timedelta from freqtrade.persistence import Trade from freqtrade.strategy import stoploss_from_open, merge_informative_pair, DecimalParameter, IntParameter, CategoricalParameter import technical.indicators as ftt def EWO(dataframe, ema_length=5, ema2_length=35): df = dataframe.copy() ema1 = ta.EMA(df, timeperiod=ema_length) ema2 = ta.EMA(df, timeperiod=ema2_length) emadif = (ema1 - ema2) / df['close'] * 100 return emadif class SMAOffsetProtectOptV1(IStrategy): INTERFACE_VERSION = 2 # Buy hyperspace params: buy_params = { "base_nb_candles_buy": 46, "ewo_high": 3.188, "ewo_low": -8.109, "low_offset": 0.984, "rsi_buy": 57, } # Sell hyperspace params: sell_params = { "base_nb_candles_sell": 79, "high_offset": 1.0, } # ROI table: minimal_roi = { "0": 0.314, "82": 0.117, "297": 0.074, "479": 0 } # Stoploss: stoploss = -0.336 # Trailing stop: trailing_stop = False # value loaded from strategy trailing_stop_positive = 0.001 # value loaded from strategy trailing_stop_positive_offset = 0.01 # value loaded from strategy trailing_only_offset_is_reached = True # value loaded from strategy # Max Open Trades: max_open_trades = 10 # value loaded from strategy protections = [ # { # "method": "StoplossGuard", # "lookback_period_candles": 12, # "trade_limit": 1, # "stop_duration_candles": 6, # "only_per_pair": True # }, #{ # "method": "StoplossGuard", # "lookback_period_candles": 12, # "trade_limit": 5, # "stop_duration_candles": 6, # "only_per_pair": False #}, { "method": "LowProfitPairs", "lookback_period_candles": 60, "trade_limit": 5, "stop_duration": 60, "required_profit": -0.05 }, { "method": "CooldownPeriod", "stop_duration_candles": 2 } ] # SMAOffset base_nb_candles_buy = IntParameter( 5, 80, default=buy_params['base_nb_candles_buy'], space='buy', optimize=True) base_nb_candles_sell = IntParameter( 5, 80, default=sell_params['base_nb_candles_sell'], space='sell', optimize=True) low_offset = DecimalParameter( 0.9, 0.99, default=buy_params['low_offset'], space='buy', optimize=True) high_offset = DecimalParameter( 0.99, 1.1, default=sell_params['high_offset'], space='sell', optimize=True) # Protection fast_ewo = 50 slow_ewo = 200 ewo_low = DecimalParameter(-20.0, -8.0, default=buy_params['ewo_low'], space='buy', optimize=True) ewo_high = DecimalParameter( 2.0, 12.0, default=buy_params['ewo_high'], space='buy', optimize=True) rsi_buy = IntParameter(30, 70, default=buy_params['rsi_buy'], space='buy', optimize=True) # Trailing stop: trailing_stop = False # value loaded from strategy trailing_stop_positive = 0.001 # value loaded from strategy trailing_stop_positive_offset = 0.01 # value loaded from strategy trailing_only_offset_is_reached = True # value loaded from strategy # Sell signal use_exit_signal = True exit_profit_only = False exit_profit_offset = 0.01 ignore_roi_if_entry_signal = True # Optimal timeframe for the strategy timeframe = '30m' informative_timeframe = '1h' process_only_new_candles = True startup_candle_count = 30 plot_config = { 'main_plot': { 'ma_buy': {'color': 'orange'}, 'ma_sell': {'color': 'orange'}, }, } use_custom_stoploss = False def informative_pairs(self): pairs = self.dp.current_whitelist() informative_pairs = [(pair, self.informative_timeframe) for pair in pairs] return informative_pairs def get_informative_indicators(self, metadata: dict): dataframe = self.dp.get_pair_dataframe( pair=metadata['pair'], timeframe=self.informative_timeframe) return dataframe def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: if self.config['runmode'].value == 'hyperopt': # Calculate all ma_buy values for val in self.base_nb_candles_buy.range: dataframe[f'ma_{val}'] = ta.EMA(dataframe, timeperiod=val) else: dataframe[f'ma_{self.base_nb_candles_buy.value}'] = ta.EMA(dataframe, timeperiod=self.base_nb_candles_buy.value) dataframe[f'ma_{self.base_nb_candles_sell.value}'] = ta.EMA(dataframe, timeperiod=self.base_nb_candles_sell.value) # Elliot dataframe['EWO'] = EWO(dataframe, self.fast_ewo, self.slow_ewo) # RSI dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14) return dataframe def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: conditions = [] conditions.append( ( (dataframe['close'] < (dataframe[f'ma_{self.base_nb_candles_buy.value}'] * self.low_offset.value)) & (dataframe['EWO'] > self.ewo_high.value) & (dataframe['rsi'] < self.rsi_buy.value) & (dataframe['volume'] > 0) ) ) conditions.append( ( (dataframe['close'] < (dataframe[f'ma_{self.base_nb_candles_buy.value}'] * self.low_offset.value)) & (dataframe['EWO'] < self.ewo_low.value) & (dataframe['volume'] > 0) ) ) if conditions: dataframe.loc[ reduce(lambda x, y: x | y, conditions), 'buy' ]=1 return dataframe def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: conditions = [] conditions.append( ( (dataframe['close'] > (dataframe[f'ma_{self.base_nb_candles_sell.value}'] * self.high_offset.value)) & (dataframe['volume'] > 0) ) ) if conditions: dataframe.loc[ reduce(lambda x, y: x | y, conditions), 'sell' ]=1 return dataframe

Nacho Villamil

yes please, because for example there are some errors in Frederic's comment regarding the Machete strategy. In line 495 regarding the function: 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'] 25) ) return signal Missing < or > or =, etc. Several lines of the provided code are also missing characters. Anyway thank you very much for your help. Best regards

Dutch Algotrading

I have copied and paste the above code but for some reason the code is not accepted by the bot. Maybe you can mail it so that I can add this to a special post or something like that. Btw. I used your other hints about the ZEMA and these worked like a charm. I am making a new post about this. All credits go to you and others that worked on this solution! Thank You!!

Frederic Collard

Thank you for this fantastic work and especially to the community members who helped fixing this on latest version of Docker. This looks almost too good to be true. Can you please confirm if this strategy has a lookahead bias ? Can you help me figuring it out with the tools available in freqtrade so that I can also contribute :)

Dutch Algotrading

I was testing this algo with the lookahead bias command but it errored out on me. But the community members found a way around this. I posted this some days ago.