# source: https://raw.githubusercontent.com/remiotore/freqtrade/44beaeb6a420cd8e9f2e4ea93e11d6cfa192ee03/strategies/777.py
import arrow
import numpy as np
import pandas as pd
import talib.abstract as ta
from pandas import DataFrame
from freqtrade.strategy.interface import IStrategy
from freqtrade.exchange import timeframe_to_seconds
from datetime import timedelta

pd.set_option("display.precision", 10)

class Github_remiotore_freqtrade__777__20260111_210550(IStrategy):
    stoploss = -0.99
    can_short = True

    trailing_stop = True
    trailing_stop_positive = 0.5
    trailing_stop_positive_offset = 0.6
    trailing_only_offset_is_reached = True

    disable_dataframe_checks = True

    atr_period = 20
    timeframe = '15m'
    timeframe_seconds = timeframe_to_seconds(timeframe)

    plot_config = {
        'main_plot': {
            'renko_close': {'color': 'blue'},
            'renko_open': {'color': 'orange'},
            'sar': {'color': 'green'},
        }
    }

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:

        dataframe['sar'] = ta.SAR(dataframe, acceleration=0.02, maximum=0.2)

        dataframe['tema'] = ta.TEMA(dataframe, timeperiod=50)
        dataframe['ATR'] = ta.ATR(dataframe, timeperiod=self.atr_period)

        renko_columns = [
            'date', 'renko_open', 'renko_high', 'renko_low', 'renko_close',
            'trend', 'prev_trend', 'prev2_trend', 'prev3_trend',
            'prev_date', 'new_brick'
        ]

        DATE_IDX = 0
        CLOSE_IDX = 4
        TREND_IDX = 5
        PREV_TREND_IDX = 6
        PREV2_TREND_IDX = 7
        NEW_BRICK = True
        COPIED_BRICK = False

        brick_size = np.NaN
        data = []
        prev_brick = None
        prev2_trend = False
        prev3_trend = False

        for row in dataframe.itertuples():
            if np.isnan(row.ATR):
                continue
            else:
                brick_size = row.ATR

            close = row.close
            date = row.date

            if prev_brick is None:
                trend = True
                prev_brick = [
                    date,
                    close - brick_size,
                    close,
                    close - brick_size,
                    close,
                    trend,
                    False,
                    False,
                    False,
                    date,
                    NEW_BRICK,
                ]
                prev2_trend = prev_brick[PREV_TREND_IDX]
                prev3_trend = prev_brick[PREV2_TREND_IDX]
                data.append(prev_brick)
                continue

            prev_date = prev_brick[DATE_IDX]
            prev_close = prev_brick[CLOSE_IDX]
            prev_trend = prev_brick[TREND_IDX]

            new_brick = None
            trend = prev_trend

            bricks = int(np.nan_to_num((close - prev_close) / brick_size))

            if trend and bricks >= 1:
                new_brick = [
                    date,
                    prev_close,
                    prev_close + bricks * brick_size,
                    prev_close,
                    prev_close + bricks * brick_size,
                    trend,
                    prev_trend,
                    prev2_trend,
                    prev3_trend,
                    prev_date,
                    NEW_BRICK,
                ]

            elif trend and bricks <= -2:
                trend = not trend
                new_brick = [
                    date,
                    prev_close - brick_size,
                    prev_close - brick_size,
                    prev_close - abs(bricks) * brick_size,
                    prev_close - abs(bricks) * brick_size,
                    trend,
                    prev_trend,
                    prev2_trend,
                    prev3_trend,
                    prev_date,
                    NEW_BRICK,
                ]

            elif not trend and bricks <= -1:
                new_brick = [
                    date,
                    prev_close,
                    prev_close,
                    prev_close - abs(bricks) * brick_size,
                    prev_close - abs(bricks) * brick_size,
                    trend,
                    prev_trend,
                    prev2_trend,
                    prev3_trend,
                    prev_date,
                    NEW_BRICK,
                ]

            elif not trend and bricks >= 2:
                trend = not trend
                new_brick = [
                    date,
                    prev_close + brick_size,
                    prev_close + bricks * brick_size,
                    prev_close + brick_size,
                    prev_close + bricks * brick_size,
                    trend,
                    prev_trend,
                    prev2_trend,
                    prev3_trend,
                    prev_date,
                    NEW_BRICK,
                ]

            else:
                data.append([
                    date,
                    prev_brick[1],
                    prev_brick[2],
                    prev_brick[3],
                    prev_brick[4],
                    prev_brick[5],
                    prev_brick[6],
                    prev_brick[7],
                    prev_brick[8],
                    prev_brick[9],
                    COPIED_BRICK,
                ])

            if new_brick is not None:
                data.append(new_brick)
                prev2_trend = prev_brick[PREV_TREND_IDX]
                prev3_trend = prev_brick[PREV2_TREND_IDX]
                prev_brick = new_brick

        renko_chart = pd.DataFrame(data=data, columns=renko_columns)

        merged_dataframe = dataframe.merge(renko_chart, how='left', on='date')

        merged_dataframe[['renko_open', 'renko_high', 'renko_low', 'renko_close', 'trend', 'prev_trend', 'prev2_trend', 'prev3_trend']] = merged_dataframe[
            ['renko_open', 'renko_high', 'renko_low', 'renko_close', 'trend', 'prev_trend', 'prev2_trend', 'prev3_trend']
        ].ffill()

        return merged_dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Вхід у довгу позицію на першій стрілочці PSAR або Renko
        """
        dataframe['enter_long'] = 0
        dataframe['psar_shifted'] = dataframe['sar'].shift(1)

        dataframe.loc[
            (
                (dataframe['psar_shifted'] > dataframe['close']) &  # PSAR був вище ціни
                (dataframe['sar'] < dataframe['close']) &            # PSAR тепер нижче ціни
                (dataframe['trend'] == True) &                       # Поточний brick бичачий
                (dataframe['prev_trend'] == False)                   # Попередній brick ведмежий
            ),
            'enter_long'
        ] = 1

        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Вихід з довгої позиції або вхід у коротку позицію на першій стрілочці PSAR або Renko
        """
        dataframe['enter_short'] = 0
        dataframe['exit_long'] = 0
        dataframe['psar_shifted'] = dataframe['sar'].shift(1)

        dataframe.loc[
            (
                (dataframe['psar_shifted'] < dataframe['close']) &  # PSAR був нижче ціни
                (dataframe['sar'] > dataframe['close']) &             # PSAR тепер вище ціни
                (dataframe['trend'] == False) &                      # Поточний brick ведмежий
                (dataframe['prev_trend'] == True)                    # Попередній brick бичачий
            ),
            'enter_short'
        ] = 1

        return dataframe
