# source: https://raw.githubusercontent.com/segfault88/freqtrader/447e543c3d583f7a32c7da191f8692f0b6baa0b9/Dopeyting.py
# --- Imports ---
import freqtrade.vendor.qtpylib.indicators as qtpylib
import pandas as pd
import talib.abstract as ta
from freqtrade.strategy import DecimalParameter, IntParameter, IStrategy


class Github_segfault88_freqtrader__Dopeyting__20250729_234125(IStrategy):
    """
    From Github_segfault88_freqtrader__Dopeyting__20250729_234125 see: https://old.reddit.com/r/algotrading/comments/1mcngpl/making_5_monthly_on_my_crypto_algorithm_here_is/

    This is a trading strategy that enters a trade if 2 out of 3
    conditions are met.

    Conditions for BUY:
    1. 7-period SMA crosses above 25-period SMA.
    2. RSI is below 32.
    3. Price closes at or below the lower Bollinger Band * 1.002.

    Conditions for SELL:
    1. 7-period SMA crosses below 25-period SMA.
    2. RSI is above 70.
    3. Price closes at or above the upper Bollinger Band.

    All parameters are optimizable via Hyperopt.
    """

    # --- Strategy Configuration ---
    timeframe = "1h"

    # Stoploss configuration
    stoploss = -0.10

    # Minimal ROI (disables ROI-based selling in favor of sell signals)
    minimal_roi = {"0": 100}

    # Trailing stoploss
    trailing_stop = False

    # --- Hyperoptable Parameters ---

    # MA Parameters
    ma_short_period = IntParameter(5, 20, default=7, space="buy", optimize=True)
    ma_long_period = IntParameter(20, 50, default=25, space="buy", optimize=True)

    # RSI Parameters
    rsi_period = IntParameter(10, 25, default=14, space="buy", optimize=True)
    rsi_buy_level = IntParameter(20, 40, default=32, space="buy", optimize=True)
    rsi_sell_level = IntParameter(60, 80, default=70, space="sell", optimize=True)

    # Bollinger Bands Parameters
    bb_period = IntParameter(15, 30, default=20, space="buy", optimize=True)
    bb_stddev = DecimalParameter(1.5, 2.5, default=2.0, space="buy", optimize=True)
    bb_buy_factor = DecimalParameter(
        0.99, 1.01, default=1.002, space="buy", optimize=True
    )
    bb_sell_factor = DecimalParameter(
        0.99, 1.01, default=1.0, space="sell", optimize=True
    )

    def populate_indicators(
        self, dataframe: pd.DataFrame, metadata: dict
    ) -> pd.DataFrame:
        """
        Adds all necessary indicators to the given DataFrame.
        """
        # Moving Averages
        dataframe["sma_short"] = ta.SMA(
            dataframe, timeperiod=self.ma_short_period.value
        )
        dataframe["sma_long"] = ta.SMA(dataframe, timeperiod=self.ma_long_period.value)

        # RSI
        dataframe["rsi"] = ta.RSI(dataframe, timeperiod=self.rsi_period.value)

        # Bollinger Bands
        bollinger = qtpylib.bollinger_bands(
            qtpylib.typical_price(dataframe),
            window=self.bb_period.value,
            stds=self.bb_stddev.value,
        )
        dataframe["bb_lowerband"] = bollinger["lower"]
        dataframe["bb_upperband"] = bollinger["upper"]

        return dataframe

    def populate_buy_trend(
        self, dataframe: pd.DataFrame, metadata: dict
    ) -> pd.DataFrame:
        """
        Defines the buy signal logic.
        A buy signal is generated if at least 2 of the 3 conditions are met.
        """
        # --- Define the 3 buy conditions ---

        # Condition 1: MA Crossover
        buy_cond_1 = qtpylib.crossed_above(
            dataframe["sma_short"], dataframe["sma_long"]
        )

        # Condition 2: RSI Oversold
        buy_cond_2 = dataframe["rsi"] < self.rsi_buy_level.value

        # Condition 3: Price below Lower Bollinger Band
        buy_cond_3 = (
            dataframe["close"] <= dataframe["bb_lowerband"] * self.bb_buy_factor.value
        )

        # --- Combine conditions (at least 2 must be True) ---
        # In pandas, True is treated as 1 and False as 0, so we can sum them
        buy_conditions_sum = (
            buy_cond_1.astype(int) + buy_cond_2.astype(int) + buy_cond_3.astype(int)
        )

        # Set the buy signal
        dataframe.loc[(buy_conditions_sum >= 2), "buy"] = 1

        return dataframe

    def populate_sell_trend(
        self, dataframe: pd.DataFrame, metadata: dict
    ) -> pd.DataFrame:
        """
        Defines the sell signal logic.
        A sell signal is generated if at least 2 of the 3 conditions are met.
        """
        # --- Define the 3 sell conditions ---

        # Condition 1: MA Crossunder
        sell_cond_1 = qtpylib.crossed_below(
            dataframe["sma_short"], dataframe["sma_long"]
        )

        # Condition 2: RSI Overbought
        sell_cond_2 = dataframe["rsi"] > self.rsi_sell_level.value

        # Condition 3: Price above Upper Bollinger Band
        sell_cond_3 = (
            dataframe["close"] >= dataframe["bb_upperband"] * self.bb_sell_factor.value
        )

        # --- Combine conditions (at least 2 must be True) ---
        sell_conditions_sum = (
            sell_cond_1.astype(int) + sell_cond_2.astype(int) + sell_cond_3.astype(int)
        )

        # Set the sell signal
        dataframe.loc[(sell_conditions_sum >= 2), "sell"] = 1

        return dataframe
