# source: https://raw.githubusercontent.com/remiotore/freqtrade/44beaeb6a420cd8e9f2e4ea93e11d6cfa192ee03/strategies/FSupertrendStrategy319.py
from datetime import datetime, timedelta
import pandas_ta as pta

from freqtrade.persistence import Trade
from freqtrade.strategy import IStrategy, IntParameter, DecimalParameter
from pandas import DataFrame
import talib.abstract as ta
import numpy as np


class Github_remiotore_freqtrade__FSupertrendStrategy319__20260111_210550(IStrategy):
    can_short = True

    INTERFACE_VERSION: int = 3
    # Buy hyperspace params:
    buy_params = {
        "buy_m1": 2,
        "buy_m2": 4
    }

    # Sell hyperspace params:
    sell_params = {
        "sell_m1": 5,
        "sell_profit": 0.005,
        "sell_fastk_min": 5,
        "sell_fastk_max": 95,
        "sell_profit2": -0.008,
    }

    # ROI table:
    minimal_roi = {
        "0": 0.02,
        "8": 0.015,
        "14": 0.01,
        "18": 0.006,
        "20": 0.001
    }

    # Stoploss:
    stoploss = -0.025

    # Trailing stop:
    trailing_stop = True                   # 启用追踪止损
    trailing_stop_positive = 0.0025         # 激活后，止损位设置在当前价格峰值下方 0.2%
    trailing_stop_positive_offset = 0.0065  # 当盈利达到 0.5% 时激活追踪止损       
    trailing_only_offset_is_reached = True # 仅在盈利达到 0.5% 后才开始追踪

    timeframe = "1m"

    startup_candle_count = 80

    buy_m1 = IntParameter(1, 8, default=1, optimize=False)
    buy_m2 = IntParameter(1, 8, default=1, optimize=False)

    buy_rsi_min = IntParameter(10, 30, default=20, optimize=False)
    buy_rsi_max = IntParameter(70, 90, default=80, optimize=False)

    sell_m1 = IntParameter(1, 5, default=1, optimize=False)

    sell_profit = DecimalParameter(0, 0.01, default=0.003, optimize=False)
    sell_profit2 = DecimalParameter(-0.015, -0.002, default=-0.008, optimize=True)
    sell_fastk_max = IntParameter(80, 100, default=90, optimize=False)
    sell_fastk_min = IntParameter(0, 20, default=10, optimize=False)

    # @property
    # def protections(self):
    # return  [
    # {
    # "method": "CooldownPeriod",
    # "stop_duration_candles": 1
    # }
    # ]

    def leverage(self, pair, current_time, current_rate, proposed_leverage, max_leverage, side, **kwargs):
        return 2

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # for multiplier in self.buy_m1.range:
        #     dataframe[f"supertrend_1_buy"] = supertrend(dataframe, multiplier, 5)["STX"]
        # for multiplier in self.buy_m2.range:
        #     dataframe[f"supertrend_2_buy"] = supertrend(dataframe, multiplier, 10)["STX"]

        # for multiplier in self.sell_m1.range:
        # dataframe[f"supertrend_1_sell"] = supertrend(dataframe, multiplier, 10)["STX"]

        macd = ta.MACD(dataframe)
        dataframe['macd'] = macd['macd']
        dataframe['macdsignal'] = macd['macdsignal']
        dataframe['macdhist'] = macd['macdhist']
        dataframe['rsi'] = ta.RSI(dataframe, timeperiod=5)
        
        dataframe['adx'] = ta.ADX(dataframe, timeperiod=10)

        stoch_fast = ta.STOCHF(dataframe, 5, 3, 0, 3, 0)
        dataframe['fastk'] = stoch_fast['fastk']
        
        dataframe['rsi_fastk'] = dataframe['rsi'] + dataframe['fastk']
        

        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            # (dataframe[f"supertrend_1_buy"] == "up")

            (dataframe['macd'] < dataframe['macdsignal'])
            # & (dataframe['macdhist'] < dataframe['macdhist'].shift(1))
            & (dataframe['rsi'] < 15)

            & (dataframe['fastk'] < 5)

            & (dataframe['rsi_fastk'] < 15)
            & (dataframe['adx'] > 30)
            # & (dataframe['fastk'] < dataframe['fastk'].shift(1))

            & (dataframe["volume"] > 0),
            ["enter_short", "enter_tag"]
        ] = (1, "long")

        dataframe.loc[
            # (dataframe[f"supertrend_1_buy"] == "down")

            (dataframe['macd'] > dataframe['macdsignal'])
            # & (dataframe['macdhist'] > dataframe['macdhist'].shift(1))
            & (dataframe['rsi'] > 85)

            & (dataframe['fastk'] > 95)

            & (dataframe['rsi_fastk'] > 185)
            & (dataframe['adx'] > 30)
            # & (dataframe['fastk'] > dataframe['fastk'].shift(1))

            & (dataframe["volume"] > 0),
            ["enter_long", "enter_tag"]
        ] = (1, "short")

        return dataframe

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

    def custom_exit(self, pair: str, trade: Trade, current_time: datetime, current_rate: float, current_profit: float, **kwargs):
        dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
        current_candle = dataframe.iloc[-1].squeeze()

        if current_profit > 0.005:
            if trade.is_short:
                if current_candle["fastk"] < 5:
                    return "fastk_exit_short"
            else:
                if current_candle["fastk"] > 95:
                    return "fastk_exit_long"


        if current_profit > 0.001 and (current_time - timedelta(minutes=12) > trade.open_date_utc):
            if trade.is_short:
                if current_candle["fastk"] == 0:
                    return "fastk_exit_short10"
            else:
                if current_candle["fastk"] == 100:
                    return "fastk_exit_long10"

        if current_profit < -0.008:
            if trade.is_short:
                if current_candle["fastk"] < 10:
                    return "fastk_stoploss_short"
            else:
                if current_candle["fastk"] > 90:
                    return "fastk_stoploss_long"
