# source: https://raw.githubusercontent.com/shatianming5/Agent_market/8dc940a702171d651cabe59aea11f778550390e4/workspace/strategies/rsi_bb_5m.py
"""RSI+BB Mean Reversion adapted for 5-minute timeframe.

Same logic as the 1H version that passed walk-forward,
but with parameters scaled for 5m bars:
- Faster RSI (7 instead of 14)
- Tighter BB (1.5 std instead of 2.0)
- Much tighter TP/SL (0.5% / 0.8%)
- Quick trades: in/out within 1-3 hours
"""
from __future__ import annotations

import sys
from pathlib import Path

import numpy as np
from pandas import DataFrame

_ROOT = Path(__file__).resolve().parents[2]
if str(_ROOT / "src") not in sys.path:
    sys.path.insert(0, str(_ROOT / "src"))
    sys.path.insert(0, str(_ROOT))

from freqtrade.strategy import IStrategy


class Github_shatianming5_Agent_market__rsi_bb_5m__20260330_190736(IStrategy):
    timeframe = "5m"
    minimal_roi = {"0": 0.008, "30": 0.004, "60": 0.002}
    stoploss = -0.008
    trailing_stop = True
    trailing_stop_positive = 0.003
    trailing_stop_positive_offset = 0.005
    use_exit_signal = True
    process_only_new_candles = True
    startup_candle_count: int = 50
    can_short = False

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # Fast RSI (7-period for 5m)
        delta = dataframe["close"].diff()
        gain = delta.where(delta > 0, 0.0).rolling(7).mean()
        loss = (-delta.where(delta < 0, 0.0)).rolling(7).mean()
        rs = gain / (loss + 1e-10)
        dataframe["rsi_7"] = 100 - (100 / (1 + rs))

        # Tight Bollinger Bands
        sma = dataframe["close"].rolling(20).mean()
        std = dataframe["close"].rolling(20).std()
        dataframe["bb_upper"] = sma + 1.5 * std
        dataframe["bb_middle"] = sma
        dataframe["bb_lower"] = sma - 1.5 * std

        # Volume filter
        dataframe["vol_sma"] = dataframe["volume"].rolling(30).mean()

        # Momentum
        dataframe["roc_12"] = dataframe["close"].pct_change(12) * 100

        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (dataframe["volume"] > 0)
            & (dataframe["close"] < dataframe["bb_lower"])
            & (dataframe["rsi_7"] < 25)
            & (dataframe["volume"] > dataframe["vol_sma"] * 0.8),
            ["enter_long", "enter_tag"],
        ] = (1, "5m_oversold")
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (dataframe["volume"] > 0)
            & ((dataframe["close"] > dataframe["bb_middle"]) | (dataframe["rsi_7"] > 55)),
            "exit_long",
        ] = 1
        return dataframe
