# source: https://raw.githubusercontent.com/vaskosmihaylov/nfi-custom-strategies/b1e7c0c36c931e80a5186e89f9374beabaffffcf/user_data/strategies/e0v1e/E0V1E_3.py
import freqtrade.vendor.qtpylib.indicators as qtpylib
from datetime import datetime, timedelta
import talib.abstract as ta
import pandas_ta as pta
from freqtrade.persistence import Trade
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame, Series
from freqtrade.strategy import DecimalParameter, IntParameter
from functools import reduce
import numpy as np
import warnings

warnings.simplefilter(action="ignore", category=RuntimeWarning)


class Github_vaskosmihaylov_nfi_custom_strategies__E0V1E_3__20260311_122119(IStrategy):

    # binance futures version
    minimal_roi = {"0": 1}
    timeframe = "5m"
    process_only_new_candles = True
    startup_candle_count = 20
    order_types = {
        "entry": "market",
        "exit": "market",
        "emergency_exit": "market",
        "force_entry": "market",
        "force_exit": "market",
        "stoploss": "market",
        "stoploss_on_exchange": False,
        "stoploss_on_exchange_interval": 60,
        "stoploss_on_exchange_market_ratio": 0.99,
    }

    stoploss = -0.25
    trailing_stop = True
    trailing_stop_positive = 0.002
    trailing_stop_positive_offset = 0.03
    trailing_only_offset_is_reached = True

    is_optimize_32 = False
    buy_rsi_fast_32 = IntParameter(
        20, 70, default=40, space="buy", optimize=is_optimize_32
    )
    buy_rsi_32 = IntParameter(15, 50, default=42, space="buy", optimize=is_optimize_32)
    buy_sma15_32 = DecimalParameter(
        0.900, 1, default=0.973, decimals=3, space="buy", optimize=is_optimize_32
    )
    buy_cti_32 = DecimalParameter(
        -1, 1, default=-0.52, decimals=2, space="buy", optimize=True
    )

    # 新增可优化参数：24小时价格变化百分比范围
    buy_24h_min_pct1 = DecimalParameter(
        -30.0, 0.0, default=-25, decimals=1, space="buy", optimize=True
    )
    buy_24h_max_pct1 = DecimalParameter(
        0.0, 200.0, default=40, decimals=1, space="buy", optimize=True
    )

    buy_cti_2 = DecimalParameter(
        -1, 1, default=0.5, decimals=2, space="buy", optimize=True
    )

    # 新增可优化参数：24小时价格变化百分比范围
    buy_24h_min_pct2 = DecimalParameter(
        -30.0, 0.0, default=-15.4, decimals=1, space="buy", optimize=True
    )
    buy_24h_max_pct2 = DecimalParameter(
        0.0, 200.0, default=10.8, decimals=1, space="buy", optimize=True
    )

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # buy_1 indicators
        dataframe["sma_15"] = ta.SMA(dataframe, timeperiod=15)
        dataframe["cti"] = pta.cti(dataframe["close"], length=20)
        dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14)
        dataframe["rsi_fast"] = ta.RSI(dataframe, timeperiod=4)
        dataframe["rsi_slow"] = ta.RSI(dataframe, timeperiod=20)

        dataframe["24h_change_pct"] = dataframe["close"].pct_change(periods=288) * 100

        # profit sell indicators
        dataframe["cci"] = ta.CCI(dataframe, timeperiod=20)

        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        conditions = []
        dataframe.loc[:, "enter_tag"] = ""
        buy_1 = (
            (dataframe["rsi_slow"] < dataframe["rsi_slow"].shift(1))
            & (dataframe["rsi_fast"] < self.buy_rsi_fast_32.value)
            & (dataframe["rsi"] > self.buy_rsi_32.value)
            & (dataframe["close"] < dataframe["sma_15"] * self.buy_sma15_32.value)
            & (dataframe["cti"] < self.buy_cti_32.value)
            & (
                dataframe["24h_change_pct"] > self.buy_24h_min_pct1.value
            )  # 使用可优化参数
            & (dataframe["24h_change_pct"] < self.buy_24h_max_pct1.value)
        )

        buy_2 = (
            (dataframe["rsi_slow"] < dataframe["rsi_slow"].shift(1))
            & (dataframe["rsi_fast"] < self.buy_rsi_fast_32.value)
            & (dataframe["rsi"] > self.buy_rsi_32.value)
            & (dataframe["close"] < dataframe["sma_15"] * self.buy_sma15_32.value)
            & (dataframe["cti"] < self.buy_cti_2.value)
            & (
                dataframe["24h_change_pct"] > self.buy_24h_min_pct2.value
            )  # 使用可优化参数
            & (dataframe["24h_change_pct"] < self.buy_24h_max_pct2.value)
        )

        conditions.append(buy_1)
        dataframe.loc[buy_1, "enter_tag"] += "buy_1"

        conditions.append(buy_2)
        dataframe.loc[buy_2, "enter_tag"] += "buy_2"

        if conditions:
            dataframe.loc[reduce(lambda x, y: x | y, conditions), "enter_long"] = 1
        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_time - timedelta(hours=4) > trade.open_date_utc:
            if current_profit > -0.05:
                if current_candle["cci"] > 100:
                    return "cci_loss_sell_2"

        if current_time - timedelta(hours=8) > trade.open_date_utc:
            if current_profit >= -0.1:
                return "time_loss_sell_8_10"

        if current_time - timedelta(hours=16) > trade.open_date_utc:
            if current_profit >= -0.15:
                return "time_loss_sell_16_15"

        return None

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

        dataframe.loc[:, ["exit_long", "exit_tag"]] = (0, "long_out")
        return dataframe