# source: https://raw.githubusercontent.com/remiotore/freqtrade/44beaeb6a420cd8e9f2e4ea93e11d6cfa192ee03/strategies/brawbot.py
# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
# isort: skip_file
# --- Do not remove these libs ---
import numpy as np  # noqa
import pandas as pd  # noqa
from pandas import DataFrame
from freqtrade.strategy.interface import IStrategy
from freqtrade.strategy import DecimalParameter
from technical.indicators import ichimoku
from freqtrade.persistence import Trade
import talib.abstract as ta
import logging
from datetime import datetime

logger = logging.getLogger(__name__)

LOG_FILENAME = datetime.now().strftime('logfile_%d_%m_%Y.log')
logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG, format='%(asctime)s :: %(message)s')


class Github_remiotore_freqtrade__brawbot__20260111_210550(IStrategy):
    """
    Estratégia otimizada para entradas cautelosas, evitando moedas com alta volatilidade
    e priorizando transações rápidas e seguras, com stoploss dinâmico.
    """
    # Configuração do tipo de ordem
    order_types = {
        'buy': 'limit',
        'sell': 'limit',
        'stoploss': 'market',
        'stoploss_on_exchange': False
    }

    # Retorno mínimo sobre o investimento (ROI)
    minimal_roi = {
        "60": 0.0002,
        "40": 0.0005,
        "20": 0.001,
        "10": 0.002,  # 0.2% após 10 minutos
        "5": 0.005,   # 0.5% após 5 minutos
        "0": 0.01     # 1% no final
    }

    # Configuração do timeframe
    timeframe = '5m'

    # Stoploss padrão
    stoploss = -0.10  # Início com -10%

    # Número máximo de trades abertos
    max_open_trades = 3  # Limitado a 3 trades para maior controle

    # Interface do Freqtrade (necessário usar versão 2)
    INTERFACE_VERSION = 2

    # Indicadores customizáveis via Hyperopt
    ema_short = DecimalParameter(5, 15, default=8, space='buy')
    ema_long = DecimalParameter(20, 50, default=21, space='buy')
    rsi_buy = DecimalParameter(30, 70, default=50, space='buy')

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Popula os indicadores técnicos usados pela estratégia.
        """
        # Indicadores Ichimoku
        ichi = ichimoku(dataframe)
        dataframe['tenkan'] = ichi['tenkan_sen']
        dataframe['kijun'] = ichi['kijun_sen']
        dataframe['senkou_a'] = ichi['senkou_span_a']
        dataframe['senkou_b'] = ichi['senkou_span_b']

        # Médias móveis exponenciais (curta e longa)
        dataframe['ema_short'] = ta.EMA(dataframe, timeperiod=int(self.ema_short.value))
        dataframe['ema_long'] = ta.EMA(dataframe, timeperiod=int(self.ema_long.value))

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

        # ATR (Average True Range)
        dataframe['atr'] = ta.ATR(dataframe, timeperiod=14)

        # Variação máxima nas últimas 48h
        dataframe['price_change_48h'] = (dataframe['high'].rolling(288).max() - dataframe['low'].rolling(288).min()) / dataframe['low'].rolling(288).min()

        return dataframe

    def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Define as condições de compra.
        """
        dataframe.loc[
            (
                # Filtro de volatilidade: ignora moedas com variação > 8% nas últimas 48h
                (dataframe['price_change_48h'] < 0.08) &
                # Condição 1: Cruzamento de EMA curta acima da EMA longa
                (dataframe['ema_short'] > dataframe['ema_long']) &
                (dataframe['close'] > dataframe['ema_short']) &  # Preço acima da EMA curta
                # Condição 2: RSI indicando força (compras em tendência)
                (dataframe['rsi'] > self.rsi_buy.value) &
                # Condição 3: Volume médio alto
                (dataframe['volume'] > dataframe['volume'].rolling(10).mean() * 1.2)  # Volume 20% maior que a média
            ),
            'buy'] = 1
        return dataframe

    def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
  #      """
  #      Define as condições de venda.
  #      """
  #      dataframe.loc[
  #          (
  #              # Condição 1: RSI indicando sobrecompra
  #              (dataframe['rsi'] > 70) |
  #              # Condição 2: Cruzamento de EMA curta abaixo da EMA longa
  #              (dataframe['ema_short'] < dataframe['ema_long']) |
  #              # Condição 3: Preço abaixo da EMA curta (reversão de tendência)
  #              (dataframe['close'] < dataframe['ema_short'])
  #          ),
  #          'sell'] = 1
        return dataframe

    def custom_stoploss(self, pair: str, trade: Trade, current_time: datetime, current_rate: float,
                        current_profit: float, **kwargs) -> float:
        """
        Ajusta o stoploss dinamicamente com base no tempo.
        A cada dia, o stoploss aumenta de -10% para -8%, -6%, ..., até -1%.
        """
        max_stoploss = -0.10  # -10% (inicial)
        min_stoploss = -0.01  # Valor mínimo de stoploss (-1%)
        trade_duration = (current_time - trade.open_date_utc).total_seconds()

        # Calcular o número de dias de operação
        days_open = trade_duration / (24 * 60 * 60)

        # Ajuste progressivo do stoploss com base no tempo
        # Cada dia a mais, aumenta 2% (menos negativo)
        dynamic_stoploss = max_stoploss + days_open * 0.02

        # Garantir que o stoploss não ultrapasse o mínimo permitido
        dynamic_stoploss = min(dynamic_stoploss, min_stoploss)

        return dynamic_stoploss
