# source: https://raw.githubusercontent.com/remiotore/freqtrade/44beaeb6a420cd8e9f2e4ea93e11d6cfa192ee03/strategies/Insomnia.py






from typing import Dict
from pandas import DataFrame
from datetime import datetime
from typing import Optional
from freqtrade.strategy import (DecimalParameter,
                                IntParameter, IStrategy, informative,  stoploss_from_open)
from freqtrade.persistence import Trade
from freqtrade.optimize.space import Categorical, Dimension, Integer, SKDecimal


import talib.abstract as ta

    
class Github_remiotore_freqtrade__Insomnia__20260111_210550(IStrategy):
    
    @property
    def protections(self):
        return [
            {
                "method": "CooldownPeriod",
                "stop_duration_candles": 5
            },
            {
                "method": "MaxDrawdown",
                "lookback_period_candles": 10,
                "trade_limit": 20,
                "stop_duration_candles": 4,
                "max_allowed_drawdown": 0.2
            },
            {
                "method": "StoplossGuard",
                "lookback_period_candles": 12,
                "trade_limit": 4,
                "stop_duration_candles": 2,
                "only_per_pair": False
            },
        ]


























    INTERFACE_VERSION = 3

    timeframe = '30m'

    can_short: bool = False

    levarage_input = 4.0

    minimal_roi = {
        "0": 0.4,
        "150": 0.2, 
        "300": 0.0
    }


    stoploss = -0.034

    trailing_stop = False
    trailing_stop_positive = 0.219
    trailing_stop_positive_offset = 0.284
    trailing_only_offset_is_reached = False

    process_only_new_candles = False

    use_exit_signal = True
    exit_profit_only = False
    ignore_roi_if_entry_signal = False

    startup_candle_count: int = 250


    buy_params = {
        "buy_rsi": 14,
        "buy_rsi_1": 14,
        "buy_rsi_4": 14,
        "buy_rsi_12": 14,
        "buy_sma_1": 200,
        "buy_sma_4": 200,
        "buy_sma_12": 200,
        "buy_rsi_compare_long": 32,
        "buy_rsi_compare_short": 68,
        "buy_compare_vol_long": 3,
        "buy_compare_vol_short": 3,
        "buy_compare_rsi_12_long": 49,
        "buy_compare_rsi_12_short": 49,
        "buy_compare_rsi_1_long": 35,
        "buy_compare_rsi_1_short": 65,
    }

    sell_params = {
        "sell_rsi_compare_long": 65,
        "sell_rsi_compare_short": 30,
    }

    buy_rsi = IntParameter(8, 20, default=buy_params['buy_rsi'], space="buy")

    buy_rsi_1 = IntParameter(8, 20, default=buy_params['buy_rsi_1'], space="buy", optimize=False)
    buy_rsi_4 = IntParameter(8, 20, default=buy_params['buy_rsi_4'], space="buy", optimize=False)
    buy_rsi_12 = IntParameter(8, 20, default=buy_params['buy_rsi_12'], space="buy", optimize=False)

    buy_sma_1 = IntParameter(150, 250, default=buy_params['buy_sma_1'], space="buy")
    buy_sma_4 = IntParameter(150, 250, default=buy_params['buy_sma_4'], space="buy")
    buy_sma_12 = IntParameter(150, 250, default=buy_params['buy_sma_12'], space="buy")


    buy_rsi_compare_long = IntParameter(20, 49, default=buy_params['buy_rsi_compare_long'], space="buy", optimize=False)
    buy_rsi_compare_short = IntParameter(51, 80, default=buy_params['buy_rsi_compare_short'], space="buy")

    buy_compare_vol_long = DecimalParameter(0.1, 5, decimals=1, default=buy_params['buy_compare_vol_long'], space="buy", optimize=False)
    buy_compare_vol_short = DecimalParameter(0.1, 5, decimals=1, default=buy_params['buy_compare_vol_short'], space="buy", optimize=False)

    buy_compare_rsi_12_long = IntParameter(20, 49, default=buy_params['buy_compare_rsi_12_long'], space="buy", optimize=False)
    buy_compare_rsi_12_short = IntParameter(49, 80, default=buy_params['buy_compare_rsi_12_short'], space="buy", optimize=False)

    buy_compare_rsi_1_long = IntParameter(20, 49, default=buy_params['buy_compare_rsi_1_long'], space="buy")
    buy_compare_rsi_1_short = IntParameter(51, 80, default=buy_params['buy_compare_rsi_1_short'], space="buy")

    sell_rsi_compare_long = IntParameter(65, 70, default=buy_params['buy_compare_rsi_1_short'], space="sell")
    sell_rsi_compare_short = IntParameter(30, 50, default=buy_params['buy_compare_rsi_1_short'], space="sell")

    use_custom_stoploss = True

    order_types = {
        'entry': 'market',
        'exit': 'market',
        'stoploss': 'market',
        'stoploss_on_exchange': True
    }

    order_time_in_force = {
        'entry': 'GTC',
        'exit': 'GTC'
    }
    
    @property
    def plot_config(self):
        return {

            'main_plot': {
                f'sma_{self.buy_sma_1.value}_1h': {'color': 'green'},
                f'sma_{self.buy_sma_4.value}_4h': {'color': 'brown'},
                f'sma_{self.buy_sma_12.value}_12h': {'color': 'red'},
            },
            'subplots': {

                "RSI": {
                    f'rsi_{self.buy_rsi.value}': {'color': 'green'},
                    f'rsi_{self.buy_rsi_1.value}_1h': {'color': 'brown'},
                    f'rsi_{self.buy_rsi_12.value}_12h': {'color': 'red'},
                },
                "Volume": {
                    'volume_usdt': {'color': 'green', 'type': 'bar'},
                }
            }
        }

    @informative('1h')
    def populate_indicators_1h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        for val in self.buy_rsi_1.range:
            dataframe[f'rsi_{val}'] = ta.RSI(dataframe, timeperiod=val)
        for val in self.buy_sma_1.range:
            dataframe[f'sma_{val}'] = ta.SMA(dataframe, timeperiod=val)
        return dataframe

    @informative('4h')
    def populate_indicators_4h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        for val in self.buy_rsi_4.range:
            dataframe[f'rsi_{val}'] = ta.RSI(dataframe, timeperiod=val)
        for val in self.buy_sma_4.range:
            dataframe[f'sma_{val}'] = ta.SMA(dataframe, timeperiod=val)
        return dataframe

    @informative('12h')
    def populate_indicators_12h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        for val in self.buy_rsi_12.range:
            dataframe[f'rsi_{val}'] = ta.RSI(dataframe, timeperiod=val)
        for val in self.buy_sma_12.range:
            dataframe[f'sma_{val}'] = ta.SMA(dataframe, timeperiod=val)
        return dataframe

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        for val in self.buy_rsi.range:
            dataframe[f'rsi_{val}'] = ta.RSI(dataframe, timeperiod=val)
        dataframe['volume_cum'] = dataframe['volume'].rolling(window=48).sum()
        dataframe['volume_usdt'] = dataframe['volume_cum'] * dataframe['close']


        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:

        dataframe.loc[
            ((dataframe[f'rsi_{self.buy_rsi.value}'] < self.buy_rsi_compare_long.value) &
             (dataframe[f'volume_usdt'] > self.buy_compare_vol_long.value * 1000000) &
             (dataframe[f'rsi_{self.buy_rsi_12.value}_12h'] > self.buy_compare_rsi_12_long.value) &
             (dataframe[f'rsi_{self.buy_rsi_1.value}_1h'] < self.buy_compare_rsi_1_long.value) &
             (dataframe['close'] > dataframe[f'sma_{self.buy_sma_12.value}_12h']) &
             (dataframe['close'] > dataframe[f'sma_{self.buy_sma_4.value}_4h']) &
             (dataframe['close'] > dataframe[f'sma_{self.buy_sma_1.value}_1h'])
            ),
            'enter_long'] = 1


        dataframe.loc[
            ((dataframe[f'rsi_{self.buy_rsi.value}'] > self.buy_rsi_compare_short.value) &
             (dataframe[f'volume_usdt'] > self.buy_compare_vol_short.value * 1000000) &
             (dataframe[f'rsi_{self.buy_rsi_12.value}_12h'] < self.buy_compare_rsi_12_short.value) &
             (dataframe[f'rsi_{self.buy_rsi_1.value}_1h'] > self.buy_compare_rsi_1_short.value) &
             (dataframe['close'] < dataframe[f'sma_{self.buy_sma_12.value}_12h']) &
             (dataframe['close'] < dataframe[f'sma_{self.buy_sma_4.value}_4h']) &
             (dataframe['close'] < dataframe[f'sma_{self.buy_sma_1.value}_1h'])
            ),
            'enter_short'] = 1
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (dataframe[f'rsi_{self.buy_rsi.value}'] > self.sell_rsi_compare_long.value),
            'exit_long'] = 1

        dataframe.loc[
            (dataframe[f'rsi_{self.buy_rsi.value}'] < self.sell_rsi_compare_short.value),
            'exit_short'] = 1


        return dataframe

    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:
        if self.levarage_input > max_leverage:
            return max_leverage

        return self.levarage_input

    def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
                        current_rate: float, current_profit: float, after_fill: bool,
                        **kwargs) -> Optional[float]:

        if current_profit > 0.12:
            return stoploss_from_open(0.02, current_profit, is_short=trade.is_short, leverage=trade.leverage)
        elif current_profit > 0.15:
            return stoploss_from_open(0.05, current_profit, is_short=trade.is_short, leverage=trade.leverage)
        elif current_profit > 0.25:
            return stoploss_from_open(0.18, current_profit, is_short=trade.is_short, leverage=trade.leverage)
        elif current_profit > 0.3:
            return stoploss_from_open(0.25, current_profit, is_short=trade.is_short, leverage=trade.leverage)

        return None