# source: https://raw.githubusercontent.com/shatianming5/Agent_market/2154e7914e43a9585737ea9303cd4bd7f45995bc/workspace/strategies/auto_v204.py
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__auto_v204__20260330_151458(IStrategy):
    INTERFACE_VERSION = 3

    timeframe = "1h"
    can_short = False
    process_only_new_candles = True
    startup_candle_count: int = 50

    minimal_roi = {"0": 0.06, "240": 0.03, "720": 0.012}
    stoploss = -0.06
    use_exit_signal = True

    rsi_period = 14
    bb_period = 20
    bb_std = 2.0
    atr_period = 14

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        if dataframe is None or dataframe.empty:
            return dataframe

        close = dataframe["close"].astype(float)
        high = dataframe["high"].astype(float)
        low = dataframe["low"].astype(float)
        vol = dataframe["volume"].astype(float)

        delta = close.diff()
        gain = delta.clip(lower=0.0)
        loss = (-delta).clip(lower=0.0)
        alpha = 1.0 / float(self.rsi_period)
        avg_gain = gain.ewm(alpha=alpha, adjust=False).mean()
        avg_loss = loss.ewm(alpha=alpha, adjust=False).mean()
        rs = avg_gain / (avg_loss + 1e-12)
        dataframe["rsi"] = (100.0 - (100.0 / (1.0 + rs))).replace([np.inf, -np.inf], np.nan).ffill().fillna(0.0)

        mid = close.rolling(self.bb_period).mean()
        std = close.rolling(self.bb_period).std(ddof=0)
        upper = mid + self.bb_std * std
        lower = mid - self.bb_std * std
        dataframe["bb_middle"] = mid
        dataframe["bb_upper"] = upper
        dataframe["bb_lower"] = lower
        bb_range = (upper - lower).replace(0.0, np.nan)
        dataframe["bb_width"] = (bb_range / (mid + 1e-12)).replace([np.inf, -np.inf], np.nan).ffill().fillna(0.0)
        dataframe["bb_percent"] = ((close - lower) / (bb_range + 1e-12)).replace([np.inf, -np.inf], np.nan).ffill().fillna(0.0)

        vol_sma = vol.rolling(20).mean()
        dataframe["vol_sma"] = vol_sma
        dataframe["vol_ratio"] = (vol / (vol_sma + 1e-12)).replace([np.inf, -np.inf], np.nan).ffill().fillna(0.0)

        prev_close = close.shift(1)
        tr = np.maximum(high - low, np.maximum((high - prev_close).abs(), (low - prev_close).abs()))
        dataframe["atr"] = tr.rolling(self.atr_period).mean().replace([np.inf, -np.inf], np.nan).ffill().fillna(0.0)

        lb = 12
        dataframe["bull_div"] = (
            (low < low.shift(lb) * 0.997)
            & (dataframe["rsi"] > dataframe["rsi"].shift(lb) + 2.0)
        ).astype(int)

        dataframe["hh_6"] = high.rolling(6).max().replace([np.inf, -np.inf], np.nan).ffill().fillna(0.0)
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        if dataframe is None or dataframe.empty:
            return dataframe

        rsi = dataframe["rsi"]
        close = dataframe["close"]
        lower = dataframe["bb_lower"]
        width = dataframe["bb_width"]
        volr = dataframe["vol_ratio"]
        bbp = dataframe["bb_percent"]

        base_ok = (dataframe["volume"] > 0) & (volr > 0.3) & (width > 0.004)

        touch = (close < lower * 1.003) & (rsi < 41.0) & (bbp < 0.20)
        deep = ((close < lower * 0.995) | (bbp < 0.08)) & (rsi < 34.0)
        div = (dataframe["bull_div"] > 0) & (close < dataframe["bb_middle"] * 0.995) & (rsi < 46.0)

        enter = base_ok & (touch | deep | div)
        dataframe.loc[enter, ["enter_long", "enter_tag"]] = (1, "rsi_bb_mr_v204")
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        if dataframe is None or dataframe.empty:
            return dataframe

        rsi = dataframe["rsi"]
        close = dataframe["close"]
        mid = dataframe["bb_middle"]
        upper = dataframe["bb_upper"]
        atr = dataframe["atr"]
        hh6 = dataframe["hh_6"]
        bbp = dataframe["bb_percent"]

        base_ok = dataframe["volume"] > 0

        take_profit = ((close > upper * 0.995) & (rsi > 55.0)) | ((bbp > 0.85) & (rsi > 58.0))
        delayed_mean = (close > mid * 1.002) & (rsi > 60.0)
        overbought = rsi > 72.0
        trail_after_push = (close > mid) & (close < (hh6 - atr * 1.2)) & (rsi > 50.0)

        exit_cond = base_ok & (take_profit | delayed_mean | overbought | trail_after_push)
        dataframe.loc[exit_cond, "exit_long"] = 1
        return dataframe