# source: https://raw.githubusercontent.com/rajsanjib/freqtrader/07ec18d8762b5161b1ff084e0c44367532bfb894/user_data/strategies/ShortTermMomentumStrategy.py
# --- Do not remove these libs ---
import numpy as np
import pandas as pd
from pandas import DataFrame
from datetime import datetime
import talib.abstract as ta
from freqtrade.strategy import IStrategy, informative
from freqtrade.persistence import Trade

# --------------------------------
# Add your lib to import here
import freqtrade.vendor.qtpylib.indicators as qtpylib


class Github_rajsanjib_freqtrader__ShortTermMomentumStrategy__20250423_033243(IStrategy):
    """
    Short-Term Momentum Strategy
    
    This strategy is designed for short-term trading with quick entry and exit based on:
    - RSI for entry/exit signals
    - EMA crossovers for trend direction
    - MACD for momentum confirmation
    - Bollinger Bands for volatility-based exits
    - Volume filters to avoid low liquidity situations
    
    Timeframe: 5m (recommended)
    """
    
    # Strategy interface version - required
    INTERFACE_VERSION = 3

    # Minimal ROI designed for short-term trades
    # Aim to take profit quickly on volatile movements
    minimal_roi = {
        "0": 0.025,   # 2.5% profit immediately
        "10": 0.02,   # 2% after 10 minutes
        "20": 0.015,  # 1.5% after 20 minutes
        "30": 0.01,   # 1% after 30 minutes
        "60": 0.005   # 0.5% after 60 minutes
    }

    # Stoploss is relatively tight for short-term trading
    stoploss = -0.025  # 2.5%
    
    # Trailing stoploss to lock in profits
    trailing_stop = True
    trailing_stop_positive = 0.01  # 1%
    trailing_stop_positive_offset = 0.02  # 2%
    trailing_only_offset_is_reached = True

    # Optimal timeframe for the strategy
    timeframe = '5m'

    # Run "populate_indicators()" only for new candle.
    process_only_new_candles = True

    # Number of candles the strategy requires
    startup_candle_count = 50
    
    # For short-term trading, we need fast execution
    order_types = {
        'entry': 'market',
        'exit': 'market',
        'stoploss': 'market',
        'stoploss_on_exchange': False
    }
    
    # Trading timeframe is short - act quickly
    order_time_in_force = {
        'entry': 'gtc',
        'exit': 'gtc'
    }
    
    plot_config = {
        'main_plot': {
            'ema9': {'color': 'red'},
            'ema21': {'color': 'green'},
            'bb_upperband': {'color': 'blue'},
            'bb_lowerband': {'color': 'blue'},
        },
        'subplots': {
            "RSI": {
                'rsi': {'color': 'orange'},
            },
            "MACD": {
                'macd': {'color': 'blue'},
                'macdsignal': {'color': 'orange'},
            },
            "VOLUME": {
                'volume': {'color': 'blue'},
            }
        }
    }

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Compute technical indicators we need for our short-term strategy
        """
        
        # Volume indicators
        dataframe['volume_mean'] = dataframe['volume'].rolling(window=10).mean()
        
        # EMA - Exponential Moving Average for trends
        dataframe['ema9'] = ta.EMA(dataframe, timeperiod=9)
        dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
        dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
        
        # MACD for momentum detection
        macd = ta.MACD(dataframe)
        dataframe['macd'] = macd['macd']
        dataframe['macdsignal'] = macd['macdsignal']
        dataframe['macdhist'] = macd['macdhist']
        
        # Bollinger Bands for volatility measurement
        bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
        dataframe['bb_upperband'] = bollinger['upper']
        dataframe['bb_middleband'] = bollinger['mid']
        dataframe['bb_lowerband'] = bollinger['lower']
        dataframe['bb_width'] = (dataframe['bb_upperband'] - dataframe['bb_lowerband']) / dataframe['bb_middleband']
        dataframe['bb_pct'] = (dataframe['close'] - dataframe['bb_lowerband']) / (dataframe['bb_upperband'] - dataframe['bb_lowerband'])
        
        # RSI for overbought/oversold conditions
        dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
        
        # ADX for trend strength
        dataframe['adx'] = ta.ADX(dataframe)
        
        # Short-term price change metrics for trend strength
        dataframe['price_change_1h'] = dataframe['close'].pct_change(12).fillna(0) * 100  # 12 x 5m = 1h
        
        # Volume based metrics
        dataframe['volume_change'] = dataframe['volume'] / dataframe['volume'].shift(1)
        
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Entry signals for short-term trading
        """
        dataframe.loc[
            (
                # Uptrend condition
                (dataframe['ema9'] > dataframe['ema21']) &
                
                # Momentum rising
                (dataframe['macd'] > dataframe['macdsignal']) &
                
                # RSI rising but not overbought
                (dataframe['rsi'] > 50) & (dataframe['rsi'] < 70) &
                
                # Price below upper Bollinger - still room to grow
                (dataframe['close'] < dataframe['bb_upperband']) &
                
                # Significant volume
                (dataframe['volume'] > 0.8 * dataframe['volume_mean']) &
                
                # ADX showing that we're in a trend
                (dataframe['adx'] > 25)
            ),
            'enter_long'] = 1

        dataframe.loc[
            (
                # Downtrend condition
                (dataframe['ema9'] < dataframe['ema21']) &
                
                # Momentum falling
                (dataframe['macd'] < dataframe['macdsignal']) &
                
                # RSI falling but not oversold
                (dataframe['rsi'] < 50) & (dataframe['rsi'] > 30) &
                
                # Price above lower Bollinger - still room to fall
                (dataframe['close'] > dataframe['bb_lowerband']) &
                
                # Significant volume
                (dataframe['volume'] > 0.8 * dataframe['volume_mean']) &
                
                # ADX showing that we're in a trend
                (dataframe['adx'] > 25)
            ),
            'enter_short'] = 1

        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Exit signals for short-term trading
        """
        dataframe.loc[
            (
                (
                    # Trend reversal - EMA crossover
                    (dataframe['ema9'] < dataframe['ema21']) |
                    
                    # RSI overbought
                    (dataframe['rsi'] > 75) |
                    
                    # Price hitting upper Bollinger Band
                    (dataframe['close'] > dataframe['bb_upperband']) |
                    
                    # MACD crossing below signal line
                    (qtpylib.crossed_below(dataframe['macd'], dataframe['macdsignal']))
                )
            ),
            'exit_long'] = 1

        dataframe.loc[
            (
                (
                    # Trend reversal - EMA crossover
                    (dataframe['ema9'] > dataframe['ema21']) |
                    
                    # RSI oversold
                    (dataframe['rsi'] < 25) |
                    
                    # Price hitting lower Bollinger Band
                    (dataframe['close'] < dataframe['bb_lowerband']) |
                    
                    # MACD crossing above signal line
                    (qtpylib.crossed_above(dataframe['macd'], dataframe['macdsignal']))
                )
            ),
            'exit_short'] = 1

        return dataframe
    
    def custom_stoploss(self, pair: str, trade: Trade, current_time: datetime,
                        current_rate: float, current_profit: float, **kwargs) -> float:
        """
        Custom stoploss for short-term trading
        """
        # For short-term trading, we want to exit losing trades quickly
        # and give winning trades room to grow
        
        # If we're in profit, use a tighter stoploss to protect gains
        if current_profit > 0.01:  # 1%
            return 0.005  # 0.5% from current price
        
        # Default to stoploss defined in strategy
        return self.stoploss