# source: https://raw.githubusercontent.com/remiotore/freqtrade/44beaeb6a420cd8e9f2e4ea93e11d6cfa192ee03/strategies/TurtleTrader.py
from freqtrade.strategy import IStrategy, merge_informative_pair
from pandas import DataFrame
import talib.abstract as ta


class Github_remiotore_freqtrade__TurtleTrader__20260111_210550(IStrategy):
    INTERFACE_VERSION = 3

    # Strategy Parameters
    entry_period = 20
    exit_period = 10
    atr_period = 20
    atr_mult = 2.0  # For stop loss
    pyr_atr_mult = 0.5  # For pyramiding levels

    # Freqtrade Settings
    timeframe = '1d'
    startup_candle_count: int = entry_period + atr_period
    minimal_roi = {"0": 0.10}
    stoploss = -0.99  # Use custom stoploss
    trailing_stop = False

    def populate_indicators(self, df: DataFrame, metadata: dict) -> DataFrame:
        df['20d_high'] = df['high'].rolling(window=self.entry_period).max()
        df['10d_low'] = df['low'].rolling(window=self.exit_period).min()
        df['atr'] = ta.ATR(df, timeperiod=self.atr_period)
        return df

    def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
        df['enter_long'] = 0
        df.loc[
            (df['close'] > df['20d_high'].shift(1)),
            'enter_long'
        ] = 1
        return df

    def populate_exit_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
        df['exit_long'] = 0
        df.loc[
            (df['close'] < df['10d_low'].shift(1)),
            'exit_long'
        ] = 1
        return df

    def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float,
                            time_in_force: str, exit_tag: str, **kwargs) -> bool:
        trade = kwargs.get("trade", None)

        if not trade:
            return True  # Initial entry

        # Pyramiding logic
        data = self.dp.get_pair_dataframe(pair=pair, timeframe=self.timeframe)
        candle = data.iloc[-1]
        base_price = trade.open_rate
        atr = candle['atr']
        position_size = trade.amount

        # Determine pyramid level based on price distance
        levels_crossed = int((candle['close'] - base_price) / (self.pyr_atr_mult * atr))
        current_units = int(position_size / trade.open_trade_data.get('base_unit_size', 1.0))

        # Max 4 units total
        if current_units < 4 and levels_crossed > current_units:
            trade.open_trade_data['base_unit_size'] = position_size if 'base_unit_size' not in trade.open_trade_data else trade.open_trade_data['base_unit_size']
            return True
        return False

    def custom_stoploss(self, pair: str, trade, current_time, current_rate, current_profit, **kwargs):
        atr = self.dp.get_pair_dataframe(pair=pair, timeframe=self.timeframe).iloc[-1]['atr']
        stoploss_price = trade.open_rate - self.atr_mult * atr
        if current_rate <= stoploss_price:
            return 0.0
        return 1
