# source: https://raw.githubusercontent.com/plcacs/Harmonizing_ml_results/a66800d87059b5b854166f27c66f5104ecc830b8/cloned_repos/o1_mini/1/strategy_test_v3_251abc.py
from datetime import datetime
from typing import Any, Dict, List, Optional, Tuple, Union

import talib.abstract as ta
from pandas import DataFrame
import freqtrade.vendor.qtpylib.indicators as qtpylib
from freqtrade.persistence import Trade
from freqtrade.strategy import (
    BooleanParameter,
    DecimalParameter,
    IntParameter,
    IStrategy,
    RealParameter,
)


class Github_plcacs_Harmonizing_ml_results__strategy_test_v3_251abc__20250519_020121(IStrategy):
    """
    Strategy used by tests freqtrade bot.
    Please do not modify this strategy, it's intended for internal use only.
    Please look at the SampleStrategy in the user_data/strategy directory
    or strategy repository https://github.com/freqtrade/freqtrade-strategies
    for samples and inspiration.
    """

    INTERFACE_VERSION: int = 3
    minimal_roi: Dict[str, float] = {"40": 0.0, "30": 0.01, "20": 0.02, "0": 0.04}
    max_open_trades: int = -1
    stoploss: float = -0.1
    timeframe: str = "5m"
    order_types: Dict[str, Union[str, bool]] = {
        "entry": "limit",
        "exit": "limit",
        "stoploss": "limit",
        "stoploss_on_exchange": False,
    }
    startup_candle_count: int = 20
    order_time_in_force: Dict[str, str] = {"entry": "gtc", "exit": "gtc"}
    buy_params: Dict[str, Any] = {"buy_rsi": 35}
    sell_params: Dict[str, Any] = {"sell_rsi": 74, "sell_minusdi": 0.4}
    buy_rsi: IntParameter = IntParameter([0, 50], default=30, space="buy")
    buy_plusdi: RealParameter = RealParameter(low=0, high=1, default=0.5, space="buy")
    sell_rsi: IntParameter = IntParameter(low=50, high=100, default=70, space="sell")
    sell_minusdi: DecimalParameter = DecimalParameter(
        low=0, high=1, default=0.5001, decimals=3, space="sell", load=False
    )
    protection_enabled: BooleanParameter = BooleanParameter(default=True)
    protection_cooldown_lookback: IntParameter = IntParameter(
        [0, 50], default=30
    )

    @property
    def protections(self) -> Union[Dict[str, Any], List[Any]]:
        prot: Union[Dict[str, Any], List[Any]] = []
        if self.protection_enabled.value:
            prot = self.config.get("_strategy_protections", {})
        return prot

    bot_started: bool = False

    def bot_start(self) -> None:
        self.bot_started = True

    def informative_pairs(self) -> List[Tuple[str, str]]:
        return []

    def populate_indicators(
        self, dataframe: DataFrame, metadata: Dict[str, Any]
    ) -> DataFrame:
        dataframe["adx"] = ta.ADX(dataframe)
        macd = ta.MACD(dataframe)
        dataframe["macd"] = macd["macd"]
        dataframe["macdsignal"] = macd["macdsignal"]
        dataframe["macdhist"] = macd["macdhist"]
        dataframe["minus_di"] = ta.MINUS_DI(dataframe)
        dataframe["plus_di"] = ta.PLUS_DI(dataframe)
        dataframe["rsi"] = ta.RSI(dataframe)
        stoch_fast = ta.STOCHF(dataframe)
        dataframe["fastd"] = stoch_fast["fastd"]
        dataframe["fastk"] = stoch_fast["fastk"]
        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"]
        dataframe["ema10"] = ta.EMA(dataframe, timeperiod=10)
        return dataframe

    def populate_entry_trend(
        self, dataframe: DataFrame, metadata: Dict[str, Any]
    ) -> DataFrame:
        dataframe.loc[
            (
                (dataframe["rsi"] < self.buy_rsi.value)
                & (dataframe["fastd"] < 35)
                & (dataframe["adx"] > 30)
                & (dataframe["plus_di"] > self.buy_plusdi.value)
            )
            | (
                (dataframe["adx"] > 65)
                & (dataframe["plus_di"] > self.buy_plusdi.value)
            ),
            "enter_long",
        ] = 1
        dataframe.loc[
            qtpylib.crossed_below(dataframe["rsi"], self.sell_rsi.value),
            ("enter_short", "enter_tag"),
        ] = (1, "short_Tag")
        return dataframe

    def populate_exit_trend(
        self, dataframe: DataFrame, metadata: Dict[str, Any]
    ) -> DataFrame:
        dataframe.loc[
            (
                (
                    qtpylib.crossed_above(dataframe["rsi"], self.sell_rsi.value)
                    | qtpylib.crossed_above(dataframe["fastd"], 70)
                )
                & (dataframe["adx"] > 10)
                & (dataframe["minus_di"] > 0)
            )
            | (
                (dataframe["adx"] > 70)
                & (dataframe["minus_di"] > self.sell_minusdi.value)
            ),
            "exit_long",
        ] = 1
        dataframe.loc[
            qtpylib.crossed_above(dataframe["rsi"], self.buy_rsi.value),
            ("exit_short", "exit_tag"),
        ] = (1, "short_Tag")
        return dataframe

    def leverage(
        self,
        pair: str,
        current_time: datetime,
        current_rate: float,
        proposed_leverage: float,
        max_leverage: float,
        entry_tag: Optional[str],
        side: str,
        **kwargs: Any,
    ) -> float:
        return 3.0

    def adjust_trade_position(
        self,
        trade: Trade,
        current_time: datetime,
        current_rate: float,
        current_profit: float,
        min_stake: float,
        max_stake: float,
        current_entry_rate: float,
        current_exit_rate: Optional[float],
        current_entry_profit: float,
        current_exit_profit: Optional[float],
        **kwargs: Any,
    ) -> Optional[float]:
        if current_profit < -0.0075:
            orders = trade.select_filled_orders(trade.entry_side)
            return round(orders[0].stake_amount, 0)
        return None


class Github_plcacs_Harmonizing_ml_results__strategy_test_v3_251abc__20250519_020121Futures(Github_plcacs_Harmonizing_ml_results__strategy_test_v3_251abc__20250519_020121):
    can_short: bool = True
