# source: https://raw.githubusercontent.com/DerSalvador/freqtrade-helm-chart/a669dc11b640b0eb63aa8f8b51e9f181fd7ee43c/chart/deployed_strategies/binance-futures-k8s-namespace/GodCard.py
from freqtrade.strategy import IStrategy
from freqtrade.strategy import BooleanParameter, CategoricalParameter, DecimalParameter, IStrategy, IntParameter
from functools import reduce
from pandas import DataFrame
# --------------------------------
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
import numpy  # noqa

class Github_DerSalvador_freqtrade_helm_chart__GodCard__20260115_122204(IStrategy):
    INTERFACE_VERSION = 3
    timeframe = '5m'
    # Define the parameter spaces
    cooldown_lookback = IntParameter(2, 48, default=5, space='protection', optimize=True)
    stop_duration = IntParameter(12, 200, default=5, space='protection', optimize=True)
    use_stop_protection = BooleanParameter(default=True, space='protection', optimize=True)

    @property
    def protections(self):
        prot = []
        prot.append({'method': 'CooldownPeriod', 'stop_duration_candles': self.cooldown_lookback.value})
        if self.use_stop_protection.value:
            prot.append({'method': 'StoplossGuard', 'lookback_period_candles': 24, 'trade_limit': 4, 'stop_duration_candles': self.stop_duration.value, 'only_per_pair': False})
        return prot
    # run "populate_indicators" only for new candle
    process_only_new_candles = False
    # Experimental settings (configuration will overide these if set)
    use_exit_signal = True
    exit_profit_only = True
    ignore_roi_if_entry_signal = False
    # Optional order type mapping
    order_types = {'entry': 'limit', 'exit': 'limit', 'stoploss': 'market', 'stoploss_on_exchange': False}
    # Hyperopt parameters
    entry_rsi = IntParameter(low=1, high=100, default=30, space='entry', optimize=True)
    entry_rsi_enabled = CategoricalParameter([True, False], default=False, space='entry', optimize=True)
    entry_trigger = CategoricalParameter(['bb_one', 'bb_two', 'bb_three'], default='bb_one', space='entry', optimize=True)
    exit_rsi = IntParameter(low=1, high=100, default=70, space='exit', optimize=True)
    exit_rsi_enabled = CategoricalParameter([True, False], default=False, space='exit', optimize=True)
    exit_trigger = CategoricalParameter(['bb_low_exit', 'bb_mid_exit', 'bb_up_exit', 'sarBoi'], default='bb_two_exit', space='exit', optimize=True)
    # Buy hyperspace params:
    entry_params = {'entry_rsi': 56, 'entry_rsi_enabled': False, 'entry_trigger': 'bb_two'}
    # Sell hyperspace params:
    exit_params = {'exit_rsi': 9, 'exit_rsi_enabled': True, 'exit_trigger': 'bb_mid_exit'}
    # Protection hyperspace params:
    protection_params = {'cooldown_lookback': 0, 'stop_duration': 39, 'use_stop_protection': False}
    # ROI table:
    minimal_roi = {'0': 0.344, '32': 0.09, '120': 0.041, '447': 0}
    # Stoploss:
    stoploss = -0.087
    # Trailing stop:
    trailing_stop = True
    trailing_stop_positive = 0.01
    trailing_stop_positive_offset = 0.043
    trailing_only_offset_is_reached = True

    def informative_pairs(self):
        return []

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # RSI
        dataframe['rsi'] = ta.RSI(dataframe)
        # SAR Parabol
        dataframe['sar'] = ta.SAR(dataframe)
        # Bollinger bands
        bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=1)
        dataframe['bb_lowerband'] = bollinger['lower']
        dataframe['bb_middleband'] = bollinger['mid']
        dataframe['bb_upperband'] = bollinger['upper']
        bollinger2 = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
        dataframe['bb_lowerband2'] = bollinger2['lower']
        dataframe['bb_middleband2'] = bollinger2['mid']
        dataframe['bb_upperband2'] = bollinger2['upper']
        bollinger3 = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=3)
        dataframe['bb_lowerband3'] = bollinger3['lower']
        dataframe['bb_middleband3'] = bollinger3['mid']
        dataframe['bb_upperband3'] = bollinger3['upper']
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        conditions = []
        # GUARDS AND TRENDS
        if self.entry_rsi_enabled.value:
            conditions.append(dataframe['rsi'] > self.entry_rsi.value)
        # TRIGGERS
        if self.entry_trigger.value == 'bb_one':
            conditions.append(dataframe['close'] < dataframe['bb_lowerband'])
        if self.entry_trigger.value == 'bb_two':
            conditions.append(dataframe['close'] < dataframe['bb_lowerband2'])
        if self.entry_trigger.value == 'bb_three':
            conditions.append(dataframe['close'] < dataframe['bb_lowerband3'])
        # Check that volume is not 0
        conditions.append(dataframe['volume'] > 0)
        if conditions:
            dataframe.loc[reduce(lambda x, y: x & y, conditions), 'entry'] = 1
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        conditions = []
        # GUARDS AND TRENDS
        if self.exit_rsi_enabled.value:
            conditions.append(dataframe['rsi'] > self.exit_rsi.value)
        # TRIGGERS
        if self.exit_trigger.value == 'sarBoi':
            conditions.append(dataframe['sar'] > dataframe['close'])
        if self.entry_trigger.value == 'bb_low_exit':
            conditions.append(dataframe['close'] > dataframe['bb_lowerband'])
        if self.entry_trigger.value == 'bb_mid_exit':
            conditions.append(dataframe['close'] > dataframe['bb_middleband'])
        if self.entry_trigger.value == 'bb_up_exit':
            conditions.append(dataframe['close'] > dataframe['bb_upperband'])
        # Check that volume is not 0
        conditions.append(dataframe['volume'] > 0)
        if conditions:
            dataframe.loc[reduce(lambda x, y: x & y, conditions), 'exit'] = 1
        return dataframe