# source: https://raw.githubusercontent.com/ythere-y/QuantLab/4c16942a9bfed55206e58cee087641540e38c1fc/user_data/strategies/RsiOversoldStrategy.py
"""
RSI Oversold Bounce Strategy

Buy when RSI drops below oversold threshold (default 30) then starts rising.
Sell when RSI rises above overbought threshold (default 70).

Includes ADX filter to avoid flat/ranging markets with weak signals.

Timeframe: 1h
Pairs: BTC/USDT, ETH/USDT, SOL/USDT, BNB/USDT
"""
import numpy as np
import pandas as pd
from datetime import datetime, timedelta, timezone
from pandas import DataFrame
from typing import Optional, Union

from freqtrade.strategy import (
    IStrategy,
    Trade,
    Order,
    PairLocks,
    BooleanParameter,
    CategoricalParameter,
    DecimalParameter,
    IntParameter,
    RealParameter,
)

import talib.abstract as ta
from technical import qtpylib


class Github_ythere_y_QuantLab__RsiOversoldStrategy__20260502_162050(IStrategy):
    """
    RSI Oversold Bounce strategy.
    Buy: RSI crosses above oversold level (coming from below).
    Sell: RSI crosses above overbought level.
    Filter: ADX > threshold to confirm trend strength.
    """

    INTERFACE_VERSION = 3
    can_short: bool = False

    minimal_roi = {
        "0": 0.06,
        "60": 0.04,
        "120": 0.02,
        "240": 0.0,
    }

    stoploss = -0.08  # 8% stop loss

    # Trailing stop
    trailing_stop = True
    trailing_stop_positive = 0.015
    trailing_stop_positive_offset = 0.035
    trailing_only_offset_is_reached = True

    timeframe = "1h"
    process_only_new_candles = True
    use_exit_signal = True
    exit_profit_only = False
    ignore_roi_if_entry_signal = False

    # Hyperoptable parameters
    buy_rsi = IntParameter(15, 40, default=30, space="buy", optimize=True)
    sell_rsi = IntParameter(60, 85, default=70, space="sell", optimize=True)
    buy_adx = IntParameter(15, 40, default=25, space="buy", optimize=True)
    buy_rsi_period = IntParameter(7, 21, default=14, space="buy", optimize=True)

    startup_candle_count: int = 50

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

    order_time_in_force = {"entry": "GTC", "exit": "GTC"}

    plot_config = {
        "main_plot": {},
        "subplots": {
            "RSI": {
                "rsi": {"color": "red"},
            },
            "ADX": {
                "adx": {"color": "purple"},
            },
        },
    }

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """Calculate RSI and ADX indicators."""
        # RSI with multiple periods for hyperopt
        for period in range(7, 22):
            dataframe[f"rsi_{period}"] = ta.RSI(dataframe, timeperiod=period)

        # ADX for trend strength filter
        dataframe["adx"] = ta.ADX(dataframe)

        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """Buy when RSI crosses above oversold threshold with ADX confirmation."""
        rsi_col = f"rsi_{self.buy_rsi_period.value}"

        dataframe.loc[
            (
                (qtpylib.crossed_above(dataframe[rsi_col], self.buy_rsi.value))
                & (dataframe["adx"] > self.buy_adx.value)
                & (dataframe["volume"] > 0)
            ),
            "enter_long",
        ] = 1

        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """Sell when RSI crosses above overbought threshold."""
        rsi_col = f"rsi_{self.buy_rsi_period.value}"

        dataframe.loc[
            (
                (qtpylib.crossed_above(dataframe[rsi_col], self.sell_rsi.value))
                & (dataframe["volume"] > 0)
            ),
            "exit_long",
        ] = 1

        return dataframe
