💬 Forum

CombinedStrategy

🏆 League #1872 / 1922

remiotore/ccxt-freqtrade/strategies/CombinedStrategy_20250110_5.py · ★3 · ⑂2 · first seen 2026-07-16 · repo updated 2026-01-11 · ⬇ 1 download

Basics mode: futures timeframe: 5m interface version: 3
Settings stoploss: -0.25 has minimal roi trailing custom stoploss
Indicators ADX EMA MACD RSI talib
Concepts divergence trailing
Methods custom_stoploss
15 related strategies ( identical code, similar name)

Each tile is a different kind of check — from an instant code lint to full sandboxed backtests and forward tests on recent data. Not sure what a check actually proves? See the FAQ →

Source

Download Raw
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
from freqtrade.strategy import IStrategy
from pandas import DataFrame
from datetime import datetime
import numpy as np
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib

class CombinedStrategy(IStrategy):
    INTERFACE_VERSION = 3

    # Configurações gerais
    can_short = True
    timeframe = '5m'  # Timeframe principal
    informative_timeframe = '5m'  # Timeframe informativo adicional
    stoploss = -0.25

    trailing_stop = True
    trailing_stop_positive = 0.01
    trailing_stop_positive_offset = 0.02

    minimal_roi = {
        "0": 0.05,
        "20": 0.04,
        "30": 0.03,
        "60": 0.01
    }

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Popula os indicadores necessários para a estratégia.
        """
        # Certifique-se de que o dataframe não está vazio
        if dataframe.empty:
            return dataframe

        # RSI (Índice de Força Relativa)
        dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)

        # MACD (Moving Average Convergence Divergence)
        macd = ta.MACD(dataframe, fastperiod=12, slowperiod=26, signalperiod=9)
        dataframe['macd'] = macd['macd']
        dataframe['macdsignal'] = macd['macdsignal']

        # ADX (Average Directional Index)
        dataframe['adx'] = ta.ADX(dataframe, timeperiod=14)

        # Médias Móveis Exponenciais (EMA)
        dataframe['ema20'] = ta.EMA(dataframe, timeperiod=20)
        dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)

        # Gradiente do RSI (Gradiente da EMA do RSI)
        rsi_ema = ta.EMA(dataframe['rsi'], timeperiod=14)
        dataframe['rsi_gra'] = np.gradient(rsi_ema)

        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Define as condições de entrada para long e short.
        """
        # Certifique-se de que o dataframe não está vazio
        if dataframe.empty:
            return dataframe

        # Entrada long (compra)
        dataframe.loc[
            (
                (dataframe['rsi'] > 50) &  # RSI acima de 50
                (dataframe['macd'] > dataframe['macdsignal']) &  # MACD cruzando para cima
                (dataframe['adx'] > 25) &  # ADX indicando tendência forte
                (dataframe['rsi_gra'] > 0)  # Gradiente positivo do RSI
            ),
            'enter_long'] = 1

        # Entrada short (venda)
        dataframe.loc[
            (
                (dataframe['rsi'] < 50) &  # RSI abaixo de 50
                (dataframe['macd'] < dataframe['macdsignal']) &  # MACD cruzando para baixo
                (dataframe['adx'] > 25) &  # ADX indicando tendência forte
                (dataframe['rsi_gra'] < 0)  # Gradiente negativo do RSI
            ),
            'enter_short'] = 1

        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Define as condições de saída para long e short.
        """
        # Certifique-se de que o dataframe não está vazio
        if dataframe.empty:
            return dataframe

        # Saída long
        dataframe.loc[
            (
                (dataframe['rsi'] > 70) |  # RSI em sobrecompra
                qtpylib.crossed_below(dataframe['ema20'], dataframe['ema50'])  # EMA20 cruzando abaixo da EMA50
            ),
            'exit_long'] = 1

        # Saída short
        dataframe.loc[
            (
                (dataframe['rsi'] < 30) |  # RSI em sobrevenda
                qtpylib.crossed_above(dataframe['ema20'], dataframe['ema50'])  # EMA20 cruzando acima da EMA50
            ),
            'exit_short'] = 1

        return dataframe

    def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
                        current_rate: float, current_profit: float, **kwargs) -> float:
        """
        Stop-loss dinâmico baseado no lucro atual.
        """
        if current_profit > 0.3:
            return 0.01
        elif current_profit > 0.1:
            return 0.02
        elif current_profit > 0.05:
            return 0.05

        return 0.1