# source: https://raw.githubusercontent.com/DOUGLASGUEDESATRIA/OSIRIS_TRADE/fe3c09567f3798d1cad6d7a306fa4f6131d91e17/user_data/strategies/OsirisMultiScalpV3.py
"""
OsirisMultiScalp v3 — Go simple, go native
============================================
LESSON LEARNED: custom_stoploss is a trap for simulating tight TP/SL.
Native stoploss + minimal_roi is rock-solid and correctly simulates
intra-candle behavior.

MATH FOR 1:1 R:R:
  Random WR = ~50%
  Fee impact = 0.04% / 1.0% target = 4% overhead
  Need WR > 52% to be profitable
  RSI extremes show +7pp edge → WR ~57% → PF 1.33
"""

import logging
from pandas import DataFrame
from freqtrade.persistence import Trade
from freqtrade.strategy import (
    IStrategy,
    DecimalParameter,
    IntParameter,
)
import talib.abstract as ta

logger = logging.getLogger(__name__)


class Github_DOUGLASGUEDESATRIA_OSIRIS_TRADE__OsirisMultiScalpV3__20260329_060843(IStrategy):
    INTERFACE_VERSION = 3
    can_short = True
    timeframe = "15m"

    startup_candle_count = 50
    process_only_new_candles = True

    order_types = {
        "entry": "limit",
        "exit": "limit",
        "stoploss": "market",
        "stoploss_on_exchange": False,
    }

    # ── Fixed SL & TP ────────────────────────────────────────────────
    stoploss = -0.01       # 1% fixed SL from open

    minimal_roi = {
        "0": 0.01,         # 1% TP → 1:1 R:R with 1% SL
    }

    trailing_stop = False
    use_custom_stoploss = False

    # ── Entry params (hyperoptable) ──────────────────────────────────
    long_rsi = IntParameter(20, 45, default=35, space="buy", optimize=True)
    short_rsi = IntParameter(55, 80, default=65, space="buy", optimize=True)
    rsi_period = IntParameter(10, 20, default=14, space="buy", optimize=True)
    use_bb_filter = IntParameter(0, 1, default=0, space="buy", optimize=True)

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        for period in range(10, 21):
            dataframe[f"rsi_{period}"] = ta.RSI(dataframe, timeperiod=period)

        bb = ta.BBANDS(dataframe, timeperiod=20, nbdevup=2.0, nbdevdn=2.0)
        dataframe["bb_upper"] = bb["upperband"]
        dataframe["bb_lower"] = bb["lowerband"]

        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        rsi = dataframe[f"rsi_{self.rsi_period.value}"]
        rsi_1 = rsi.shift(1)
        rsi_2 = rsi.shift(2)

        # Fresh RSI cross: wasn't extreme recently (prevents stacking)
        long_fresh = (rsi_1 >= self.long_rsi.value) | (rsi_2 >= self.long_rsi.value)
        long_base = (rsi < self.long_rsi.value) & long_fresh & (dataframe["volume"] > 0)

        short_fresh = (rsi_1 <= self.short_rsi.value) | (rsi_2 <= self.short_rsi.value)
        short_base = (rsi > self.short_rsi.value) & short_fresh & (dataframe["volume"] > 0)

        # Optional BB filter (closer to band = stronger mean-rev)
        if self.use_bb_filter.value == 1:
            long_base = long_base & (dataframe["close"] <= dataframe["bb_lower"] * 1.005)
            short_base = short_base & (dataframe["close"] >= dataframe["bb_upper"] * 0.995)

        dataframe.loc[long_base, "enter_long"] = 1
        dataframe.loc[short_base, "enter_short"] = 1

        return dataframe

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