# source: https://raw.githubusercontent.com/remiotore/freqtrade/44beaeb6a420cd8e9f2e4ea93e11d6cfa192ee03/strategies/Klassi.py
# --- Do not remove these libs ---
from email.policy import default
from idna import valid_contextj
from freqtrade.strategy.interface import IStrategy # type: ignore
from typing import Dict, Optional, Union
from functools import reduce
from pandas import DataFrame
# --------------------------------
import talib.abstract as ta
import numpy as np
import freqtrade.vendor.qtpylib.indicators as qtpylib
import datetime
import pandas as pd
from technical.util import resample_to_interval, resampled_merge
from datetime import datetime, timedelta
from freqtrade.persistence import Trade
from freqtrade.strategy import stoploss_from_open, merge_informative_pair, DecimalParameter, IntParameter, CategoricalParameter
import technical.indicators as ftt
import logging
from datetime import datetime, timedelta
import helper_functions as helper


logger = logging.getLogger(__name__)


def calculate_chop(dataframe, period=14):
    df = dataframe.copy()
    high_n = df['high'].rolling(window=period).max()
    low_n = df['low'].rolling(window=period).min()  
    # محاسبه محدوده واقعی (TR)
    tr1 = df['high'] - df['low']
    tr2 = abs(df['high'] - df['close'].shift(1))
    tr3 = abs(df['low'] - df['close'].shift(1))
    tr = pd.concat([tr1, tr2, tr3], axis=1).max(axis=1)
    # مجموع محدوده واقعی (Sum TR) برای دوره n
    sum_tr = tr.rolling(window=period).sum()
    # محاسبه CHOP
    chop = 100 * np.log10(sum_tr / (high_n - low_n)) / np.log10(period)
    # مقادیر پایین CHOP (زیر 38.2) نشان‌دهنده بازاری با روند قوی است.
    # مقادیر بالای CHOP (بالای 61.8) نشان‌دهنده بازاری خنثی (بی‌روند) و پرنوسان است.
    return chop

# محاسبه‌ی میانگین وزنی محدوده (RWMA)
def range_ma(range_vals, price_vals, period):
    weights = range_vals / range_vals.rolling(window=period).sum()
    weighted_sum = (price_vals * weights).rolling(window=period).sum()
    total_weights = weights.rolling(window=period).sum()
    return weighted_sum / total_weights

def calculate_vsi(dataframe): # volume sensitivity index
    dataframe = dataframe.copy()
    # محاسبه تغییرات درصدی قیمت
    dataframe['price_change'] = dataframe['close'].pct_change()

    # محاسبه تغییرات درصدی حجم
    dataframe['volume_change'] = dataframe['volume'].pct_change()

    # محاسبه حساسیت به حجم
    dataframe['vsi'] = dataframe['price_change'] / dataframe['volume_change']
    
    # نرمال‌سازی VSI
    dataframe['vsi_normalized'] = (dataframe['vsi'] - dataframe['vsi'].min()) / (dataframe['vsi'].max() - dataframe['vsi'].min())
    
    return dataframe['vsi_normalized']


# def ConDi(dataframe, dataframe1, dataframe2):
#     # ابتدا ستون ConDi رو با مقدار پیش‌فرض 0 ایجاد می‌کنیم
#     dataframe['ConDi'] = 0
    
#     # شرط برای همگرایی (هر دو به سمت بالا یا هر دو به سمت پایین)
#     dataframe.loc[
#         ((dataframe1 > dataframe1.shift(1)) & (dataframe2 > dataframe2.shift(1))) |
#         ((dataframe1 < dataframe1.shift(1)) & (dataframe2 < dataframe2.shift(1))),
#         'ConDi'
#     ] = 1
    
#     # شرط برای واگرایی (یکی به سمت بالا و دیگری به سمت پایین)
#     dataframe.loc[
#         ((dataframe1 > dataframe1.shift(1)) & (dataframe2 < dataframe2.shift(1))) |
#         ((dataframe1 < dataframe1.shift(1)) & (dataframe2 > dataframe2.shift(1))),
#         'ConDi'
#     ] = -1
    
#     return dataframe['ConDi']

def ConDi(dataframe, dataframe1, dataframe2):
    dataframe['ConDi'] = 0
    dataframe.loc[
        ((dataframe1 > dataframe1.shift(1)) & (dataframe2 > dataframe2.shift(1))) |
        ((dataframe1 < dataframe1.shift(1)) & (dataframe2 < dataframe2.shift(1))),
        'ConDi'
    ] = 1
    dataframe.loc[
        ((dataframe1 > dataframe1.shift(1)) & (dataframe2 < dataframe2.shift(1))) |
        ((dataframe1 < dataframe1.shift(1)) & (dataframe2 > dataframe2.shift(1))),
        'ConDi'
    ] = -1
    return dataframe['ConDi']

def hma_volume(dataframe, period ):
    wma_1 = dataframe['nominal'].rolling(period//2).sum()/dataframe['volume'].rolling(period//2).sum()
    wma_2 = dataframe['nominal'].rolling(period).sum()/dataframe['volume'].rolling(period).sum()
    diff = 2 * wma_1 - wma_2
    hma = diff.rolling(int(np.sqrt(period))).mean()
    return hma

def Market_Stability_index(current_price, last_halving_price=63000, next_halving_price= 179000, last_halving_date=(datetime(2024,4, 26)), next_halving_date=(datetime(2028, 4,1))):
    days_between_halvings= (next_halving_date-last_halving_date).days
    days_since_last_halving= (datetime.now()-last_halving_date).days
    real_BTC_price= last_halving_price + (next_halving_price-last_halving_price)* (days_since_last_halving/days_between_halvings)
    stability_index = ((real_BTC_price - current_price)/ current_price)*100
    return stability_index 

def cross(dataframe1, dataframe2):
    cross_up = (dataframe1 > dataframe2) & (dataframe1.shift(1) < dataframe2.shift(1))
    cross_down = (dataframe2 > dataframe1) & (dataframe2.shift(1) < dataframe1.shift(1))
    
    if cross_up.iloc[-1]:
        return 1
    elif cross_down.iloc[-1]:
        return -1
    return 0

class Github_remiotore_freqtrade__Klassi__20260111_210550(IStrategy):
    INTERFACE_VERSION = 3
    can_short = True
    # Stoploss:
    stoploss = -0.33
    max_open_trades = 6     # Max Open Trades
    entry_tags_limit = 2   # limit per entry tag
    max_leverage = 15.0
    wave_length = 0
    # ROI table:
    minimal_roi = {
        "0": 0.264,     #     "0": 0.219,
        "31": 0.093,    #     "24": 0.087,
        "52": 0.026,    #     "67": 0.024,
        "94": 0         #     "164": 0
    }
    
    
    custom_roi= {
        "0": 0.05,
        "60": 0
    }
    
        # Leverage configuration
    leverage_configuration = {}

    # Create custom dictionary for storing run-time data
    custom_info = {}
    
    def __init__(self, config: Dict) -> None:
        super().__init__(config)


    # Buy hyperspace params:
    buy_params = {
        "base_nb_candles_buy": 12,
        "low_offset": 0.979, #--> Original Value is 0.915
        "long_WAD": -80,
        "long_rsi": 30,
    }

    # Sell hyperspace params:
    sell_params = {
        "base_nb_candles_sell": 72,
        "high_offset": 1.008,
        "short_WAD": -20,
        "short_rsi": 70
    }

    # Variables:
    base_nb_candles_buy = IntParameter(5, 80, default=buy_params['base_nb_candles_buy'], space='buy', optimize=False)
    base_nb_candles_sell = IntParameter(5, 80, default=sell_params['base_nb_candles_sell'], space='sell', optimize=False)
    low_offset = DecimalParameter(0.9, 0.99, default=buy_params['low_offset'], space='buy', optimize=False)
    high_offset = DecimalParameter(0.99, 1.1, default=sell_params['high_offset'], space='sell', optimize=False)
    atr_period = IntParameter(5, 30, default=14, space='stoploss', optimize=False)
    atr_multiplier = DecimalParameter(1.0, 30.0, default=10.0, space='stoploss', optimize=False)
    fast_ewo = 50
    slow_ewo = 200
    short_WAD = IntParameter(-35, 0, default=sell_params['short_WAD'], space='sell', optimize= False)
    long_WAD = IntParameter(-100, -65, default= buy_params['long_WAD'], space= 'buy', optimize= False)
    short_rsi = IntParameter(51,100, default = sell_params['short_rsi'], space= 'sell', optimize= False)
    long_rsi = IntParameter(0,49, default = buy_params['long_rsi'], space= 'buy', optimize= False)
    ket_stead = DecimalParameter(0.0, 0.1 , default=0.001, space='buy', optimize=True)
    ichimoku_period1=50
    ichimoku_period2=100
    ichimoku_period3=300
    BBperiod= 250
    roc_period= 14
    pmom = 66
    nmom = 30
    

    
    #for calculation of coral trend
    ema_fast_period=50
    ema_slow_period=200
    # cci_period=IntParameter(30, 200, default=150, space= "buy", optimize=True)
    cci_threshold=IntParameter(0, 200, default=200, space = "buy", optimize=False)
    cci_period= 15
    
    # Trailing stop:
    trailing_stop = True
    trailing_stop_positive = 0.03 #---> 0.002 is Original Value
    trailing_stop_positive_offset = 0.11 #--> 0.055 is Original Value
    trailing_only_offset_is_reached = True
    
    # Sell signal
    use_exit_signal = True
    exit_profit_only = True
    exit_profit_offset = 0.10
    ignore_roi_if_entry_signal = True
    
    # Optimal timeframe for the strategy
    timeframe = '5m'
    informative_timeframe1 = '1h'
    informative_timeframe2 = '4h'
    informative_timeframe3 = '1d'
    informative_pair= 'BTC/USDT:USDT'
    process_only_new_candles = True
    startup_candle_count = 200
    plot_config = {
        "main_plot": {
            "kama": {
            "color": "#e392fe",
            "type": "line"
            },
            "ema": {
            "color": "#f2751a",
            "type": "line"
            },
            "kc_upper": {
            "color": "#5c0700",
            "type": "line"
            },
            "kc_lower": {
            "color": "#263e0f",
            "type": "line"
            },
            "ema2": {
            "color": "#ccde01"
            },
            "kama_1h": {
            "color": "#be38f3",
            "type": "line"
            },
            "kama_4h": {
            "color": "#61177c",
            "type": "line"
            },
            "EMA_1h": {
            "color": "#d29d00",
            "type": "line"
            },
            "EMA_4h": {
            "color": "#785700",
            "type": "line"
            },
            "highBand": {
            "color": "#c0c0c0",
            "type": "line"
            },
            "lowBand": {
            "color": "#aaaaaa",
            "type": "line"
            },
            "vwap": {
            "color": "#3ef4e2"
            }
        },
        "subplots": {
            "Trends": {
            "long_slope": {
                "color": "#ff2600",
                "type": "line"
            },
            "short_slope": {
                "color": "#00f900",
                "type": "line"
            },
            "long_kama_1h": {
                "color": "#00f900",
                "type": "line"
            },
            "long_kama_4h": {
                "color": "#00f900",
                "type": "line"
            },
            "short_kama_4h": {
                "color": "#ff2600",
                "type": "line"
            },
            "long_kama": {
                "color": "#00f900",
                "type": "line"
            },
            "short_kama": {
                "color": "#ff2600",
                "type": "line"
            },
            "short_ema_1h": {
                "color": "#ff2600",
                "type": "line"
            },
            "long_ema_1h": {
                "color": "#00f900",
                "type": "line"
            },
            "long_ema_4h": {
                "color": "#00f900",
                "type": "line"
            },
            "short_ema_4h": {
                "color": "#ff2600",
                "type": "line"
            },
            "short_kama_1h": {
                "color": "#ff2600",
                "type": "line"
            },
            "long_WM2": {
                "color": "#00f900",
                "type": "line"
            },
            "short_WM2": {
                "color": "#ff2600",
                "type": "line"
            },
            "short_adx": {
                "color": "#ff2600",
                "type": "line"
            },
            "long_adx": {
                "color": "#00f900",
                "type": "line"
            },
            "long_adx_1h": {
                "color": "#00f900",
                "type": "line"
            },
            "short_adx_1h": {
                "color": "#ff2600",
                "type": "line"
            },
            "long_adx_4h": {
                "color": "#00f900",
                "type": "line"
            },
            "short_adx_4h": {
                "color": "#ff2600",
                "type": "line"
            }
            },
            "WilliamR%": {
            "WAD": {
                "color": "#f1c9fe",
                "type": "line"
            },
            "WM1": {
                "color": "#d357fe",
                "type": "line"
            },
            "WM2": {
                "color": "#61177c",
                "type": "line"
            },
            "WM0": {
                "color": "#b18cfe",
                "type": "line"
            }
            },
            "POWER": {
            "kama_slope": {
                "color": "#ff4013",
                "type": "line"
            }
            },
            "ADX": {
            "ADX": {
                "color": "#ffe2d6",
                "type": "line"
            },
            "ADX_4h": {
                "color": "#ff6a00",
                "type": "line"
            },
            "ADX_1h": {
                "color": "#ffc677",
                "type": "line"
            }
            },
            "RSI": {
            "RSI_4h": {
                "color": "#d29d00",
                "type": "line"
            },
            "RSI": {
                "color": "#fefcdd",
                "type": "line"
            },
            "RSI_1h": {
                "color": "#ffd877",
                "type": "line"
            }
            },
            "ATR%": {
            "atrpct": {
                "color": "#f8fadb",
                "type": "line"
            },
            "atrpct_4h": {
                "color": "#669c35",
                "type": "line"
            },
            "atrpct_1h": {
                "color": "#b1dd8c",
                "type": "line"
            }
            },
            "v": {
            "volume_ema": {
                "color": "#00a3d7",
                "type": "line"
            }
            }
        }
        }
    use_custom_stoploss = False
    
    # For postition sizing
    # risk_per_trade = 0.02  # Risking 2% of total capital per trade
    # stop_loss_distance = abs(trade.entry_price - stop_loss)
    # position_size = (total_capital * risk_per_trade) / stop_loss_distance
    
    @property
    def protections(self):
        return [
            {
                "method": "StoplossGuard",
                "lookback_period_candles": 24,
                "trade_limit": 1,
                "stop_duration_candles": 288,
                "only_per_pair": True
            },
            {
                "method": "LowProfitPairs",
                "lookback_period_candles": 12,
                "stop_duration": 144,
                "required_profit": -0.1,
                "only_per_pair": True,
            }
        ]
        
    def cleanup_cache(self):
        """ 
        Cleanup the cache with stored dataframes if the last updated time has passed (with a margin of two minutes).
        """

        outdatedkeys = []

        currentdatetime = datetime.now()
        for key in self.custom_info['cache']:
            minutes = (currentdatetime - self.custom_info['cache'][key]['datetime']).total_seconds() / 60
            
            if (minutes - 2) > timeframe_to_minutes(self.custom_info['cache'][key]['tf']):
                outdatedkeys.append(key)

                self.log(f"Removing cache storage for '{key}' because last update was {minutes} minutes ago")

        for key in outdatedkeys:
            del self.custom_info['cache'][key]
            
    def bot_start(self, **kwargs) -> None:
        """
        Called only once after bot instantiation.
        :param **kwargs: Ensure to keep this here so updates to this won't break your strategy.
        """
    
        # Setup cache for dataframes
        self.custom_info['cache'] = {}

        # Setup removal of autolocks
        self.custom_info['remove-autolock'] = []
        
        self.open_trades_tags = [] # Track open trades and their entry tags with timestamps
        self.trade_exit_times = [] # Track the exit times to prevent next trades

        # Call to super first
        super().bot_start()
    def bot_loop_start(self, current_time: datetime, **kwargs) -> None:
        """
        Called at the start of the bot iteration (one loop).
        Might be used to perform pair-independent tasks
        (e.g. gather some remote resource for comparison)
        :param current_time: datetime object, containing the current datetime
        :param **kwargs: Ensure to keep this here so updates to this won't break your strategy.
        """

        # Run the cleanup of cache once every five minutes
        if current_time.minute % 5 == 0 and current_time.second <= 10:
            self.cleanup_cache()

        # Check if there are pairs set for which the Auto lock should be reoved
        if len(self.custom_info['remove-autolock']) > 0:
            self.unlock_reason("Auto lock")

            # Sanity check to alert when removing the lock failed
            for pair in self.custom_info['remove-autolock']:
                lock = self.is_locked_until(pair)
                if lock:
                    self.log(
                        f"{pair} has still an active lock until {lock}, while it should have been removed!",
                        level="ERROR"
                    )

            # Clear the list
            self.custom_info['remove-autolock'].clear()

        return super().bot_loop_start(current_time)

    def informative_pairs(self):
        pairs = self.dp.current_whitelist()
        informative_pairs = [(pair, self.informative_timeframe1) for pair in pairs] # 1h
        informative_pairs += [(pair, self.informative_timeframe2) for pair in pairs] # 4h
        informative_pairs += [(pair, self.informative_timeframe3) for pair in pairs] # 1d
        informative_pairs += [(self.informative_pair, self.timeframe)]
        return informative_pairs

    def get_informative_indicators(self, metadata: dict):
        dataframe = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.informative_timeframe1)
        return dataframe  

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:    
        if not self.dp:
            # Don't do anything if DataProvider is not available.
            return dataframe  
        
        informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.informative_timeframe1)
        informative['kama'] = ta.KAMA(informative, period= 50, fast_ema= 3, slow_ema=21)
        informative.loc[(informative['kama'].shift(1) > informative['kama']),'short_kama'] = 2  
        informative.loc[(informative['kama'].shift(1) < informative['kama']),'long_kama'] = 2  
        informative['kama_slope'] = (informative['kama']/informative['kama'].shift(1)) * 1000 - 1000   # kama_slope over 2 means a little trend has been started like  a trap. use for not_buy
        informative['RSI'] = ta.RSI(informative, period=14)
        informative['rsi_ma'] =  ta.SMA(informative['RSI'] , period = 5 )
        informative['ATR'] = ta.ATR(informative, period= 14)
        informative['ADX'] = ta.ADX(informative, period= 21)
        informative.loc[(informative['ADX'].shift(1) < informative['ADX']),'long_adx'] = 6
        informative.loc[(informative['ADX'].shift(1) > informative['ADX']),'short_adx'] = 6    
        informative['EMA'] = ta.EMA(informative, period=21)
        informative.loc[(informative['EMA'].shift(1) > informative['EMA']),'short_ema'] = 2.5  
        informative.loc[(informative['EMA'].shift(1) < informative['EMA']),'long_ema'] = 2.5  
        informative['chop'] = calculate_chop(informative, 14)
        informative['nominal'] = informative['close'] * informative['volume']
        informative['HMA'] = hma_volume(informative, period= 7)
        
        dataframe = merge_informative_pair(dataframe, informative, self.timeframe, self.informative_timeframe1, ffill=True)  

        informative2 = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.informative_timeframe2)  # داده‌های تایم‌فریم دوم
        informative2['kama'] = ta.KAMA(informative2, period= 50, fast_ema= 3, slow_ema=21)
        informative2.loc[(informative2['kama'].shift(1) > informative2['kama']),'short_kama'] = 3  
        informative2.loc[(informative2['kama'].shift(1) < informative2['kama']),'long_kama'] = 3 
        informative2['kama_slope'] = (informative2['kama']/informative2['kama'].shift(1)) * 1000 - 1000   # kama_slope over 2 means a little trend has been started like  a trap. use for not_buy
        informative2['RSI'] = ta.RSI(informative2, period=14)
        informative2['ATR'] = ta.ATR(informative2, period=14)
        informative2['MFI'] = ta.MFI(dataframe, timeperiod=14)
        informative2.loc[(informative2['MFI'].shift(1) > informative2['MFI']),'short_mfi'] = 1  
        informative2.loc[(informative2['MFI'].shift(1) < informative2['MFI']),'long_mfi'] = 1 
        informative2['ADX'] = ta.ADX(informative2, period=21)
        informative2.loc[(informative2['ADX'].shift(1) > informative2['ADX']),'short_adx'] = 7  
        informative2.loc[(informative2['ADX'].shift(1) < informative2['ADX']),'long_adx'] = 7 
        informative2['EMA'] = ta.EMA(informative2, period=21)
        informative2.loc[(informative2['EMA'].shift(1) > informative2['EMA']),'short_ema'] = 3.5  
        informative2.loc[(informative2['EMA'].shift(1) < informative2['EMA']),'long_ema'] = 3.5 
        informative2['WAD'] = ta.WILLR(informative2, timeperiod=50)
        informative2['wad_sma'] = ta.SMA(informative2, period = 5 )
        informative2['chop'] = calculate_chop(informative2, 14)
        informative2['nominal'] = informative2['close'] * informative2['volume']
        informative2['HMA'] = hma_volume(informative2, period= 5)
        dataframe = merge_informative_pair(dataframe, informative2, self.timeframe, self.informative_timeframe2, ffill=True)
        
        informative3 = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.informative_timeframe3)  # داده‌های تایم‌فریم دوم
        informative3['kama'] = ta.KAMA(informative3, period= 50, fast_ema= 3, slow_ema=21)
        informative3.loc[(informative3['kama'].shift(1) > informative3['kama']),'short_kama'] = 4  
        informative3.loc[(informative3['kama'].shift(1) < informative3['kama']),'long_kama'] = 4 
        informative3['kama_slope'] = (informative3['kama']/informative3['kama'].shift(1)) * 1000 - 1000   # kama_slope over 2 means a little trend has been started like  a trap. use for not_buy
        informative3['chop'] = calculate_chop(informative3, 14)
        dataframe = merge_informative_pair(dataframe, informative3, self.timeframe, self.informative_timeframe3, ffill=True)
        
        btc_price = self.dp.get_pair_dataframe(pair=self.informative_pair, timeframe=self.timeframe)
        dataframe = merge_informative_pair(dataframe, btc_price, self.timeframe, self.timeframe, ffill=True)
        
        drop_columns = [f"{s}_{self.timeframe}" for s in ['date', 'open', 'high', 'low', 'volume']]
        drop_columns += [f"{s}_{self.informative_timeframe1}" for s in ['date', 'open', 'high', 'low', 'volume']]
        drop_columns += [f"{s}_{self.informative_timeframe2}" for s in ['date', 'open', 'high', 'low', 'volume']]
        drop_columns += [f"{s}_{self.informative_timeframe3}" for s in ['date', 'open', 'high', 'low', 'volume']]
        dataframe.drop(columns=dataframe.columns.intersection(drop_columns), inplace=True)
        # ------------ SPREAD CALCULATOR TO CALC LEVERAGE ------------------------------
        dataframe['spread'] = 100 * abs(dataframe['high'] - dataframe['low']) / dataframe['close']
        dataframe['spread_avg'] = dataframe['spread'].rolling(window=200).mean()
        dataframe['spread_avg_small'] = ta.SMA(dataframe['spread'], timeperiod = 5)
        
        # ------------ TREND INDICATORS ------------------------------------------------
        dataframe['kama'] = ta.KAMA(dataframe, window=50, pow1=4, pow2=12, fillna=True)
        dataframe['kama_'] = ta.KAMA(dataframe['close'], timeperiod=7, fastlimit=0.02, slowlimit=0.666)
        dataframe.loc[(dataframe['kama'].shift(1) > dataframe['kama']),'short_kama'] = 1  
        dataframe.loc[(dataframe['kama'].shift(1) < dataframe['kama']),'long_kama'] = 1    
        
        dataframe['ema'] = ta.SMA(dataframe, timeperiod=13)
        dataframe.loc[(dataframe['ema'].shift(1) > dataframe['ema']),'down_ema'] = 2  
        dataframe.loc[(dataframe['ema'].shift(1) < dataframe['ema']),'long_ema'] = 2    
        dataframe['ema200'] = ta.EMA(dataframe, timeperiod = 200)
        dataframe['ema5'] = ta.EMA(dataframe, timeperiod = 5)
        dataframe['nominal'] = dataframe['close'] * dataframe['volume']
        
        dataframe['HMA'] = hma_volume(dataframe, period= 9)
        
        typical_price = (dataframe['high'] + dataframe['low'] + dataframe['close']) / 3
        vwap = (typical_price * dataframe['volume']).cumsum() / dataframe['volume'].cumsum()
        dataframe['vwap'] = vwap


        dataframe['volume_ema'] = ta.EMA(dataframe['volume'], timeperiod=20)
        dataframe.loc[
            (dataframe['vwap'] < dataframe ['vwap'].shift(1)),
            'short_vwap'] = 1.5
        dataframe.loc[
            dataframe['vwap'] > dataframe ['vwap'].shift(1),
            'long_vwap'] = 1.5
        
        # ------------------------- POWER -------------------------------
        dataframe['ADX'] = ta.ADX(dataframe, timeperiod=21)
        dataframe.loc[(dataframe['ADX'].shift(1) > dataframe['ADX']),'short_adx'] = 5  
        dataframe.loc[(dataframe['ADX'].shift(1) < dataframe['ADX']),'long_adx'] = 5    
        
                # ATR for setting dynamic stop loss and take profit
        dataframe['ATR'] = ta.ATR(dataframe, timeperiod=14)
        dataframe['atrpct'] = (dataframe['ATR']/dataframe['close'])*100
        dataframe['atrpct_1h'] = (dataframe['ATR_1h']/dataframe['close'])* 100
        dataframe['atrpct_4h'] = (dataframe['ATR_4h']/dataframe['close_4h'])*100
        
        dataframe['band'] = np.minimum(dataframe['ATR'] * 0.3, dataframe['close'] * (0.3 / 100))
        
        dataframe['vwap_upper'] = dataframe['vwap'] + 1.7 * dataframe['ATR']
        dataframe['vwap_lower'] = dataframe['vwap'] - 1.7 * dataframe['ATR']
        
        dataframe['diff_kamavwap']= dataframe['kama'] - dataframe['vwap']
        dataframe['diff_kamavwap_sma'] = ta.EMA(dataframe['diff_kamavwap'], timeperiod = 7)
        dataframe['der_diff_kamavwap'] = dataframe['diff_kamavwap_sma'].diff()/dataframe['close']
        dataframe['der_diff_kamavwap_sma'] = ta.EMA(dataframe['der_diff_kamavwap'], timeperiod = 7)
        dataframe['der_diff_kamavwap_slope'] = dataframe['der_diff_kamavwap_sma']/dataframe['der_diff_kamavwap_sma'].shift(1)

        
        dataframe['distance_index'] = dataframe['diff_kamavwap_sma']/dataframe['close']
        dataframe['diff_kamavwap_slope'] = dataframe['diff_kamavwap'] / dataframe['diff_kamavwap'].shift(1)
        dataframe['diff_kamavwap_slope_sma'] = ta.SMA(dataframe['diff_kamavwap_slope'], timeperiod = 3)
        #--------------------------OSCILLATORS-----------------------------
        dataframe['RSI'] = ta.RSI(dataframe, timeperiod=14)
        dataframe['rsi_ma'] = ta.SMA(dataframe['RSI'], timeperiod=8)
        dataframe['L_rsi_thres'] = (dataframe['distance_index'] * 100) + 25
        dataframe['S_rsi_thres'] = (dataframe['distance_index'] * 100) + 75
        
        dataframe['MFI'] = ta.MFI(dataframe, timeperiod=14)
        
        dataframe['rsi_mfi'] = (dataframe['MFI'] + dataframe['RSI']) / 2
        
        dataframe['cci'] = ta.CCI(dataframe['high'], dataframe['low'], dataframe['close'], timeperiod=self.cci_period)  
                # محاسبه شاخص تراکم-توزیع ویلیامز (WAD)
        dataframe['WAD'] = ta.WILLR(dataframe, timeperiod=50)
        dataframe['wad_sma']= ta.SMA(dataframe['WAD'], timeperiod = 3)
        dataframe['WM0'] = ta.SMA(dataframe['WAD'], timeperiod= 15)
        dataframe['WM1'] = ta.SMA(dataframe['WAD'], timeperiod=50)
        dataframe['WM2'] = ta.SMA(dataframe['WAD'], timeperiod=200)
        
        dataframe['long_rsi_threshold'] = 25 + (50 + dataframe['WM1']) / 2
        dataframe['short_rsi_threshold'] = 75 + (50 + dataframe['WM1']) / 2
        dataframe['diff_rsi'] = dataframe['long_rsi_threshold'].diff()
        
        dataframe['chop'] = calculate_chop(dataframe, 14)
        dataframe['chop_ma'] = ta.SMA(dataframe['chop'], 21)

        #------------------Market Stability Index  and indicators based on it ----------------------------
        dataframe['MIndex']= Market_Stability_index(dataframe['close_5m'] ,last_halving_price=63000, next_halving_price= 179000, last_halving_date=(datetime(2024,4, 26)), next_halving_date=(datetime(2028, 4,1)))
        dataframe['long_wad_threshold'] = (dataframe['MIndex'] + 70) * -1
        dataframe['short_wad_threshold']  = (30 - dataframe['MIndex']  )* -1
        
        
        #----------------------------------
        # Keltner Channel Calculation
        dataframe['kc_middle'] = ta.EMA(dataframe['close'], timeperiod=20)
        dataframe['kc_upper'] = dataframe['kc_middle'] + (ta.ATR(dataframe, timeperiod=14) * 1.5)  # Modified to 1.5x ATR for crypto
        dataframe['kc_lower'] = dataframe['kc_middle'] - (ta.ATR(dataframe, timeperiod=14) * 1.5)
        
        # --------------- DERIVITIVES --------------------------
        dataframe['typical_price'] = typical_price
        dataframe['kama_slope'] = (dataframe['kama']/dataframe['kama'].shift(1)) * 1000 - 1000   # kama_slope over 2 means a little trend has been started like  a trap. use for not_buy
        
        dataframe['der1_price'] = (dataframe['kama'] / dataframe['kama'].shift(1)) * 1000 - 1000 
        dataframe.loc[dataframe['der1_price'] > 10, 'der1_price'] = 10
        dataframe.loc[dataframe['der1_price'] < - 10, 'der1_price'] = -10            
        dataframe['der1_price_sma'] = ta.SMA(dataframe['der1_price'], timeperiod = 5)
               
        dataframe['der2_price'] = (dataframe['der1_price_sma']/dataframe['der1_price_sma'].shift(1)) * 10000 - 10000
        dataframe.loc[dataframe['der2_price'] > 10, 'der2_price'] = 10
        dataframe.loc[dataframe['der2_price'] < -10, 'der2_price'] = -10
        dataframe['der2_price_sma'] = ta.SMA(dataframe['der2_price'], timeperiod = 5)
        
        
        # ------------------ Wave length calculations ----------------------
        dataframe['cross_result'] = cross(dataframe['close'], dataframe['vwap'])

        # ---------------------------------- COnvergence divergence -------------------
        dataframe['condi_rsi_kama'] = ConDi(dataframe, dataframe['rsi_ma'], dataframe['ema'])
        dataframe['condi_wad_ema'] =  ConDi(dataframe, dataframe['wad_sma'] , dataframe['ema'])
        dataframe['condi_rsi_hma'] = ConDi(dataframe, dataframe['rsi_ma_1h'], dataframe['HMA_1h'])
        dataframe['condi_wad_hma'] = ConDi(dataframe, dataframe['wad_sma_4h'], dataframe['HMA_4h'])
        dataframe['condi_ema_hma'] = ConDi(dataframe, dataframe['ema'], dataframe['HMA'])
        
        dataframe['p_mom'] = (dataframe['rsi_mfi'].shift(1) < self.pmom) & (dataframe['rsi_mfi'] > self.pmom) & (dataframe['ema5'].diff() > 0)
        dataframe['n_mom'] = (dataframe['rsi_mfi'].shift(1) > self.nmom) & (dataframe['rsi_mfi'] < self.nmom) & (dataframe['ema5'].diff() < 0)
        # dataframe['rwma'] = range_ma(dataframe['high'] - dataframe['low'], dataframe['close'], 20)
        # dataframe['rwma_band_upper'] = dataframe['rwma'] + dataframe['band']
        # dataframe['rwma_band_lower'] = dataframe['rwma'] - dataframe['band']
        dataframe['STOCH_K'], dataframe['STOCH_D'] = ta.STOCH(dataframe['high'], dataframe['low'], dataframe['close'],
                                             fastk_period=14, slowk_period=3, slowd_period=3,
                                             slowk_matype=0, slowd_matype=0)
        
        
        # ---------------------------------- BTC Dominance data -----------------------

        
        
        
        
        #_-_____NOT CLEANED BELOW

        dataframe['atf'] = 0    
        dataframe.loc[(
            (dataframe['diff_kamavwap_slope']>1 ) &
            (dataframe['diff_kamavwap_slope'].shift(1)<1)), 'atf'
        ] = 1
        dataframe.loc[(
            (dataframe['diff_kamavwap_slope']<1 ) &
            (dataframe['diff_kamavwap_slope'].shift(1)>1)), 'atf'
        ] = -1        
    
        dataframe['vwap_slope'] = (dataframe['vwap']/dataframe['vwap'].shift(1))*1000 - 1000


        
        # dataframe['kamadiff_normalized']= (dataframe['kamadiff'] - dataframe['kamadiff'].min()) / (dataframe['kamadiff'].max() - dataframe['kamadiff'].min())
        

        dataframe['is_wave'] = np.where(
            ((abs(dataframe['diff_kamavwap_slope'] - 1 ) < 0.01 )),
            0 , 1)
        
        dataframe['vsi'] = calculate_vsi(dataframe)
        
                # Calculate new indicators and conditions for entry

        # Calculate Price Volatility Index (item 2)
        dataframe['price_volatility'] = abs(dataframe['close'] - dataframe['close'].shift(1)) / dataframe['volume_ema']

        # Dynamic Slope for Entry Signals (item 3)
        dataframe['kama_vwap_slope'] = (dataframe['kama'] - dataframe['vwap']).diff() / dataframe['close']
        dataframe['kama_vwap_slope_sma'] = ta.SMA(dataframe['kama_vwap_slope'], timeperiod=7)

        # Williams Accumulation Distribution (WAD) - Strengthen Signals (item 5)
        dataframe['wad_support'] = (dataframe['WAD'] > dataframe['WM1']) # Bullish support
        dataframe['wad_resistance'] = (dataframe['WAD'] < dataframe['WM1']) # Bearish resistance
        
        # Adding Dynamic ADX Condition for Strong Trend Confirmation
        dataframe['ADX'] = ta.ADX(dataframe, timeperiod=21)
        dataframe['adx_trend'] = (dataframe['ADX'] > 25)  # Filter only strong trends

        # Bollinger Bands to filter high volatility breakouts
        dataframe['bb_upper'], dataframe['bb_middle'], dataframe['bb_lower'] = ta.BBANDS(dataframe['close'], timeperiod=20)
        dataframe['bb_width'] = (dataframe['bb_upper'] - dataframe['bb_lower']) / dataframe['bb_middle']  # Bollinger Width
        dataframe['low_volatility'] = dataframe['bb_width'] < 0.1  # Low volatility indication

        # Adding ATR as a Dynamic Volatility Filter
        dataframe['atr_threshold'] = dataframe['ATR'] < dataframe['ATR'].rolling(window=20).mean()  # Low ATR indication

        # Volume Indicator for additional confirmation
        dataframe['volume_sma'] = ta.SMA(dataframe['volume'], timeperiod=20)
        dataframe['high_volume'] = dataframe['volume'] > dataframe['volume_sma'] * 1.5  # Volume spike confirmation

        # Enhanced RSI Sensitivity
   
        dataframe['rsi_bullish'] = dataframe['RSI'] > 50  # Uptrend confirmation with RSI
        dataframe['rsi_bearish'] = dataframe['RSI'] < 50  # Downtrend confirmation with RSI
        
        dataframe.loc[
            (dataframe['der_diff_kamavwap_sma'] < dataframe['kama_vwap_slope_sma']) 
            ,'not_short'] = True
        dataframe.loc[
            (dataframe['der_diff_kamavwap_sma'] > dataframe['kama_vwap_slope_sma']) 
            ,'not_short'] = True 





        return dataframe
    
    def get_open_trades(self):
        # Fetch all open trades
        return Trade.get_open_trades()

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        
        
        # --------------------------------GPT -------------------------
        
        #         Updated Long Entry Conditions
        # پیشرفته سازی سیگنال ورود Long
        # dataframe.loc[
        #     (dataframe['typical_price'] > dataframe['vwap']) &
        #     (dataframe['long_vwap'] == 1.5) &
        #     (dataframe['adx_trend']) &
        #     (dataframe['wad_support']) &
        #     (dataframe['chop'] < 68.1) &
        #     (abs(dataframe['kama_vwap_slope_sma']) > 0.002) &
        #     (dataframe['price_volatility'] < 0.1) &
        #     (dataframe['high_volume']) &
        #     (dataframe['rsi_bullish']) &
        #     (dataframe['low_volatility']),
        #     ['enter_long', 'enter_tag']] = (1, 'Advanced_kama_vwap_adx')

        # # پیشرفته سازی سیگنال ورود Short
        # dataframe.loc[
        #     (dataframe['typical_price'] < dataframe['vwap']) &
        #     (dataframe['short_vwap'] == 1.5) &
        #     (dataframe['adx_trend']) &
        #     (dataframe['wad_resistance']) &
        #     (dataframe['chop'] < 68.1) &
        #     (abs(dataframe['kama_vwap_slope_sma']) > 0.002) &
        #     (dataframe['price_volatility'] < 0.1) &
        #     (dataframe['high_volume']) &
        #     (dataframe['rsi_bearish']) &
        #     (dataframe['low_volatility']),
        #     ['enter_short', 'enter_tag']] = (1, 'Advanced_kama_vwap_adx')

        
        # ----------------------------- Based on RSI --------------------
        # dataframe.loc[(
        #     (dataframe['der_diff_kamavwap_sma'] > dataframe['kama_vwap_slope_sma'] ) &
        #     (dataframe['der_diff_kamavwap_sma'].shift(1) < dataframe['kama_vwap_slope_sma'].shift(1) ) &
        #     (dataframe['der_diff_kamavwap_sma'] > 0.002 ) & 
        #     (dataframe['short_vwap'] == 1.5) &
        #     (dataframe['STOCH_D'] > dataframe['STOCH_K']) &
        #     (dataframe['volume'] > 100 )
        # ), ['enter_short', 'enter_tag']] = (1, 'der')
        # dataframe.loc[(
        #     (dataframe['der_diff_kamavwap_sma'] < dataframe['kama_vwap_slope_sma'] ) &
        #     (dataframe['der_diff_kamavwap_sma'].shift(1) > dataframe['kama_vwap_slope_sma'].shift(1) ) &
        #     (dataframe['der_diff_kamavwap_sma'] < -0.002 ) & 
        #     (dataframe['STOCH_D'] < dataframe['STOCH_K']) &
        #     (dataframe['long_vwap'] == 1.5) &
        #     (dataframe['volume'] > 100 )
        # ), ['enter_long', 'enter_tag']] = (1, 'der')

        # --------------------------------Trend Market Entries-----------------------------------

        # ----------------Based on kama, ema WAD (wad calculated based on MIndex) ------------
        dataframe.loc[(
            (dataframe['ADX'] > 30) &  # Ensure market is trending
            (dataframe['is_wave'] == 1 ) &
            (dataframe['condi_wad_ema'] == 1 ) &
            (dataframe['condi_rsi_kama'] == 1 ) &
            (dataframe['RSI'] < dataframe['long_rsi_threshold'] ) & #30
            (dataframe['RSI_1h'] < 40 ) &
            (dataframe['wad_sma'] < dataframe['long_wad_threshold']) &
            (dataframe['close'] < dataframe['kama']) &
            (dataframe['long_vwap'] == 1.5) &
            (dataframe['volume'] > 1000)
        ), ['enter_long', 'enter_tag']] = (1, 'kemaMIx')

        dataframe.loc[(
            (dataframe['ADX'] > 30) &  # Ensure market is trending
            (dataframe['is_wave'] == 1 ) &
            (dataframe['condi_wad_ema'] == 1 ) &
            (dataframe['condi_rsi_kama'] == 1 ) &
            (dataframe['RSI'] > dataframe['short_rsi_threshold']) & #70 
            (dataframe['wad_sma'] > dataframe['short_wad_threshold']) &
            (dataframe['close'] > dataframe['kama']) &
            (dataframe['short_vwap'] == 1.5) &
            (dataframe['volume'] > 1000)
        ), ['enter_short', 'enter_tag']] = (1, 'kemaMIx')
        # -------- based on cross of EMA200 and KAMA50 ---------------
        # dataframe.loc[(
        #     # (dataframe['atrpct'] > 1) &
        #     (dataframe['ADX'] > 25) & # it was considered that adx>40 is a super strong trend, adx< 20 considered as trange market  
        #     # (dataframe['ADX_4h'] > 20) & # it was considered that adx>40 is a super strong trend, adx< 20 considered as trange market  
        #     # (dataframe['is_wave'] == 0) &  # Ensure market is trending
        #     (dataframe['kama_'] > dataframe['ema']) & # EMA and KAMA cross
        #     (dataframe['kama_'].shift(1) < dataframe['ema'].shift(1)) &
        #     (dataframe['chop_1h'] < 68.1) &
        #     (dataframe['condi_rsi_kama'] == 1 ) &
        #     (dataframe['condi_wad_ema'] == 1 ) &
        #     (dataframe['close'] < dataframe['kc_upper']) & # For safety
        #     (abs(dataframe['diff_kamavwap_slope'] - 1 ) > 0.01) &
        #     (dataframe['volume'] > 10000)
        # ), ['enter_long', 'enter_tag']] = (1, 'L_k*ema')

        # dataframe.loc[(
        #     # (dataframe['atrpct'] > 1) &
        #     (dataframe['ADX'] > 25) & # it was considered that adx>40 is a super strong trend, adx< 20 considered as trange market  
        #     # (dataframe['ADX_4h'] > 20) & # it was considered that adx>40 is a super strong trend, adx< 20 considered as trange market  
        #     # (dataframe['is_wave'] == 0 ) &  # Ensure market is trending
        #     (dataframe['kama_'] < dataframe['ema']) & # EMA and KAMA cross
        #     (dataframe['kama_'].shift(1) > dataframe['ema'].shift(1)) &
        #     (dataframe['chop_1h'] < 68.1) &
        #     (dataframe['condi_rsi_kama'] == 1 ) &
        #     (dataframe['condi_wad_ema'] == 1 ) &
        #     (dataframe['close'] > dataframe['kc_lower']) & # for safety
        #     (abs(dataframe['diff_kamavwap_slope'] - 1 ) > 0.01) &
        #     # (dataframe['short_vwap'] == 1.5) &
        #     (dataframe['volume'] > 10000)
        # ), ['enter_short', 'enter_tag']] = (1, 'S_k*ema')
    
        # ------------------------ based on ketlner, for not strong trends -----------------
        # dataframe.loc[(
        #     (dataframe['short_vwap'] == 1.5) & # ENsure Market is Trending
        #     ((dataframe['atrpct'] < 1) & (dataframe['atrpct_1h'] < 1)) &
        #     # (dataframe['vsi'] > 0.4) & 
        #     (dataframe['close'] > dataframe['kc_upper']) &  # Price above Keltner upper band (overbought)
        #     abs((dataframe['diff_kamavwap_slope'] - 1) < self.ket_stead.value ) &
        #     (dataframe['WAD'] > dataframe['short_wad_threshold']) &
        #     (dataframe['condi_rsi_kama'] == 1 ) &
        #     (dataframe['condi_wad_ema'] == 1 ) &
        #     (dataframe['chop_4h'] < 68.1) &
        #     (dataframe['volume'] > 1000)
        # ), ['enter_short', 'enter_tag']] = (1, 'ketlner')
        
        # dataframe.loc[(
        #     (dataframe['long_vwap'] == 1.5) & # ENsure Market is Trending
        #     ((dataframe['atrpct'] < 1) & (dataframe['atrpct_1h'] < 1)) &
        #     # (dataframe['vsi'] > 0.4) & 
        #     (dataframe['close'] < (dataframe['kc_lower'])) &  # Price below Keltner lower band (oversold)
        #     (dataframe['WAD'] < dataframe['long_wad_threshold']) &
        #     (dataframe['condi_rsi_kama'] == 1 ) &
        #     (dataframe['condi_wad_ema'] == 1 ) &
        #     abs((dataframe['diff_kamavwap_slope'] - 1) < self.ket_stead.value ) &
        #     (dataframe['chop_4h'] < 68.1) &
        #     (dataframe['volume'] > 10000)
        # ), ['enter_long', 'enter_tag']] = (1, 'ketlner')
        

         
        # ----------------based on Williams ------------------------------
        # dataframe.loc[(
        #     (dataframe['ATR_4h'] < 1) &
        #     (dataframe['condi_wad_ema'] == 1 ) &
        #     (dataframe['condi_rsi_kama'] == 1 ) &
        #     (dataframe['RSI'] > 75 + (50 + dataframe['WM1']) / 2) & #70
        #     ((dataframe['WAD'] > dataframe['WM0']) | (dataframe['WAD'] > -2 )) &
        #     (dataframe['WM1'] > dataframe['WM2']) &
        #     (dataframe['chop_4h'] < 68.1) &
        #     (dataframe['volume'] > 10000)
        # ), ['enter_short', 'enter_tag']] = (1, 'SW%')
        
        # dataframe.loc[(
        #     (dataframe['ATR_4h'] < 1) & 
        #     (dataframe['condi_wad_ema'] == 1 ) &
        #     (dataframe['condi_rsi_kama'] == 1 ) &
        #     (dataframe['RSI'] < 25 + (50 + dataframe['WM1']) / 2 ) & #30
        #     (dataframe['WM1'] < dataframe['WM2']) &
        #     ((dataframe['WAD'] > dataframe['WM0']) | (dataframe['WAD'] < -98 )) &
        #     (dataframe['chop_4h'] < 68.2) &
        #     (dataframe['volume'] > 10000)
        # ), ['enter_long', 'enter_tag']] = (1, 'LW%')

        # ------- based on atf ---------------------------------
        
        dataframe.loc[(
            (dataframe['atf'] == -1) &
            (dataframe['WAD'] > dataframe['short_wad_threshold']) &
            (abs(dataframe['diff_kamavwap_slope'] - 1) > 0.003) &  # Increase slope threshold slightly for stronger signals
            (dataframe['RSI'] > 70) &  # Add RSI to confirm overbought conditions for short
            (dataframe['ADX'] > 25) &  # Only enter when ADX confirms trend strength
            (dataframe['short_vwap'] == 1.5) &
            (dataframe['volume'] > 1000) &
            (dataframe['volume'] > dataframe['volume'].rolling(window=10).mean())  # Confirm abnormal volume
        ), ['enter_short', 'enter_tag']] = (1, 'ATF')
        dataframe.loc[(
            (abs(dataframe['diff_kamavwap_slope'] - 1) > 0.003) &
            (dataframe['atf'] == 1) &
            (dataframe['WAD'] < dataframe['long_wad_threshold']) &
            (dataframe['RSI'] < 30) &  # Add RSI to confirm oversold conditions for long
            (dataframe['ADX'] > 25) &  # Only enter when ADX confirms trend strength
            (dataframe['long_vwap'] == 1.5) &
            (dataframe['volume'] > 1000) &
            (dataframe['volume'] > dataframe['volume'].rolling(window=10).mean())  # Confirm abnormal volume
        ), ['enter_long', 'enter_tag']] = (1, 'ATF')
        
        # ----------------------------- Based on derivatives --------------------
        dataframe.loc[(
            (dataframe['der_diff_kamavwap_slope'] < 1 ) &
            (dataframe['der_diff_kamavwap_slope'].shift(1) > 1) &  
            (dataframe['der_diff_kamavwap_sma'] > 0.001) &
            (dataframe['WAD'] > dataframe['short_wad_threshold']) &
            # (dataframe['is_wave'] == 1 ) &
            (dataframe['condi_wad_ema'] == 1 ) &
            (dataframe['condi_rsi_kama'] == 1 ) &
            (dataframe['short_vwap'] == 1.5) &
            (dataframe['STOCH_D'] > dataframe['STOCH_K']) &
            (dataframe['volume'] > 1000 )
        ), ['enter_short', 'enter_tag']] = (1, 'der2')
        dataframe.loc[(
            (dataframe['der_diff_kamavwap_slope'] > 1 ) &
            (dataframe['der_diff_kamavwap_slope'].shift(1) < 1) &
            (dataframe['der_diff_kamavwap_sma'] < -0.001) &
            (dataframe['WAD'] < dataframe['long_wad_threshold']) &
            # (dataframe['is_wave'] == 1 ) &
            (dataframe['condi_wad_ema'] == 1 ) &
            (dataframe['STOCH_D'] < dataframe['STOCH_K']) &
            (dataframe['condi_rsi_kama'] == 1 ) &
            (dataframe['long_vwap'] == 1.5) &
            (dataframe['volume'] > 1000 )
        ), ['enter_long', 'enter_tag']] = (1, 'der2')
        

        
        # -------------------------------------- GPT suggest --------------------------------------------------------------        
        
        # # # Entry Conditions for Long
        # dataframe.loc[
        #     (dataframe['typical_price'] > dataframe['vwap']) &  # Market trending up
        #     (dataframe['typical_price'].shift(1) < dataframe['vwap'].shift(1)) &
        #     (dataframe['long_vwap'] == 1.5) &  # Long VWAP signal
        #     (dataframe['wad_support']) &  # WAD support
        #     (dataframe['chop'] < 68.1) &  # Low choppiness, potential trend
        #     (abs(dataframe['kama_vwap_slope_sma']) > 0.002) &  # Uptrend slope
        #     (dataframe['price_volatility'] < 0.1),  # Filter low volatility
        #     ['enter_long', 'enter_tag']] = (1, 'kama_vwap')

        # # Entry Conditions for Short
        # dataframe.loc[
        #     (dataframe['typical_price'] < dataframe['vwap']) &  # Market trending down
        #     (dataframe['typical_price'].shift(1) > dataframe['vwap'].shift(1)) &
        #     (dataframe['short_vwap'] == 1.5) &  # Short VWAP signal
        #     (dataframe['wad_resistance']) &  # WAD resistance
        #     (dataframe['chop'] < 68.1) &  # Low choppiness, potential trend
        #     (abs(dataframe['kama_vwap_slope_sma']) > 0.002) &  # Downtrend slope
        #     (dataframe['price_volatility'] < 0.1),  # Filter low volatility
        #     ['enter_short', 'enter_tag']] = (1, 'kama_vwap')
        
        
        # --------------------------- Advanced RSI -------------------------------
        
        
        
        # ----------------------------based on RSI, WAD and WAD.mean() for range markets ----------------------------------------
        dataframe.loc[(
            (dataframe['short_rsi_threshold'] > dataframe['S_rsi_thres']) &
            (dataframe['diff_rsi'] < 0) &
            (dataframe['diff_rsi'].shift(1) > 0) &
            (dataframe['close'] > dataframe['kama_']) &
            (dataframe['RSI'] > 70) &
            (dataframe['ADX'] > 25) &  # Add ADX filter for stronger trends
            (dataframe['ATR'] > dataframe['ATR'].rolling(window=14).mean()) &  # Filter for volatility
            (dataframe['short_vwap'] == 1.5) &
            (dataframe['STOCH_D'] > dataframe['STOCH_K']) &
            (dataframe['volume'] > 1000)
        ), ['enter_short', 'enter_tag']] = (1, 'rsi')
        
        dataframe.loc[(
            (dataframe['long_rsi_threshold'] < dataframe['L_rsi_thres']) &
            (dataframe['diff_rsi'] > 0) &
            (dataframe['diff_rsi'].shift(1) < 0) &
            (dataframe['close'] < dataframe['kama_']) &
            (dataframe['RSI'] < 30) &
            (dataframe['ADX'] > 25) &  # Add ADX filter for stronger trends
            (dataframe['ATR'] > dataframe['ATR'].rolling(window=14).mean()) &  # Filter for volatility
            (dataframe['long_vwap'] == 1.5) &
            (dataframe['STOCH_D'] < dataframe['STOCH_K']) &
            (dataframe['volume'] > 1000)
        ), ['enter_long', 'enter_tag']] = (1, 'rsi')
        
        
        # -------------------------- based on Con Di ---------------------------
        # dataframe.loc[(
        #     (dataframe['condi_wad_hma'] == -1) &
        #     (dataframe['condi_rsi_hma'] == -1) &
        #     (dataframe['condi_ema_hma'] == -1) &
        #     (dataframe['close'] < dataframe['HMA']) &
        #     (dataframe['ADX'] > 25) &  # تایید روند قوی با ADX
        #     (dataframe['STOCH_D'] > dataframe['STOCH_K']) &
        #     (dataframe['RSI'] > 70) &  # تایید حالت اشباع خرید برای Short
        #     (dataframe['volume'] > 1500) 
        #     # (dataframe['volume'] > dataframe['volume'].rolling(window=10).mean())  # بررسی حجم غیرعادی
        # ), ['enter_short', 'enter_tag']] = (1, 'condis')
        
        # dataframe.loc[(
        #     (dataframe['condi_wad_hma'] == 1) & 
        #     (dataframe['condi_rsi_hma'] == 1) &
        #     (dataframe['condi_ema_hma'] == 1) &
        #     (dataframe['close'] > dataframe['HMA']) &
        #     (dataframe['ADX'] > 25) &  # تایید روند قوی با ADX
        #     (dataframe['RSI'] < 30) &  # تایید حالت اشباع فروش برای Long
        #     (dataframe['STOCH_D'] < dataframe['STOCH_K']) &
        #     (dataframe['volume'] > 1500) 
        #     # (dataframe['volume'] > dataframe['volume'].rolling(window=10).mean())  # بررسی حجم غیرعادی
        # ), ['enter_long', 'enter_tag']] = (1, 'condis')
        
        
        # ---------------------------------kosh----------------------------------
        dataframe.loc[(
            (dataframe['p_mom'] == True) &
            (dataframe['p_mom'].shift(1) == False) &
            (dataframe['STOCH_D'] < dataframe['STOCH_K']) &
            (dataframe['WAD'] < -51)
        ), ['enter_long', 'enter_tag']] = (1, 'rmi')
        dataframe.loc[(
            (dataframe['n_mom'] == True) &
            (dataframe['n_mom'].shift(1) == False) &
            (dataframe['STOCH_D'] > dataframe['STOCH_K']) &
            (dataframe['WAD'] > -49)
        ), ['enter_short', 'enter_tag']] = (1, 'rmi')
        
        # ---------------------------------STOCH----------------------------------
        # dataframe.loc[(
        #     (dataframe['p_mom'] == True) &
        #     (dataframe['p_mom'].shift(1) == False) &
        #     (dataframe['WAD'] < -51)
        # ), ['enter_long', 'enter_tag']] = (1, 'rmi')
        # dataframe.loc[(
        #     (dataframe['n_mom'] == True) &
        #     (dataframe['n_mom'].shift(1) == False) &
        #     (dataframe['WAD'] > -49)
        # ), ['enter_short', 'enter_tag']] = (1, 'rmi')

        return dataframe

    
    def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float, 
                            time_in_force: str, entry_tag: str, **kwargs) -> bool:        
        # Limit the number of open trades with the same entry tag
        open_trades = self.get_open_trades()        
        open_trades_with_tag = [trade for trade in open_trades if trade.enter_tag == entry_tag]
        if len(open_trades_with_tag) >= self.entry_tags_limit:
            # logger.warning(f"Reached limit of {self.entry_tags_limit} trades with entry tag {entry_tag}.")
            return False
        return True

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[(
            (dataframe['enter_short'] == 1 ) 
        ), ['exit_long', 'exit_tag']] = (1, 'Lopp_signal')
        dataframe.loc[(
            (dataframe['enter_long'] == 1 ) 
        ), ['exit_short', 'exit_tag']] = (1, 'Sopp_signal')
        return dataframe
    
    def custom_exit(self, pair: str, trade: Trade, current_time: datetime, current_rate: float, current_profit: float, **kwargs) -> Optional[str]:

        dataframe, *_ = self.dp.get_analyzed_dataframe(
            pair=pair, timeframe=self.timeframe
        )
        current_candle = dataframe.iloc[-1].squeeze()
        previous_candle = dataframe.iloc[-2]  # Get the previous row for comparison

        # if any(tag in trade.enter_tag for tag in ['lrsi', 'srsi']) and current_profit >= 0.02:
        #     return 'condidit'
        
        if any(tag in trade.enter_tag for tag in ['ketlner']) and (current_candle['close'] < current_candle['kc_lower']) and (current_candle['kama_slope'] > 1) and (previous_candle['kama_slope'] < 1):
            return "ketlner_did_it!!"
        
        if any(tag in trade.enter_tag for tag in ['ketlner']) and (current_candle['close'] > current_candle['kc_upper']) and (current_candle['kama_slope'] < 1) and (previous_candle['kama_slope'] > 1):
            return "ketlner_did_it!!"
        
        # if any(tag in trade.enter_tag for tag in ['Satf']) and (current_candle['kama_slope'] > previous_candle['kama_slope']):
        #     return 'satf ended'
        
        # if any(tag in trade.enter_tag for tag in ['Latf']) and (current_candle['kama_slope'] < previous_candle['kama_slope']):
        #     return 'latf ended'
        
        # if any(tag in trade.enter_tag for tag in ['S_vwap']) and (current_candle['typical_price'] > current_candle['vwap']):
        #     return 'svwap ended'
        
        # if any(tag in trade.enter_tag for tag in ['L_vwap']) and (current_candle['typical_price'] < current_candle['vwap']):
        #     return 'lvwap ended'
        
        # if any(tag in trade.enter_tag for tag in ['L_k*ema']) and (current_candle['kama_'] < current_candle['ema']) and (current_profit < 0):
        #     return "Lprevent!!"
        
        # if any(tag in trade.enter_tag for tag in ['S_k*ema']) and (current_candle['kama_'] > current_candle['ema']) and (current_profit < 0):
        #     return "Sprevent!!"

   
    def leverage(self, pair: str, current_time: datetime, current_rate: float,
                proposed_leverage: float, max_leverage: float, entry_tag: Optional[str], side: str,
                **kwargs) -> float:
        dataframe, *_ = self.dp.get_analyzed_dataframe(
            pair=pair, timeframe=self.timeframe
        )
        current_candle = dataframe.iloc[-1].squeeze()
        # dataframe['spread'] = 1000 * abs(dataframe['high'] - dataframe['low']) / dataframe['close']
        # # بقیه کدهای محاسبه leverage
        # dataframe['spread_avg'] = dataframe['spread'].rolling(window=100).mean()

        # leverage = self.max_leverage * (1.0 - float(current_candle['atr_pct']))
        return 15.0
        # return leverage

