# source: https://raw.githubusercontent.com/IvPalmer/Master-Trader/978b204f9571729b05462b2b487f594226d77478/ft_userdata/user_data/strategies/LabStrategy_009.py
# directory_url: https://github.com/IvPalmer/Master-Trader/blob/main/ft_userdata/user_data/strategies/
# User: IvPalmer
# Repository: Master-Trader
# --------------------import logging
from freqtrade.strategy import IStrategy, informative
from pandas import DataFrame
import numpy as np
import pandas as pd

logger = logging.getLogger(__name__)


class Github_IvPalmer_Master_Trader__LabStrategy_009__20260923_012354(IStrategy):
    """
    Auto-generated by Strategy Lab.
    Combo: bb(20,3)+vol(2.0)|btc_sma50+rsi35|wide
    """
    INTERFACE_VERSION: int = 3

    minimal_roi = {
        '0': 0.1,
        '360': 0.07,
        '720': 0.04,
        '1440': 0.02
}

    stoploss = -0.07
    trailing_stop = True
    trailing_stop_positive = 0.03
    trailing_stop_positive_offset = 0.05
    trailing_only_offset_is_reached = True

    timeframe = '1h'
    process_only_new_candles = True
    use_exit_signal = False
    exit_profit_only = True
    exit_profit_offset = 0.01
    startup_candle_count = 200

    @informative('1h', 'BTC/{stake}')
    def populate_indicators_btc_1h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe['sma50'] = dataframe['close'].rolling(50).mean()
        dataframe['rsi'] = _rsi(dataframe['close'], 14)
        return dataframe

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        bb_sma = dataframe['close'].rolling(20).mean()
        bb_std = dataframe['close'].rolling(20).std()
        dataframe['bb_lower'] = bb_sma - 3 * bb_std
        dataframe['vol_sma20'] = dataframe['volume'].rolling(20).mean()
        dataframe['btc_gate'] = ((dataframe['btc_usdt_close_1h'] > dataframe['btc_usdt_sma50_1h']) & (dataframe['btc_usdt_rsi_1h'] > 35)).astype(int)
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                (dataframe['close'] > dataframe['bb_lower']) &
                (dataframe['close'].shift(1) <= dataframe['bb_lower'].shift(1)) &
                (dataframe['volume'] > 2.0 * dataframe['vol_sma20']) &
                (dataframe['btc_gate'] == 1) &

                (dataframe['volume'] > 0)
            ),
            'enter_long'] = 1
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # Exits handled by ROI, stoploss, and trailing stop
        return dataframe



def _rsi(close, period=14):
    delta = close.diff()
    gain = delta.clip(lower=0)
    loss = (-delta).clip(lower=0)
    avg_gain = gain.ewm(alpha=1/period, min_periods=period).mean()
    avg_loss = loss.ewm(alpha=1/period, min_periods=period).mean()
    rs = avg_gain / (avg_loss + 1e-10)
    return 100 - (100 / (1 + rs))


def _adx(df, period=14):
    high, low, close = df['high'], df['low'], df['close']
    plus_dm = high.diff()
    minus_dm = -low.diff()
    plus_dm = plus_dm.where((plus_dm > minus_dm) & (plus_dm > 0), 0.0)
    minus_dm = minus_dm.where((minus_dm > plus_dm) & (minus_dm > 0), 0.0)
    tr = pd.concat([high-low, (high-close.shift(1)).abs(), (low-close.shift(1)).abs()], axis=1).max(axis=1)
    atr = tr.rolling(period).mean()
    plus_di = 100 * (plus_dm.ewm(alpha=1/period, min_periods=period).mean() / (atr + 1e-10))
    minus_di = 100 * (minus_dm.ewm(alpha=1/period, min_periods=period).mean() / (atr + 1e-10))
    dx = 100 * (plus_di - minus_di).abs() / (plus_di + minus_di + 1e-10)
    return dx.ewm(alpha=1/period, min_periods=period).mean()
