"""EmaEnsemble - ta sama teza co EmaCross, ale bez wybierania dlugosci EMA. PROBLEM, KTORY ROZWIAZUJE: Walk-forward pokazal, ze optymalna dlugosc EMA skacze miedzy 500 a 1200 w zaleznosci od okna treningowego. Nie ma stabilnej "wlasciwej" wartosci. Kazde wybranie jednej z nich to krok selekcji, ktory trzeba potem odliczyc w Deflated Sharpe - i wlasnie na tym kroku strategia oblewala bramke. ROZWIAZANIE: Nie wybieramy. Liczymy caly wachlarz EMA i patrzymy, jaka ICH CZESC cena przebila. Powyzej polowy - jestesmy w rynku, ponizej - w gotowce. Zero parametrow do dostrojenia: - zbior EMA jest ustalony z gory i rozlozony rownomiernie w zakresie, ktory walk-forward w ogole odwiedzil (400-1200h) - prog to 0.5, czyli wiekszosc; nie ma tu nic do optymalizowania Efekt uboczny, ktory jest wlasciwie celem: skoro nie ma czego wybierac, nie ma tez selekcji, ktora zawyzalaby wynik. """ from __future__ import annotations import numpy as np import talib.abstract as ta from pandas import DataFrame from freqtrade.strategy import IStrategy EMA_SET = (400, 600, 800, 1000, 1200) class EmaEnsemble(IStrategy): INTERFACE_VERSION = 3 timeframe = "1h" can_short = False process_only_new_candles = True startup_candle_count = 1300 minimal_roi = {"0": 10} stoploss = -0.15 trailing_stop = True def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: above = np.zeros(len(dataframe)) for p in EMA_SET: ema = ta.EMA(dataframe, timeperiod=p) above += (dataframe["close"] > ema).astype(float).to_numpy() # udzial EMA, ktore cena ma pod soba: 0.0 = ponizej wszystkich, 1.0 = powyzej dataframe["ema_score"] = above / len(EMA_SET) return dataframe def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: s = dataframe["ema_score"] dataframe.loc[ (s > 0.5) & (s.shift(1) <= 0.5) & (dataframe["volume"] > 0), ["enter_long", "enter_tag"], ] = (1, "majority_above") return dataframe def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: s = dataframe["ema_score"] dataframe.loc[ (s < 0.5) & (s.shift(1) >= 0.5), ["exit_long", "exit_tag"], ] = (1, "majority_below") return dataframe