# source: https://raw.githubusercontent.com/EJMC95/crypto-trading-bot/4d1de6b3d565f721d026d0a979242d2129a26661/user_data/strategies/E0V1E.py
# directory_url: https://github.com/EJMC95/crypto-trading-bot/blob/main/user_data/strategies/
# User: EJMC95
# Repository: crypto-trading-bot
# --------------------"""
Github_EJMC95_crypto_trading_bot__E0V1E__20260902_105840 — Freqtrade strategy for Dad (freqtrade-dad)
Based on Github_EJMC95_crypto_trading_bot__E0V1E__20260902_105840 concept: entry on volume spike + EMA expansion breakout.
Targets strong momentum bursts on 5m timeframe.

Paper trading only — dry_run: true, $1000 starting wallet.
"""
import numpy as np
import pandas as pd
from freqtrade.strategy import IStrategy, DecimalParameter, IntParameter
from pandas import DataFrame
import talib.abstract as ta


class Github_EJMC95_crypto_trading_bot__E0V1E__20260902_105840(IStrategy):
    """
    Github_EJMC95_crypto_trading_bot__E0V1E__20260902_105840 — Breakout / momentum strategy.
    5m candles, Binance/Kraken spot, paper trading.
    """
    INTERFACE_VERSION = 3
    timeframe = '5m'
    startup_candle_count = 200
    stoploss = -0.09
    trailing_stop = True
    trailing_stop_positive = 0.015
    trailing_stop_positive_offset = 0.03
    trailing_only_offset_is_reached = True
    use_custom_stoploss = False
    minimal_roi = {
        "0": 0.05,
        "20": 0.03,
        "50": 0.02,
        "100": 0.008,
    }
    process_only_new_candles = True
    use_exit_signal = True
    exit_profit_only = False
    ignore_roi_if_entry_signal = False

    # Buy params
    buy_ema_fast = IntParameter(8, 20, default=12, space='buy', optimize=True)
    buy_ema_slow = IntParameter(20, 50, default=26, space='buy', optimize=True)
    buy_rsi_limit = IntParameter(30, 55, default=50, space='buy', optimize=True)
    buy_volume_mult = DecimalParameter(1.0, 2.5, default=1.5, space='buy', optimize=True)

    # Sell params
    sell_rsi = IntParameter(60, 85, default=75, space='sell', optimize=True)

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
        dataframe['rsi_fast'] = ta.RSI(dataframe, timeperiod=4)

        # EMAs
        for period in [8, 12, 20, 26, 50, 100, 200]:
            dataframe[f'ema_{period}'] = ta.EMA(dataframe, timeperiod=period)

        # MACD
        macd = ta.MACD(dataframe, fastperiod=12, slowperiod=26, signalperiod=9)
        dataframe['macd'] = macd['macd']
        dataframe['macdsignal'] = macd['macdsignal']
        dataframe['macdhist'] = macd['macdhist']

        # Bollinger
        bollinger = ta.BBANDS(dataframe, timeperiod=20)
        dataframe['bb_lower'] = bollinger['lowerband']
        dataframe['bb_middle'] = bollinger['middleband']
        dataframe['bb_upper'] = bollinger['upperband']
        dataframe['bb_percent'] = (dataframe['close'] - dataframe['bb_lower']) / (dataframe['bb_upper'] - dataframe['bb_lower'])

        # ATR for volatility
        dataframe['atr'] = ta.ATR(dataframe, timeperiod=14)

        # Volume
        dataframe['volume_mean'] = dataframe['volume'].rolling(20).mean()
        dataframe['volume_spike'] = dataframe['volume'] / dataframe['volume_mean']

        # Stoch RSI
        stochrsi = ta.STOCHRSI(dataframe, timeperiod=14, fastk_period=3, fastd_period=3)
        dataframe['stochrsi_k'] = stochrsi['fastk']
        dataframe['stochrsi_d'] = stochrsi['fastd']

        # ADX
        dataframe['adx'] = ta.ADX(dataframe, timeperiod=14)
        dataframe['dm_plus'] = ta.PLUS_DI(dataframe, timeperiod=14)
        dataframe['dm_minus'] = ta.MINUS_DI(dataframe, timeperiod=14)

        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        ema_fast = f'ema_{self.buy_ema_fast.value}'
        ema_slow = f'ema_{self.buy_ema_slow.value}'

        dataframe.loc[
            (
                # EMA fast crossed above slow (momentum breakout)
                (dataframe[ema_fast] > dataframe[ema_slow]) &
                (dataframe[ema_fast].shift(1) <= dataframe[ema_slow].shift(1)) &
                # RSI in acceptable range (not overbought)
                (dataframe['rsi'] < self.buy_rsi_limit.value) &
                # Volume confirmation
                (dataframe['volume_spike'] > self.buy_volume_mult.value) &
                # Above 200 EMA (trend filter)
                (dataframe['close'] > dataframe['ema_200']) &
                # ADX confirms trend strength
                (dataframe['adx'] > 20) &
                (dataframe['dm_plus'] > dataframe['dm_minus']) &
                (dataframe['volume'] > 0)
            ),
            'enter_long'
        ] = 1
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        ema_fast = f'ema_{self.buy_ema_fast.value}'
        ema_slow = f'ema_{self.buy_ema_slow.value}'

        dataframe.loc[
            (
                (dataframe['rsi'] > self.sell_rsi.value) |
                (
                    (dataframe[ema_fast] < dataframe[ema_slow]) &
                    (dataframe['macdhist'] < 0)
                )
            ),
            'exit_long'
        ] = 1
        return dataframe
