# source: https://raw.githubusercontent.com/GoLukeEnviro/trading-hub/f4b272b5c189235a3cdd507907942d16f2c48470/freqtrade/bots/regime-hybrid/user_data/strategies/RegimeSwitchingHybrid_v8_BaselineTest.py
"""
Github_GoLukeEnviro_trading_hub__RegimeSwitchingHybrid_v8_BaselineTest__20260602_130327
=====================================
BASELINE-ONLY TEST — no ATR trailing, no protections, no trailing stop.
Purpose: Answer "does the entry logic alone produce a positive edge?"

Changes vs v7:
  REMOVED: custom_stoploss(), protections, ATR-based SL/TP parameters,
           atr_sl_trend, atr_tp_trend, atr_sl_range.
  NEW:     stoploss = -0.03 (hard), minimal_roi = {"0": 0.05} (5% fixed).

KEEP from v7: Entry logic (ADX + EMA50 + RSI + volume + primo_gate),
              FleetGuard entry safety, RSI overbought exit signal.

Timeframe: 15m
Trading Mode: Isolated Futures (dry-run)
"""

import logging
import sys
from datetime import datetime, timedelta
from typing import Optional

import talib.abstract as ta
from freqtrade.strategy import IStrategy, IntParameter, DecimalParameter, BooleanParameter
import freqtrade.vendor.qtpylib.indicators as qtpylib
from pandas import DataFrame

sys.path.insert(0, "/freqtrade/shared")
from primo_signal import primo_gate_allows
from fleetguard_v1 import FleetGuard, FleetGuardConfig

logger = logging.getLogger(__name__)


class Github_GoLukeEnviro_trading_hub__RegimeSwitchingHybrid_v8_BaselineTest__20260602_130327(IStrategy):

    INTERFACE_VERSION = 3
    timeframe = "15m"
    can_short = False

    # ---- Baseline Exit: ONLY hard stoploss + fixed ROI ----
    # No custom_stoploss, no trailing, no protections
    stoploss = -0.03          # Hard -3% stop
    use_custom_stoploss = False
    trailing_stop = False

    minimal_roi = {
        "0": 0.05,             # Take profit at +5%, done
        "60": 0.03,
        "120": 0.01,
        "240": 0
    }

    # ---- FleetGuard entry safety (unchanged from v7) ----
    _fleetguard = FleetGuard(FleetGuardConfig(
        max_open_trades=3,
        max_open_shorts=2,
        max_open_longs=2,
    ))

    # NO protections in v8 — pure baseline test

    startup_candle_count = 50

    # ---- Hyperoptable Buy Parameters (same as v7) ----
    adx_threshold = DecimalParameter(15.0, 35.0, default=20.0, space="buy")
    ema_pullback_pct = DecimalParameter(0.5, 4.0, default=2.0, space="buy")
    rsi_entry_max = IntParameter(45, 65, default=55, space="buy")
    volume_ma_period = IntParameter(10, 40, default=20, space="buy")

    # Fixed exit parameters
    rsi_overbought = 66

    # ---- Indicators ----
    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        if not self.dp:
            return dataframe

        dataframe['adx'] = ta.ADX(dataframe)
        dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
        dataframe['rsi'] = ta.RSI(dataframe)
        dataframe['atr'] = ta.ATR(dataframe, timeperiod=14)
        dataframe['atr_pct'] = dataframe['atr'] / dataframe['close']

        dataframe['volume_sma'] = dataframe['volume'].rolling(
            window=self.volume_ma_period.value, min_periods=1
        ).mean()

        bollinger = qtpylib.bollinger_bands(
            qtpylib.typical_price(dataframe), window=20, stds=2
        )
        dataframe['bb_lowerband'] = bollinger['lower']
        dataframe['bb_middleband'] = bollinger['mid']
        dataframe['bb_upperband'] = bollinger['upper']

        return dataframe

    # ---- Entry Logic (UNCHANGED from v7) ----
    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        pair = metadata.get("pair")
        long_gate = primo_gate_allows(pair, "long")

        pullback_pct = self.ema_pullback_pct.value / 100.0
        pullback_ceiling = dataframe['ema50'] * (1.0 - pullback_pct)

        trend_continuation = (
            (dataframe['adx'] > self.adx_threshold.value) &
            (dataframe['close'] >= pullback_ceiling) &
            (dataframe['close'] < dataframe['ema50']) &
            (dataframe['rsi'] < self.rsi_entry_max.value) &
            (dataframe['volume'] > dataframe['volume_sma']) &
            long_gate
        )

        dataframe.loc[trend_continuation, 'enter_long'] = 1
        dataframe.loc[trend_continuation, 'enter_tag'] = 'baseline_test_v8'

        return dataframe

    # ---- Exit Logic (SIMPLIFIED: only RSI overbought) ----
    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (dataframe['rsi'] > self.rsi_overbought),
            'exit_long'
        ] = 1
        return dataframe

    # ---- FleetGuard Entry Safety (unchanged from v7) ----
    def confirm_trade_entry(self, pair: str, order_type: str, amount: float,
                            rate: float, time_in_force: str, current_time: datetime,
                            entry_tag: Optional[str], side: str, **kwargs) -> bool:
        """FleetGuard entry safety check with real trade data."""
        open_trades = []
        recent_closed = []
        current_drawdown = 0.0

        try:
            from freqtrade.persistence import Trade

            for t in Trade.get_trades_proxy(is_open=True):
                open_trades.append({"pair": t.pair, "is_short": t.is_short})

            cutoff = current_time - timedelta(hours=24)
            for t in Trade.get_trades_proxy(is_open=False):
                if t.close_date and t.close_date >= cutoff:
                    recent_closed.append({
                        "pair": t.pair,
                        "is_short": t.is_short,
                        "close_profit": t.close_profit or 0.0,
                    })

            total_profit = Trade.get_total_closed_profit()
            starting_balance = (
                self.wallets.get_starting_balance()
                if hasattr(self, 'wallets') and self.wallets else 1000.0
            )
            if starting_balance > 0:
                current_drawdown = abs(min(0, total_profit / starting_balance))

        except Exception as e:
            logger.warning(f"FleetGuard data gathering fallback: {e}")
            try:
                for t in Trade.get_trades_proxy(is_open=True):
                    open_trades.append({"pair": t.pair, "is_short": t.is_short})
            except Exception:
                pass

        allowed, reason = self._fleetguard.check_entry(
            pair=pair, side=side, open_trades=open_trades,
            recent_closed_trades=recent_closed, current_drawdown_pct=current_drawdown
        )
        if not allowed:
            logger.info(f"FleetGuard REJECT: {pair} {side} — {reason}")
            return False
        return True