# source: https://raw.githubusercontent.com/aragier/tradingStrategies/ba3f2fd3be7a23d51a2f518cb043f0db05091e41/user_data/strategies/BtcEma9_21Scalp_v2r.py
# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
# flake8: noqa: F401
# isort: skip_file
# --- Do not remove these imports ---
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,
    informative,
    BooleanParameter,
    CategoricalParameter,
    DecimalParameter,
    IntParameter,
    RealParameter,
    timeframe_to_minutes,
    timeframe_to_next_date,
    timeframe_to_prev_date,
    merge_informative_pair,
    stoploss_from_absolute,
    stoploss_from_open,
)

# --------------------------------
import talib.abstract as ta
from technical import qtpylib


class Github_aragier_tradingStrategies__BtcEma9_21Scalp_v2r__20260327_161149(IStrategy):
    """
    BtcEma9_21Scalp v2 with RELAXED filters.
    Changes vs v2: volume 1.2x, ADX 20, RSI bands wider, RSI exits 70/30, lookback 2.
    """

    INTERFACE_VERSION = 3
    can_short: bool = True

    minimal_roi = {
        "30": 0.01,
        "15": 0.02,
        "0": 0.03,
    }

    stoploss = -0.02

    trailing_stop = True
    trailing_stop_positive = 0.005
    trailing_stop_positive_offset = 0.01
    trailing_only_offset_is_reached = True

    timeframe = "5m"

    process_only_new_candles = True
    use_exit_signal = True
    exit_profit_only = False
    ignore_roi_if_entry_signal = False

    # --- RELAXED Parameters ---
    ema_fast_period = IntParameter(5, 15, default=9, space="buy", optimize=True, load=True)
    ema_slow_period = IntParameter(15, 30, default=21, space="buy", optimize=True, load=True)

    rsi_long_min = IntParameter(40, 55, default=45, space="buy", optimize=True, load=True)
    rsi_long_max = IntParameter(65, 80, default=75, space="buy", optimize=True, load=True)
    rsi_short_min = IntParameter(20, 35, default=25, space="sell", optimize=True, load=True)
    rsi_short_max = IntParameter(45, 60, default=55, space="sell", optimize=True, load=True)

    rsi_exit_long = IntParameter(65, 80, default=70, space="sell", optimize=True, load=True)
    rsi_exit_short = IntParameter(20, 35, default=30, space="sell", optimize=True, load=True)

    adx_threshold = IntParameter(15, 30, default=20, space="buy", optimize=True, load=True)
    volume_factor = DecimalParameter(1.0, 2.0, default=1.2, decimals=1, space="buy", optimize=True, load=True)
    ema_1h_lookback = IntParameter(1, 5, default=2, space="buy", optimize=True, load=True)

    startup_candle_count: int = 650

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

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

    plot_config = {
        "main_plot": {
            "ema_fast": {"color": "blue"},
            "ema_slow": {"color": "orange"},
        },
        "subplots": {
            "RSI": {"rsi": {"color": "red"}},
            "ADX": {"adx": {"color": "purple"}},
            "MACD": {"macdhist": {"color": "green", "type": "bar"}},
        },
    }

    @informative("1h")
    def populate_indicators_1h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe["ema_50"] = ta.EMA(dataframe, timeperiod=50)
        return dataframe

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe["ema_fast"] = ta.EMA(dataframe, timeperiod=self.ema_fast_period.value)
        dataframe["ema_slow"] = ta.EMA(dataframe, timeperiod=self.ema_slow_period.value)
        dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14)
        dataframe["adx"] = ta.ADX(dataframe, timeperiod=14)
        macd = ta.MACD(dataframe, fastperiod=12, slowperiod=26, signalperiod=9)
        dataframe["macdhist"] = macd["macdhist"]
        dataframe["volume_sma"] = ta.SMA(dataframe["volume"], timeperiod=20)
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                (qtpylib.crossed_above(dataframe["ema_fast"], dataframe["ema_slow"]))
                & (dataframe["ema_50_1h"] > dataframe["ema_50_1h"].shift(self.ema_1h_lookback.value))
                & (dataframe["rsi"] > self.rsi_long_min.value)
                & (dataframe["rsi"] < self.rsi_long_max.value)
                & (dataframe["adx"] > self.adx_threshold.value)
                & (dataframe["volume"] > (dataframe["volume_sma"] * self.volume_factor.value))
            ),
            "enter_long",
        ] = 1

        dataframe.loc[
            (
                (qtpylib.crossed_below(dataframe["ema_fast"], dataframe["ema_slow"]))
                & (dataframe["ema_50_1h"] < dataframe["ema_50_1h"].shift(self.ema_1h_lookback.value))
                & (dataframe["rsi"] > self.rsi_short_min.value)
                & (dataframe["rsi"] < self.rsi_short_max.value)
                & (dataframe["adx"] > self.adx_threshold.value)
                & (dataframe["volume"] > (dataframe["volume_sma"] * self.volume_factor.value))
            ),
            "enter_short",
        ] = 1

        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                (
                    (qtpylib.crossed_below(dataframe["ema_fast"], dataframe["ema_slow"]))
                    & (dataframe["macdhist"] < 0)
                )
                | (dataframe["rsi"] > self.rsi_exit_long.value)
            )
            & (dataframe["volume"] > 0),
            "exit_long",
        ] = 1

        dataframe.loc[
            (
                (
                    (qtpylib.crossed_above(dataframe["ema_fast"], dataframe["ema_slow"]))
                    & (dataframe["macdhist"] > 0)
                )
                | (dataframe["rsi"] < self.rsi_exit_short.value)
            )
            & (dataframe["volume"] > 0),
            "exit_short",
        ] = 1

        return dataframe
