#
#
#
from datetime import timedelta, datetime
from typing import Optional
from freqtrade.persistence import Trade
from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter, IntParameter, BooleanParameter
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
import logging
from technical import pivots_points
# --------------------------------

# Add your lib to import here
import ta
import talib.abstract as talib
from freqtrade.strategy.strategy_helper import merge_informative_pair
import freqtrade.vendor.qtpylib.indicators as qtpylib

logger = logging.getLogger(__name__)


class Ishimoku_6(IStrategy):
    # ROI table:
    minimal_roi = {
        "0": 0.564,
        "567": 0.273,
        "2814": 0.12,
        "7675": 0
    }

    # Stoploss:
    stoploss = -0.256

    # Buy hypers
    timeframe = '4h'

    stop_buying = {}
    max_open_trades = 5
    stop_buy_for_all = False
    plot_config = {
        "main_plot": {
            "min200": {
                "color": "#86c932"
            },
            "max50": {
                "color": "white"
            },
            "max200": {
                "color": "yellow"
            },
            "bb_lowerband": {
                "color": "#da59a6"
            },
            "bb_upperband": {
                "color": "#da59a6"
            },
            "sar": {
                "color": "#4f9f51"
            },
            "enter_tag": {
                "color": "#b400c7",
                "type": "line"
            },
            "sma10": {
                "color": "#271db5",
                "type": "line"
            },
            "r1": {
                "color": "#3181d9",
                "type": "line"
            },
            "r2": {
                "color": "#e31837",
                "type": "line"
            },
            "r3": {
                "color": "#a0f99b",
                "type": "line"
            },
            "s1": {
                "color": "#ee7d7d",
                "type": "line"
            },
            "s2": {
                "color": "#740346",
                "type": "line"
            },
            "s3": {
                "color": "#ff2a10",
                "type": "line"
            }
        },
        "subplots": {
            "Ind": {
                "trend_ichimoku_base": {
                    "color": "#dd1384"
                },
                "trend_kst_diff": {
                    "color": "#850678"
                },
                "ichimoku_conversion_line": {
                    "color": "#83a12a",
                    "type": "line"
                }
            },
            "BB": {
                "ichimoku_cut_below_1h": {
                    "color": "#9ee22c",
                    "type": "line"
                },
                "ichimoku_cut_above_1h": {
                    "color": "#aa2a1f",
                    "type": "line"
                }
            },
            "Cond": {
                "cond1": {
                    "color": "yellow"
                }
            },
            "Rsi": {
                "rsi": {
                    "color": "pink"
                },
                "rsi_5_1h": {
                    "color": "#34e97f",
                    "type": "line"
                },
                "rsi_1h": {
                    "color": "#3ce8ea",
                    "type": "line"
                },
                "rsi5": {
                    "color": "#47f377",
                    "type": "line"
                }
            },
            "Percent": {
                "percent5": {
                    "color": "#2250f1",
                    "type": "line"
                },
                "percent10": {
                    "color": "#e02bbb",
                    "type": "line"
                }
            }
        }
    }
    trades = list()

    buy_base = DecimalParameter(0, 0.2, decimals=2, default=0.10, space='buy')
    buy_rsi = IntParameter(20, 80, default=70, space='buy')

    profit_b_no_change = BooleanParameter(default=True, space="sell")
    profit_b_quick_lost = BooleanParameter(default=True, space="sell")
    profit_b_sma5 = BooleanParameter(default=True, space="sell")
    profit_b_sma10 = BooleanParameter(default=True, space="sell")
    profit_b_sma20 = BooleanParameter(default=True, space="sell")
    profit_b_quick_gain = BooleanParameter(default=True, space="sell")
    profit_b_quick_gain_3 = BooleanParameter(default=True, space="sell")
    profit_b_old_sma10 = BooleanParameter(default=True, space="sell")
    profit_b_very_old_sma10 = BooleanParameter(default=True, space="sell")
    profit_b_over_rsi = BooleanParameter(default=True, space="sell")
    profit_b_short_loss = BooleanParameter(default=True, space="sell")

    sell_b_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
    sell_b_percent3 = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
    sell_b_candels = IntParameter(0, 48, default=12, space='sell')

    sell_b_too_old_day = IntParameter(0, 10, default=5, space='sell')
    sell_b_too_old_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')

    sell_b_profit_no_change = DecimalParameter(0, 0.02, decimals=3, default=0.005, space='sell')
    sell_b_profit_percent10 = DecimalParameter(0, 0.002, decimals=4, default=0.001, space='sell')

    sell_b_RSI = IntParameter(70, 98, default=88, space='sell')
    sell_b_RSI2 = IntParameter(70, 98, default=88, space='sell')
    sell_b_RSI3 = IntParameter(70, 98, default=80, space='sell')

    sell_b_RSI2_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
    sell_rsi5_1h = IntParameter(30, 80, default=41, space='sell')
    # sell_b_expected_profit = DecimalParameter(0, 0.01, decimals=3,  default=0.01, space='sell')

    profit_h_no_change = BooleanParameter(default=True, space="sell")
    profit_h_quick_lost = BooleanParameter(default=True, space="sell")
    profit_h_sma5 = BooleanParameter(default=True, space="sell")
    profit_h_sma10 = BooleanParameter(default=True, space="sell")
    profit_h_sma20 = BooleanParameter(default=True, space="sell")
    profit_h_quick_gain = BooleanParameter(default=True, space="sell")
    profit_h_quick_gain_3 = BooleanParameter(default=True, space="sell")
    profit_h_old_sma10 = BooleanParameter(default=True, space="sell")
    profit_h_very_old_sma10 = BooleanParameter(default=True, space="sell")
    profit_h_over_rsi = BooleanParameter(default=True, space="sell")
    profit_h_short_loss = BooleanParameter(default=True, space="sell")

    sell_h_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
    sell_h_percent3 = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
    sell_h_candels = IntParameter(0, 48, default=12, space='sell')

    sell_h_too_old_day = IntParameter(0, 10, default=5, space='sell')
    sell_h_too_old_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')

    sell_h_profit_no_change = DecimalParameter(0, 0.02, decimals=3, default=0.005, space='sell')
    sell_h_profit_percent10 = DecimalParameter(0, 0.002, decimals=4, default=0.001, space='sell')

    sell_h_RSI = IntParameter(70, 98, default=88, space='sell')
    sell_h_RSI2 = IntParameter(70, 98, default=88, space='sell')
    sell_h_RSI3 = IntParameter(70, 98, default=80, space='sell')

    sell_h_RSI2_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')

    btc_fall_1 = DecimalParameter(-0.1, 0, decimals=2, default=0.0, space='protection')
    btc_fall_3 = DecimalParameter(-0.1, 0, decimals=2, default=0.0, space='protection')
    btc_fall_5 = DecimalParameter(-0.1, 0, decimals=2, default=0.0, space='protection')
    btc_sell_all_profit = DecimalParameter(-0.5, 0, decimals=2, default=0.0, space='protection')
    btc_allow_to_buy = DecimalParameter(-0.02, 0.05, decimals=2, default=0.0, space='protection')

    def bot_loop_start(self, **kwargs) -> None:
        inf_tf = '5m'
        pairs = self.dp.current_whitelist()
        # print("Calcul des pairs informatives")
        for pairname in pairs:
            self.stop_buying[pairname] = True
        # print("Fin Calcul des pairs informatives")

    # def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
    #                         proposed_stake: float, min_stake: float, max_stake: float,
    #                         **kwargs) -> float:
    #
    #     informative, _ = self.dp.get_analyzed_dataframe(pair='BTC/USDT', timeframe=self.timeframe)
    #     # current_candle = informative.iloc[-1].squeeze()
    #
    #     current = informative.tail(1).iloc[0]['close']
    #     # 50000 => 2 30000 => 20
    #     if current > 50000:
    #         self.max_open_trades = 2
    #         proposed_stake = self.config['stake_amount'] / 2
    #     else:
    #         if current > 32000:
    #             self.max_open_trades = 2 + int((50000 - current) / 1000)
    #             proposed_stake = self.config['stake_amount'] / 2 \
    #                              + self.config['stake_amount'] * self.max_open_trades / self.config['max_open_trades']
    #         else:
    #             self.max_open_trades = self.config['max_open_trades']
    #             proposed_stake = self.config['stake_amount']
    #
    #     return min(max_stake, proposed_stake)

    @property
    def protections(self):
        return [
            {
                "method": "CooldownPeriod",
                "stop_duration_candles": 10
            },
            # {
            #     "method": "MaxDrawdown",
            #     "lookback_period_candles": self.lookback.value,
            #     "trade_limit": self.trade_limit.value,
            #     "stop_duration_candles": self.protection_stop.value,
            #     "max_allowed_drawdown": self.protection_max_allowed_dd.value,
            #     "only_per_pair": False
            # }
        ]

    def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float, time_in_force: str,
                            current_time: datetime, entry_tag: Optional[str], **kwargs) -> bool:
        allow_to_buy = True
        informative, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
        info_last_candle = informative.iloc[-1].squeeze()
        info_previous_last_candle = informative.iloc[-2].squeeze()

        if self.stop_buy_for_all is True:
            if info_last_candle['pct_change_1_1d'] > self.btc_allow_to_buy.value:
                self.stop_buy_for_all = False
                logger.info("1 -BUYING IS ENABLED %s date %s", pair, info_last_candle['date'])
            else:
                logger.info("1 -BUYING IS BLOCKED BY BTC FALL  %s date %s", pair, info_last_candle['date'])
                return False

        if self.stop_buying.get(pair, None) is None:
            print("enable buying tag", pair)
            self.stop_buying[pair] = False
        # if (info_last_candle['rsi_1h'] < self.protection_RSI_enable.value) & (self.stop_buying[pair] is True):
        #     print("Enable buying", pair)
        #     self.stop_buying[pair] = False

        # if self.stop_buying[pair] is True:
        #    if (info_last_candle['rsi_5_1h'] > 20) & (info_previous_last_candle['rsi_5_1h'] <= info_last_candle['rsi_5_1h']) \
        #            & (info_last_candle['max_rsi_1h'] < 50):
        #        print("2 - Enable buying", pair, info_last_candle['date'], info_last_candle['rsi_5_1h'], info_last_candle['max_rsi_1h'])
        #        self.stop_buying[pair] = False

        if self.stop_buying[pair] is True:
            if (info_last_candle['rsi5'] > 20) & (info_last_candle['rsi'] > 30):
                # print("1 - Enable buying ", pair, info_last_candle['date'], info_last_candle['rsi5'])
                logger.info("1 - Enable buying %s date %s", pair, info_last_candle['date'])

                self.stop_buying[pair] = False

        if self.stop_buying[pair]:
            allow_to_buy = False
            logger.info("3 - cancel buying %s date %s", pair, info_last_candle['date'])
        else:
            logger.info("3 - accept buying %s date %s", pair, info_last_candle['date'])
            #         , (info_last_candle['trend_ichimoku_base'],
            # (info_last_candle['close'] < info_last_candle['sma10']),
            # (info_previous_last_candle['sma10'], info_last_candle['sma10'])))

        return allow_to_buy

    def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
                    current_profit: float, **kwargs):
        dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
        last_candle = dataframe.iloc[-1].squeeze()
        previous_last_candle = dataframe.iloc[-2].squeeze()
        previous_5_candle = dataframe.iloc[-5].squeeze()

        if (self.stop_buy_for_all is True) & (current_profit < self.btc_sell_all_profit.value):
            return "btc_fall"

        expected_profit = 0.01
        days = (current_time - trade.open_date_utc).days
        ######

        btc, _ = self.dp.get_analyzed_dataframe(pair="BTC/USDT", timeframe=self.timeframe)
        btc_last_candle = btc.iloc[-1].squeeze()
        btc_previous_last_candle = btc.iloc[-2].squeeze()

        informative, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
        info_last_candle = informative.iloc[-1].squeeze()
        info_previous_last_candle = informative.iloc[-2].squeeze()

        if self.stop_buying.get(pair, None) is None:
            print("enable buying tag", pair)
            self.stop_buying[pair] = False

        if self.stop_buying[pair] is False:
            if (last_candle['rsi5'] < 16):
                logger.info("0 - Disable buying %s date=%s rsi=%s", pair, last_candle['date'], last_candle['rsi5'])
                self.stop_buying[pair] = True
                if (current_profit > 0):
                    return "stop_buying"

        if self.stop_buying[pair] is True:
            if (last_candle['rsi5'] > 20) & (last_candle['percent10'] > 0):
                logger.info("1 - Enable buying %s date=%s rsi=%s", pair, last_candle['date'], last_candle['rsi5'])
                # print("1 - Enable buying ", pair, last_candle['date'], last_candle['rsi5'])
                self.stop_buying[pair] = False


        if (btc_last_candle['percent5'] < self.btc_fall_5.value) | (btc_last_candle['percent3'] < self.btc_fall_3.value) | (
                btc_last_candle['percent'] < self.btc_fall_1.value):
            self.stop_buy_for_all = True
            return "btc_fall"

        if last_candle['rsi_5_1h'] < self.sell_rsi5_1h.value:
            if (current_profit > 0.01) & ((last_candle['percent'] < -0.003) | (last_candle['percent3'] < -0.003) | (
                    last_candle['percent5'] < -0.003) | (last_candle['rsi5'] < 41)):
                return 'b_percent_quick'


            if (current_profit >= - self.sell_b_too_old_percent.value) & (days >= self.sell_b_too_old_day.value) \
                    & (days < self.sell_b_too_old_day.value * 2) \
                    & (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
                return "b_too_old_0.01"
            if (current_profit >= - self.sell_b_too_old_percent.value * 2) & (days >= self.sell_b_too_old_day.value * 2) \
                    & (days < self.sell_b_too_old_day.value * 3) \
                    & (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
                return "b_too_old_0.02"
            if (current_profit >= - self.sell_b_too_old_percent.value * 3) & (days >= self.sell_b_too_old_day.value * 3) \
                    & (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
                return "b_too_old_0.03"

            if self.profit_b_quick_lost.value and (current_profit >= 0.015) & (last_candle['percent3'] < -0.005):
                return "b_quick_lost"

            if self.profit_b_no_change.value and (current_profit > self.sell_b_profit_no_change.value) \
                    & (last_candle['percent10'] < self.sell_b_profit_percent10.value) & (last_candle['percent5'] < 0) \
                    & ((current_time - trade.open_date_utc).seconds >= 3600):
                return "b_no_change"

            if (current_profit > self.sell_b_percent.value) & (last_candle['percent3'] < - self.sell_b_percent3.value) \
                    & ((current_time - trade.open_date_utc).seconds <= 300 * self.sell_b_candels.value):
                return "b_quick_gain_param"

            if self.profit_b_sma5.value:
                if (current_profit > expected_profit) \
                        & ((previous_5_candle['sma5'] > last_candle['sma5']) \
                           | (last_candle['percent3'] < -expected_profit) | (
                                   last_candle['percent5'] < -expected_profit)) \
                        & ((last_candle['percent'] < 0) & (last_candle['percent3'] < 0)):
                    # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
                    return 'b_sma5'

            if self.profit_b_sma10.value:
                if (current_profit > expected_profit) \
                        & ((previous_5_candle['sma10'] > last_candle['sma10']) \
                           | (last_candle['percent3'] < -expected_profit) | (
                                   last_candle['percent5'] < -expected_profit)) \
                        & ((last_candle['percent'] < 0) & (last_candle['percent3'] < 0)):
                    # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
                    return 'b_sma10'

            if self.profit_b_sma20.value:
                if (current_profit > last_candle['bb_width'] / 1.3) \
                        & (previous_last_candle['sma10'] > last_candle['sma10']) \
                        & ((current_time - trade.open_date_utc).seconds >= 3600) \
                        & ((previous_last_candle['sma20'] > last_candle['sma20']) &
                           ((last_candle['percent5'] < 0) | (last_candle['percent10'] < 0) | (
                                   last_candle['percent20'] < 0))):
                    # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
                    return 'b_sma20'

            if self.profit_b_over_rsi.value:
                if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_b_RSI.value):  # & (last_candle['percent'] < 0): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
                    # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
                    return 'b_over_rsi'

                if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_b_RSI2.value) & \
                        (last_candle['percent'] < self.sell_b_RSI2_percent.value):
                    # | (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
                    # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
                    return 'b_over_rsi_2'

                if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_b_RSI3.value) & \
                        (last_candle['close'] >= last_candle['max200']) \
                        & (last_candle[
                               'percent'] < - self.sell_b_RSI2_percent.value):  # | (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
                    # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
                    return 'b_over_rsi_max'

            if self.profit_b_short_loss.value:
                if (current_profit > -expected_profit) & (previous_last_candle['percent10'] > 0.04) & (
                        last_candle['percent'] < 0) \
                        & (days >= 1):  # | (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
                    # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
                    return 'b_short_lost'
        else:
            if (current_profit > 0.025) & ((last_candle['percent'] < -0.005) | (last_candle['percent3'] < -0.005) | (
                    last_candle['percent5'] < -0.005)):
                return 'h_percent_quick'
            if (current_profit >= - self.sell_h_too_old_percent.value) & (days >= self.sell_h_too_old_day.value) \
                    & (days < self.sell_h_too_old_day.value * 2) \
                    & (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
                return "h_too_old_0.01"
            if (current_profit >= - self.sell_h_too_old_percent.value * 2) & (days >= self.sell_h_too_old_day.value * 2) \
                    & (days < self.sell_h_too_old_day.value * 3) \
                    & (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
                return "h_too_old_0.02"
            if (current_profit >= - self.sell_h_too_old_percent.value * 3) & (days >= self.sell_h_too_old_day.value * 3) \
                    & (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
                return "h_too_old_0.03"

            if self.profit_h_quick_lost.value and (current_profit >= 0.015) & (last_candle['percent3'] < -0.005):
                return "h_quick_lost"

            if self.profit_h_no_change.value and (current_profit > self.sell_h_profit_no_change.value) \
                    & (last_candle['percent10'] < self.sell_h_profit_percent10.value) & (last_candle['percent5'] < 0) \
                    & ((current_time - trade.open_date_utc).seconds >= 3600):
                return "h_no_change"

            if (current_profit > self.sell_h_percent.value) & (last_candle['percent3'] < - self.sell_h_percent3.value) \
                    & ((current_time - trade.open_date_utc).seconds <= 300 * self.sell_h_candels.value):
                return "h_quick_gain_param"

            if self.profit_h_sma5.value:
                if (current_profit > expected_profit) \
                        & ((previous_5_candle['sma5'] > last_candle['sma5']) \
                           | (last_candle['percent3'] < -expected_profit) | (
                                   last_candle['percent5'] < -expected_profit)) \
                        & ((last_candle['percent'] < 0) & (last_candle['percent3'] < 0)):
                    # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
                    return 'h_sma5'

            if self.profit_h_sma10.value:
                if (current_profit > expected_profit) \
                        & ((previous_5_candle['sma10'] > last_candle['sma10']) \
                           | (last_candle['percent3'] < -expected_profit) | (
                                   last_candle['percent5'] < -expected_profit)) \
                        & ((last_candle['percent'] < 0) & (last_candle['percent3'] < 0)):
                    # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
                    return 'h_sma10'

            if self.profit_h_sma20.value:
                if (current_profit > last_candle['bb_width'] / 0.8) \
                        & (previous_last_candle['sma10'] > last_candle['sma10']) \
                        & ((current_time - trade.open_date_utc).seconds >= 3600) \
                        & ((previous_last_candle['sma20'] > last_candle['sma20']) &
                           ((last_candle['percent5'] < 0) | (last_candle['percent10'] < 0) | (
                                   last_candle['percent20'] < 0))):
                    # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
                    return 'h_sma20'

            if self.profit_h_over_rsi.value:
                if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI.value):
                    # & (last_candle['percent'] < 0): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
                    # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
                    return 'h_over_rsi'

                if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI2.value) & \
                        (last_candle['percent'] < - self.sell_h_RSI2_percent.value):
                    # | (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
                    # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
                    return 'h_over_rsi_2'

                if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI3.value) & \
                        (last_candle['close'] >= last_candle[
                            'max200']):  # | (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
                    # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
                    return 'h_over_rsi_max'

            if self.profit_h_short_loss.value:
                if (current_profit > -expected_profit) & (previous_last_candle['percent10'] > 0.04) & (
                        last_candle['percent'] < 0) \
                        & (days >= 1):  # | (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
                    # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
                    return 'h_short_lost'

    def informative_pairs(self):
        informative_pairs = [('BTC/USDT', '1d')]
        pairs = self.dp.current_whitelist()
        informative_pairs += [(pair, '1h') for pair in pairs]
        # self.stop_buying[pair] = [(pair, False) for pair in pairs]
        # print(self.stop_buying)
        return informative_pairs

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # Add all ta features

        dataframe['ichimoku_conversion_line'] = ta.trend.ichimoku_conversion_line(
            dataframe['high'],
            dataframe['low'],
            window1=9,
            window2=26,
            visual=False,
            fillna=False
        )

        dataframe['trend_ichimoku_base'] = ta.trend.ichimoku_base_line(
            dataframe['high'],
            dataframe['low'],
            window1=9,
            window2=26,
            visual=False,
            fillna=False
        )
        KST = ta.trend.KSTIndicator(
            close=dataframe['close'],
            roc1=10,
            roc2=15,
            roc3=20,
            roc4=30,
            window1=10,
            window2=10,
            window3=10,
            window4=15,
            nsig=9,
            fillna=False
        )

        dataframe['trend_kst_diff'] = KST.kst_diff()
        dataframe['rsi'] = talib.RSI(dataframe)
        dataframe['rsi5'] = talib.RSI(dataframe, timeperiod=5)
        dataframe['pct_change'] = dataframe['close'].pct_change(5)
        dataframe['min10'] = talib.MIN(dataframe['close'], timeperiod=10)
        dataframe['min20'] = talib.MIN(dataframe['close'], timeperiod=20)
        dataframe['min50'] = talib.MIN(dataframe['close'], timeperiod=50)
        dataframe['min5'] = talib.MIN(dataframe['close'], timeperiod=5)
        dataframe['min200'] = talib.MIN(dataframe['close'], timeperiod=200)
        dataframe['min'] = talib.MIN(dataframe['close'], timeperiod=200)
        dataframe['moy200_12'] = dataframe['min200'].rolling(12).mean()
        dataframe['distance_min'] = (dataframe['close'] - dataframe['min']) / dataframe['close']

        dataframe['max50'] = talib.MAX(dataframe['close'], timeperiod=50)
        dataframe['max200'] = talib.MAX(dataframe['close'], timeperiod=200)
        dataframe['sma5'] = talib.SMA(dataframe, timeperiod=5)
        dataframe['sma10'] = talib.SMA(dataframe, timeperiod=10)
        dataframe['sma5_ma_2'] = dataframe['sma5'].pct_change(2)
        dataframe['sma5_ma_5'] = dataframe['sma5'].pct_change(5)
        dataframe['sma20'] = talib.SMA(dataframe, timeperiod=20)
        dataframe['sma50'] = talib.SMA(dataframe, timeperiod=50)
        dataframe['sma100'] = talib.SMA(dataframe, timeperiod=100)
        dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
        dataframe["percent5"] = dataframe["percent"].rolling(5).sum()
        dataframe["percent3"] = dataframe["percent"].rolling(3).sum()
        dataframe["percent10"] = dataframe["percent"].rolling(10).sum()
        dataframe["percent20"] = dataframe["percent"].rolling(20).sum()
        dataframe["percent50"] = dataframe["percent"].rolling(50).sum()
        dataframe["volume10"] = dataframe["volume"].rolling(10).mean()
        dataframe["volume10"] = dataframe["volume"].rolling(10).mean()

        # # Bollinger Bands
        bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
        dataframe['bb_lowerband'] = bollinger['lower']
        dataframe['bb_middleband'] = bollinger['mid']
        dataframe['bb_upperband'] = bollinger['upper']
        dataframe["bb_percent"] = (
                (dataframe["close"] - dataframe["bb_lowerband"]) /
                (dataframe["bb_upperband"] - dataframe["bb_lowerband"])
        )
        dataframe["bb_width"] = (
                (dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
        )
        dataframe['sar'] = talib.SAR(dataframe)
        # Normalization
        dataframe['ichimoku_conversion_line_1'] = dataframe['ichimoku_conversion_line']
        dataframe['trend_ichimoku_base_1'] = dataframe['trend_ichimoku_base']
        dataframe['trend_kst_diff_1'] = dataframe['trend_kst_diff']

        tib = dataframe['ichimoku_conversion_line']
        dataframe['ichimoku_conversion_line'] = (tib - tib.min()) / (tib.max() - tib.min())
        tib = dataframe['trend_ichimoku_base']
        dataframe['trend_ichimoku_base'] = (tib - tib.min()) / (tib.max() - tib.min())
        tkd = dataframe['trend_kst_diff']
        dataframe['trend_kst_diff'] = (tkd - tkd.min()) / (tkd.max() - tkd.min())

        pivot = pivots_points.pivots_points(dataframe, 72, 3)
        dataframe['r1'] = pivot['r1']
        dataframe['r2'] = pivot['r2']
        dataframe['r3'] = pivot['r3']
        dataframe['s1'] = pivot['s1']
        dataframe['s2'] = pivot['s2']
        dataframe['s3'] = pivot['s3']

        ################### INFORMATIVE BTC 1H
        informative = self.dp.get_pair_dataframe(pair="BTC/USDT", timeframe="1d")
        informative["rsi"] = talib.RSI(informative)
        informative["rsi_5"] = talib.RSI(informative, timeperiod=5)
        informative['pct_change_1'] = informative['close'].pct_change(1)
        dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1d", ffill=True)

        ################### INFORMATIVE BTC 1H
        informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h")
        informative["rsi"] = talib.RSI(informative)
        informative["rsi_5"] = talib.RSI(informative, timeperiod=5)
        informative["rsi_ma"] = informative["rsi"].rolling(5).mean()
        informative['max_rsi'] = talib.MAX(informative['rsi'], timeperiod=10)
        informative['min_rsi'] = talib.MIN(informative['rsi'], timeperiod=10)
        informative['sma7'] = talib.SMA(informative, timeperiod=7)
        informative['pct_change_1'] = informative['close'].pct_change(1)
        bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(informative), window=20, stds=2)
        informative['bb_lowerband'] = bollinger['lower']
        informative['bb_middleband'] = bollinger['mid']
        informative['bb_upperband'] = bollinger['upper']
        informative["bb_percent"] = (
                (informative["close"] - informative["bb_lowerband"]) /
                (informative["bb_upperband"] - informative["bb_lowerband"])
        )
        informative["bb_width"] = (
                (informative["bb_upperband"] - informative["bb_lowerband"]) / informative["bb_middleband"]
        )
        informative['ichimoku_conversion_line'] = ta.trend.ichimoku_conversion_line(
            informative['high'],
            informative['low'],
            window1=9,
            window2=26,
            visual=False,
            fillna=False
        )

        informative['trend_ichimoku_base'] = ta.trend.ichimoku_base_line(
            informative['high'],
            informative['low'],
            window1=9,
            window2=26,
            visual=False,
            fillna=False
        )
        informative['ichimoku_conversion_line_1'] = informative['ichimoku_conversion_line']
        informative['trend_ichimoku_base_1'] = informative['trend_ichimoku_base']

        informative['ichimoku_cut_below'] = qtpylib.crossed_below(informative['ichimoku_conversion_line_1'],
                                                                  informative['trend_ichimoku_base_1'])
        informative['ichimoku_cut_above'] = qtpylib.crossed_above(informative['ichimoku_conversion_line_1'],
                                                                  informative['trend_ichimoku_base_1'])

        tib = informative['ichimoku_conversion_line']
        informative['ichimoku_conversion_line'] = (tib - tib.min()) / (tib.max() - tib.min())
        tib = informative['trend_ichimoku_base']
        informative['trend_ichimoku_base'] = (tib - tib.min()) / (tib.max() - tib.min())
        # tkd = informative['trend_kst_diff']
        # informative['trend_kst_diff'] = (tkd - tkd.min()) / (tkd.max() - tkd.min())

        dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1h", ffill=True)

        return dataframe

    def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # dataframe.loc[
        #     (
        #             (dataframe['trend_ichimoku_base'] <= 0.03) #self.buy_base.value)
        #             & (dataframe['rsi'] < self.buy_rsi.value)
        #             & (dataframe['close'] < dataframe['sma10'])
        #             & (dataframe['min50'].shift(2) == dataframe['min50'])
        #             & (dataframe['pct_change_1_1h'] < 0)
        #             # & (dataframe['close'] <= dataframe['min50'] * (1 + dataframe['bb_width'] / 1.8))
        #     ), ['buy', 'buy_tag']] = (1, 'buy_ichimoku_b')

        dataframe.loc[
            (
                    (dataframe['trend_ichimoku_base'] <= 0.08)  # self.buy_base.value)
                    # & (dataframe['rsi'] < 42) #self.buy_rsi.value)
                    # & (dataframe['sma5_ma_2'] > - 0.002)
                    & (dataframe['close'].shift(2) < dataframe['sma10'].shift(2))
                    & (dataframe['close'].shift(2) < dataframe['sar'].shift(2))
                    & (dataframe['open'].shift(2) < dataframe['sar'].shift(2))
                    # & (dataframe['close'] < dataframe['bb_lowerband'] + dataframe['bb_width'] / 3)
                    & (dataframe['sma10'].shift(1) * 1.001 < dataframe['sma10'])
                # & (dataframe['min50'].shift(2) == dataframe['min50'])
                # & (dataframe['rsi_5_1h'] > 35)
                # & (dataframe['close'] <= dataframe['min50'] * (1 + dataframe['bb_width'] / 1.8))
            ), ['buy', 'buy_tag']] = (1, 'buy_ichimoku_h')

        # dataframe.loc[
        #     (
        #         (dataframe['trend_ichimoku_base'] <= 0.08)
        #         & (dataframe['open'] == dataframe['min50'])
        #         & (dataframe['min50'].shift(4) == dataframe['min50'])
        #     ), ['buy', 'buy_tag']] = (1, 'buy_test')

        return dataframe

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

        return dataframe
