# source: https://raw.githubusercontent.com/ertugrul59/FreqtradeStra/1151e1cc7d4b5fd81d1ef5e4da1db4197d2e8a6d/user_data/strategies/ScalpKingFutures.py
from freqtrade.strategy import IStrategy, DecimalParameter, IntParameter
from pandas import DataFrame
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
from functools import reduce
from typing import Dict

class Github_ertugrul59_FreqtradeStra__ScalpKingFutures__20250106_162904(IStrategy):
    """
    Github_ertugrul59_FreqtradeStra__ScalpKingFutures__20250106_162904 Strategy
    
    A futures scalping strategy for 5m timeframe with:
    - Supports both long and short positions
    - Optimized for 10x leverage
    - Tighter risk management for futures
    - Quick scalp trades with strict exit rules
    - Enhanced protection mechanisms
    """
    
    INTERFACE_VERSION = 3
    timeframe = '5m'
    
    # Futures-specific settings
    can_short = True  # Enable short positions
    leverage = 10     # Use 10x leverage
    
    # Tighter ROI for futures
    minimal_roi = {
        "0": 0.01,      # 1% profit immediately (10% with leverage)
        "3": 0.007,     # 0.7% after 3 minutes
        "5": 0.005,     # 0.5% after 5 minutes
        "10": 0         # Exit after 10 minutes
    }

    # Tighter stoploss for futures
    stoploss = -0.007  # -0.7% stoploss (-7% with leverage)

    # Trailing stoploss
    trailing_stop = True
    trailing_stop_positive = 0.003   # 0.3% trailing stoploss
    trailing_stop_positive_offset = 0.005  # 0.5% offset
    trailing_only_offset_is_reached = True

    process_only_new_candles = True
    startup_candle_count: int = 30

    # Strategy parameters
    buy_rsi = IntParameter(20, 40, default=30, space="buy")
    sell_rsi = IntParameter(60, 80, default=70, space="sell")
    
    # MACD parameters
    buy_macd = DecimalParameter(-0.05, 0, default=-0.025, space="buy")
    
    # Bollinger Band parameters
    bb_gain = DecimalParameter(0.01, 0.03, default=0.015, space="buy")

    def leverage_callback(self) -> Dict:
        """Leverage settings for futures"""
        return {"leverage": self.leverage}

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """Generate all indicators used by the strategy"""
        
        # RSI
        dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
        
        # MACD
        macd = ta.MACD(dataframe)
        dataframe['macd'] = macd['macd']
        dataframe['macdsignal'] = macd['macdsignal']
        dataframe['macdhist'] = macd['macdhist']
        
        # Bollinger Bands
        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']
        
        # Additional indicators for trend detection
        dataframe['ema_fast'] = ta.EMA(dataframe, timeperiod=8)
        dataframe['ema_slow'] = ta.EMA(dataframe, timeperiod=21)
        
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """Entry signals for both long and short positions"""
        
        long_conditions = []
        short_conditions = []
        
        # Long entry conditions
        long_conditions.append(
            (dataframe['rsi'] < self.buy_rsi.value) &
            (dataframe['volume'] > 0) &
            (dataframe['ema_fast'] > dataframe['ema_slow']) &
            (dataframe['close'] <= dataframe['bb_lowerband'] * 
             (1 + self.bb_gain.value)) &
            (dataframe['macdhist'] > self.buy_macd.value) &
            (dataframe['macdhist'] > dataframe['macdhist'].shift(1))
        )

        # Short entry conditions
        short_conditions.append(
            (dataframe['rsi'] > self.sell_rsi.value) &
            (dataframe['volume'] > 0) &
            (dataframe['ema_fast'] < dataframe['ema_slow']) &
            (dataframe['close'] >= dataframe['bb_upperband'] * 
             (1 - self.bb_gain.value)) &
            (dataframe['macdhist'] < -self.buy_macd.value) &
            (dataframe['macdhist'] < dataframe['macdhist'].shift(1))
        )

        if long_conditions:
            dataframe.loc[
                reduce(lambda x, y: x & y, long_conditions),
                'enter_long'] = 1

        if short_conditions:
            dataframe.loc[
                reduce(lambda x, y: x & y, short_conditions),
                'enter_short'] = 1

        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """Exit signals for both long and short positions"""
        
        long_exit_conditions = []
        short_exit_conditions = []
        
        # Long exit conditions
        long_exit_conditions.append(
            (dataframe['rsi'] > self.sell_rsi.value) |
            (dataframe['ema_fast'] < dataframe['ema_slow']) |
            (dataframe['close'] >= dataframe['bb_upperband']) |
            (dataframe['macdhist'] < dataframe['macdhist'].shift(1))
        )

        # Short exit conditions
        short_exit_conditions.append(
            (dataframe['rsi'] < self.buy_rsi.value) |
            (dataframe['ema_fast'] > dataframe['ema_slow']) |
            (dataframe['close'] <= dataframe['bb_lowerband']) |
            (dataframe['macdhist'] > dataframe['macdhist'].shift(1))
        )

        if long_exit_conditions:
            dataframe.loc[
                reduce(lambda x, y: x & y, long_exit_conditions),
                'exit_long'] = 1

        if short_exit_conditions:
            dataframe.loc[
                reduce(lambda x, y: x & y, short_exit_conditions),
                'exit_short'] = 1

        return dataframe