# source: https://raw.githubusercontent.com/aabudeev/freqtrade/9c29560b14047786bc6cae0ac3bd0e5d8ad19b92/user_data/strategies/SignalOnlyStrategy_fixed.py
"""
Signal-only strategy with corrected stoploss handling.
"""

from datetime import datetime
from typing import Dict, List, Optional, Tuple

import numpy as np
import talib.abstract as ta
from pandas import DataFrame

from freqtrade.enums import ExitType, SignalDirection, TradeDirection
from freqtrade.exceptions import OperationalException
from freqtrade.persistence import Trade
from freqtrade.strategy import IStrategy, IntParameter, DecimalParameter, CategoricalParameter


class Github_aabudeev_freqtrade__SignalOnlyStrategy_fixed__20260605_063513(IStrategy):
    """
    Signal-only strategy with proper stoploss handling.
    """

    # ROI table:
    minimal_roi = {
        "0": 0.05,  # 5% if held for less than 1 hour
        "60": 0.02,  # 2% if held for 1 hour or more
        "120": 0.01,  # 1% if held for 2 hours or more
        "180": 0.005,  # 0.5% if held for 3 hours or more
        "240": 0,  # Stop loss if held for 4 hours or more
    }

    # Stoploss
    stoploss = -0.15  # 15% stoploss

    # Trailing stop
    trailing_stop = False
    trailing_stop_positive = 0.001  # 0.1%
    trailing_stop_positive_offset = 0.002  # 0.2%
    trailing_only_offset_as_percent = False

    # Order types
    order_types = {
        'entry': 'market',
        'exit': 'market',
        'stoploss': 'market',
        'stoploss_on_exchange': True,
        'stoploss_on_exchange_interval': 60,
    }

    # Leverage
    leverage_option = CategoricalParameter([1, 2, 5, 10, 25], default=1, space='buy', optimize=False)
    short_leverage_option = CategoricalParameter([1, 2, 5, 10, 25], default=1, space='sell', optimize=False)

    # Custom parameters
    use_signal_stoploss = True

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # No indicators needed for signal-only strategy
        dataframe['enter_long'] = 0
        dataframe['enter_short'] = 0
        dataframe['exit_long'] = 0
        dataframe['exit_short'] = 0
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[:, 'enter_long'] = 0
        dataframe.loc[:, 'enter_short'] = 0
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[:, "exit_long"] = 0
        dataframe.loc[:, "exit_short"] = 0
        return dataframe

    def custom_stoploss(self, pair: str, trade: Trade, current_time: datetime,
                        current_rate: float, current_profit: float, **kwargs) -> float:
        """
        Strictly use the stoploss price set during entry.
        No trailing, no adjustments.
        """
        # Use stoploss from signal
        signal_sl = trade.get_custom_data("signal_sl")
        if signal_sl is not None:
            sl_price = float(signal_sl)
            if not trade.is_short:
                if sl_price < current_rate:
                    return (sl_price / current_rate) - 1
            else:
                if sl_price > current_rate:
                    return 1 - (sl_price / current_rate)
        
        # Fallback to strategy stoploss if signal data is missing
        return self.stoploss

    def custom_exit(self, pair: str, trade: Trade, current_time: datetime, current_rate: float,
                    current_profit: float, **kwargs) -> str | bool | None:
        # Take profit from signal
        signal_tp = trade.get_custom_data("signal_tp")
        if signal_tp is not None:
            tp_price = float(signal_tp)
            if not trade.is_short:
                if current_rate >= tp_price:
                    return "signal_tp"
            else:
                if current_rate <= tp_price:
                    return "signal_tp"
        return None

    def leverages(self) -> Tuple[List[Optional[int]], List[Optional[int]]]:
        """Return leverage settings for long and short positions."""
        return [self.leverage_option.value], [self.short_leverage_option.value]

    def get_signal_direction(self, pair: str, trade: Trade) -> Optional[SignalDirection]:
        """Return signal direction based on trade properties."""
        try:
            if trade.is_short:
                return SignalDirection.SHORT
            return SignalDirection.LONG
        except Exception:
            return None

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # Signal-only strategy - no entry indicators
        dataframe.loc[:, 'enter_long'] = 0
        dataframe.loc[:, 'enter_short'] = 0
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # Signal-only strategy - no exit indicators
        dataframe.loc[:, "exit_long"] = 0
        dataframe.loc[:, "exit_short"] = 0
        return dataframe