# source: https://raw.githubusercontent.com/remiotore/freqtrade/44beaeb6a420cd8e9f2e4ea93e11d6cfa192ee03/strategies/RSIBB_V2.py
import talib.abstract as ta
import pandas as pd
import freqtrade.vendor.qtpylib.indicators as qtpylib
from pandas import DataFrame
from datetime import datetime
from freqtrade.persistence import Trade
from freqtrade.strategy import IStrategy


class Github_remiotore_freqtrade__RSIBB_V2__20260111_210550(IStrategy):
    INTERFACE_VERSION = 3
    timeframe = "5m"
    can_short = True
    use_exit_signal = False
    
    minimal_roi = {}
    stoploss = -0.01
    trailing_stop = False
    
    max_open_trades = 1
    
    @property
    def plot_config(self):
        return {
            'main_plot': {
                'bbu' : { 'color' : 'blue' },
                'bbm' : { 'color' : 'orange' },
                'bbl' : { 'color' : 'blue' },
                'sma' : { 'color' : 'blue' },
            },
            'subplots': {
                "RSI" : {
                    "rsi_fast" : { 'color' : 'yellow' },
                    "rsi_slow" : { 'color' : 'red' },
                }
            }
        }

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe["sma"] = ta.SMA(dataframe["close"], timeperiod=20)
        dataframe["atr"] = ta.ATR(dataframe["high"], dataframe["low"], dataframe["close"], timeperiod=14)
        
        dataframe["rsi_fast"] = ta.RSI(dataframe, timeperiod=6)
        dataframe["rsi_slow"] = ta.RSI(dataframe, timeperiod=12)
        
        bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
        dataframe['bbl'] = bollinger['lower']
        dataframe['bbm'] = bollinger['mid']
        dataframe['bbu'] = bollinger['upper']
        dataframe['bbw'] = dataframe['bbu'] - dataframe['bbl']
        
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                (qtpylib.crossed_above(dataframe["rsi_fast"], 70)) &
                (qtpylib.crossed_above(dataframe["close"], dataframe['bbu'])) &
                (dataframe["bbw"].diff() > 0) &
                (dataframe["rsi_fast"].diff() > 0) &
                (dataframe["rsi_slow"].diff() > 0)
            ),
            "enter_long"
        ] = 1

        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        return dataframe
    
    def custom_stoploss(self, pair: str, trade: Trade, current_time: datetime, 
                    current_rate: float, current_profit: float, **kwargs) -> float:

        df, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)

        if df.empty or 'atr' not in df.columns:
            return -0.10

        atr = df['atr'].iloc[-1]

        if pd.isna(atr) or atr <= 0:
            return -0.10

        stoploss = -max(0.04, min(atr / current_rate, 0.12))
        return stoploss

    def leverage(self, pair: str, current_time: datetime, current_rate: float, 
                proposed_leverage: float, max_leverage: float, side: str, **kwargs) -> float:
        df, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
        if len(df) < self.leverage_window_size.value:
            return proposed_leverage
        
        last_row = df.iloc[-1]
        rsi = last_row.get("rsi_slow", 50)
        atr = last_row.get("atr", 0)
        sma = last_row.get("sma", current_rate)
    
        lev = self.leverage_base.value

        if side == "long":

            if rsi < self.leverage_rsi_low.value:
                lev *= self.leverage_long_increase_factor.value

            elif rsi > self.leverage_rsi_high.value:
                lev *= self.leverage_long_decrease_factor.value
                
            if atr > 0 and current_rate > 0:
                volatility_ratio = atr / current_rate
                if volatility_ratio > self.leverage_atr_threshold_pct.value:
                    lev *= self.leverage_volatility_decrease_factor.value
                    
            if current_rate < sma:
                lev *= self.leverage_long_decrease_factor.value

        return round(max(1, min(lev, max_leverage)), 2)
