# source: https://raw.githubusercontent.com/gksdud6330/crytpo-auto-trading-bot/e754e3c873b4845c56f7fb752748330c48cd6369/freqtrade-bot/user_data/strategies/AggressiveScalper.py
from freqtrade.strategy import IStrategy, merge_informative_pair
from pandas import DataFrame
import numpy as np
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib

class Github_gksdud6330_crytpo_auto_trading_bot__AggressiveScalper__20260118_144545(IStrategy):
    """
    Aggressive Scalper - PROFIT MAXIMIZATION FOCUS
    - Fast entries/exits
    - Multiple confirmation (but relaxed)
    - High trading frequency
    """
    INTERFACE_VERSION = 3
    timeframe = '5m'
    startup_candle_count = 50
    
    # Quick profit targets
    minimal_roi = {
        "0": 0.01,      # 1% immediate
        "10": 0.008,    # 0.8% after 10 min
        "30": 0.005,    # 0.5% after 30 min
        "60": 0         # Break even
    }
    
    stoploss = -0.02
    trailing_stop = True
    trailing_stop_positive = 0.005
    trailing_stop_positive_offset = 0.01
    trailing_only_offset_is_reached = True
    
    def informative_pairs(self):
        whitelist = []
        if self.dp:
            whitelist = self.dp.current_whitelist()
        if not whitelist:
            whitelist = self.config.get('exchange', {}).get('pair_whitelist', [])
        return [(pair, '1h') for pair in whitelist]
    
    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # === RSI ===
        dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
        dataframe['rsi_fast'] = ta.RSI(dataframe, timeperiod=7)
        
        # === EMA ===
        dataframe['ema_9'] = ta.EMA(dataframe, timeperiod=9)
        dataframe['ema_21'] = ta.EMA(dataframe, timeperiod=21)
        dataframe['ema_50'] = ta.EMA(dataframe, timeperiod=50)
        
        # === MACD ===
        macd = ta.MACD(dataframe)
        dataframe['macd'] = macd['macd']
        dataframe['macdsignal'] = macd['macdsignal']
        dataframe['macdhist'] = macd['macdhist']
        
        # === Bollinger Bands ===
        bollinger = ta.BBANDS(dataframe, timeperiod=20, nbdevup=2.0, nbdevdn=2.0)
        dataframe['bb_lower'] = bollinger['lowerband']
        dataframe['bb_middle'] = bollinger['middleband']
        dataframe['bb_upper'] = bollinger['upperband']
        
        # === Stochastic ===
        stoch = ta.STOCH(dataframe)
        dataframe['stoch_k'] = stoch['slowk']
        dataframe['stoch_d'] = stoch['slowd']
        
        # === Volume ===
        dataframe['volume'] = dataframe['volume'].astype(float)
        dataframe['volume_mean'] = dataframe['volume'].rolling(window=20).mean()
        dataframe['volume_ratio'] = dataframe['volume'] / dataframe['volume_mean']
        
        # === ADX (Trend Strength) ===
        dataframe['adx'] = ta.ADX(dataframe, timeperiod=14)
        
        # === ATR (Volatility) ===
        dataframe['atr'] = ta.ATR(dataframe, timeperiod=14)
        
        # === 1h Trend Confirmation ===
        if self.dp:
            informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe='1h')
            informative['ema_21'] = ta.EMA(informative, timeperiod=21)
            dataframe = merge_informative_pair(dataframe, informative, '5m', '1h', ffill=True)
        
        if 'ema_21_1h' not in dataframe:
            dataframe['ema_21_1h'] = dataframe['ema_21']
        dataframe['ema_21_1h'] = dataframe['ema_21_1h'].fillna(dataframe['ema_21'])
        
        # === Trend Signals ===
        dataframe['trend_up_5m'] = dataframe['ema_9'] > dataframe['ema_21']
        dataframe['trend_up_1h'] = dataframe['close'] > dataframe['ema_21_1h']
        dataframe['rsi_oversold'] = dataframe['rsi'] < 45
        dataframe['rsi_overbought'] = dataframe['rsi'] > 55
        dataframe['macd_bullish'] = dataframe['macd'] > dataframe['macdsignal']
        dataframe['stoch_bullish'] = dataframe['stoch_k'] > dataframe['stoch_d']
        
        return dataframe
    
    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # === ENTRY CONDITIONS (Relaxed for more trades) ===
        
        # Main entry: Multiple bullish signals
        entry_1 = (
            dataframe['trend_up_5m'] &  # 5m uptrend
            dataframe['rsi_oversold'] &  # RSI not overbought
            dataframe['macd_bullish'] &  # MACD bullish
            dataframe['stoch_bullish'] &  # Stochastic bullish
            dataframe['volume_ratio'] > 0.5  # Minimal volume
        )
        
        # RSI reversal entry
        entry_2 = (
            (dataframe['rsi'] < 50) &
            (dataframe['rsi_fast'] > dataframe['rsi']) &
            (dataframe['close'] > dataframe['bb_lower']) &
            dataframe['trend_up_5m']
        )
        
        # MACD cross entry
        entry_3 = (
            qtpylib.crossed_above(dataframe['macd'], dataframe['macdsignal']) &
            (dataframe['macdhist'] > -0.5) &
            dataframe['trend_up_5m']
        )
        
        # Stochastic reversal entry
        entry_4 = (
            qtpylib.crossed_above(dataframe['stoch_k'], dataframe['stoch_d']) &
            (dataframe['stoch_k'] < 70) &
            (dataframe['volume_ratio'] > 0.3)
        )
        
        # Combined
        dataframe.loc[(entry_1 | entry_2 | entry_3 | entry_4), 'enter_long'] = 1
        
        return dataframe
    
    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # === EXIT CONDITIONS ===
        
        # RSI overbought
        exit_1 = (dataframe['rsi'] > 70) | (dataframe['rsi_fast'] < dataframe['rsi'])
        
        # MACD bearish cross
        exit_2 = qtpylib.crossed_below(dataframe['macd'], dataframe['macdsignal'])
        
        # Trend reversal
        exit_3 = ~dataframe['trend_up_5m']
        
        # Take profit at BB upper
        exit_4 = dataframe['close'] > dataframe['bb_middle']
        
        # Stochastic overbought reversal
        exit_5 = qtpylib.crossed_below(dataframe['stoch_k'], dataframe['stoch_d']) & (dataframe['stoch_k'] > 60)
        
        dataframe.loc[(exit_1 | exit_2 | exit_3 | exit_4 | exit_5) & (dataframe['volume'] > 0), 'exit_long'] = 1
        
        return dataframe
