# Zeus Strategy: First Generation of GodStra Strategy with maximum
# AVG/MID profit in USDT
# Author: @Mablue (Masoud Azizi)
# github: https://github.com/mablue/
# IMPORTANT: INSTALL TA BEFOUR RUN(pip install ta)
# freqtrade hyperopt --hyperopt-loss SharpeHyperOptLoss --spaces buy sell roi --strategy Zeus
# --- Do not remove these libs ---
from datetime import timedelta, datetime
from typing import Optional

from freqtrade import data
from freqtrade.persistence import Trade
from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter, IntParameter, BooleanParameter

from numpy.lib import math
from freqtrade.strategy.interface import IStrategy
from freqtrade.strategy import stoploss_from_open, merge_informative_pair, DecimalParameter, IntParameter, CategoricalParameter

import pandas
from pandas import DataFrame
import time
import logging
import calendar
from freqtrade.loggers import setup_logging
from freqtrade.strategy.strategy_helper import merge_informative_pair

# --------------------------------

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

from random import shuffle

logger = logging.getLogger(__name__)

operators = [
    "D",  # Disabled gene
    ">",  # Indicator, bigger than cross indicator
    "<",  # Indicator, smaller than cross indicator
    "=",  # Indicator, equal with cross indicator
    "C",  # Indicator, crossed the cross indicator
    "CA",  # Indicator, crossed above the cross indicator
    "CB",  # Indicator, crossed below the cross indicator
    ">R",  # Normalized indicator, bigger than real number
    "=R",  # Normalized indicator, equal with real number
    "<R",  # Normalized indicator, smaller than real number
    "/>R",  # Normalized indicator devided to cross indicator, bigger than real number
    "/=R",  # Normalized indicator devided to cross indicator, equal with real number
    "/<R",  # Normalized indicator devided to cross indicator, smaller than real number
    "UT",  # Indicator, is in UpTrend status
    "DT",  # Indicator, is in DownTrend status
    "OT",  # Indicator, is in Off trend status(RANGE)
    "CUT",  # Indicator, Entered to UpTrend status
    "CDT",  # Indicator, Entered to DownTrend status
    "COT"  # Indicator, Entered to Off trend status(RANGE)
]
# number of candles to check up,don,off trend.
TREND_CHECK_CANDLES = 8
DECIMALS = 2
fibo = {1, 1, 2, 3, 5, 8, 13, 21}

circulation = {
    'DOGE/USDT': 132670764300,
'BTC/USDT': 19215937,
'LTC/USDT': 71683856,
'ETC/USDT': 138063286,
'BCH/USDT': 19238231,
'ZEC/USDT': 15772013,
'XRP/USDT': 50298735565,
'ADA/USDT': 34424965305,
'MATIC/USDT': 8734317475,
'DOT/USDT': 1139368061,
'SOL/USDT': 362910497,
'SHIB/USDT': 549063278876302,
'TRX/USDT': 92159192741,
'AVAX/USDT': 300677692,
'XMR/USDT': 18204913,
'STD/USDT': 1344947069,
'ZIL/USDT': 13572466120,
'ETH/USDT': 122373866,
'DASH/USDT': 11017123,
'IOTA/USDT': 2779530283,
    'STX/USDT': 1344956059
#https://coinmarketcap.com/

}

buy_crossed_indicator0 = 'MINUS_DM-5'
buy_operator0 = "/<R"
buy_indicator0 = 'MA-20'

buy_crossed_indicator1 = 'DX-5'
buy_operator1 = ">"
buy_indicator1 = 'STOCH-1-10'

buy_crossed_indicator2 = 'LINEARREG-50'
buy_operator2 = "/<R"
buy_indicator2 = 'CDLDRAGONFLYDOJI-5'

from tabulate import tabulate


def pprint_df(dframe):
    print(tabulate(dframe, headers='keys', tablefmt='psql', showindex=False))


def normalize(df):
    df = (df - df.min()) / (df.max() - df.min())
    return df


def gene_calculator(dataframe, indicator):
    # Cuz Timeperiods not effect calculating CDL patterns recognations
    if 'CDL' in indicator:
        splited_indicator = indicator.split('-')
        splited_indicator[1] = "0"
        new_indicator = "-".join(splited_indicator)
        # print(indicator, new_indicator)
        indicator = new_indicator

    gene = indicator.split("-")
    gene_name = gene[0]
    gene_len = len(gene)

    if indicator in dataframe.keys():
        # print(f"{indicator}, calculated befoure")
        # print(len(dataframe.keys()))
        return dataframe[indicator]
    else:
        result = None
        # For Pattern Recognations
        if gene_len == 1:
            # print('gene_len == 1\t', indicator)
            result = getattr(talib, gene_name)(
                dataframe
            )
            return normalize(result)
        elif gene_len == 2:
            # print('gene_len == 2\t', indicator)
            gene_timeperiod = int(gene[1])
            result = getattr(talib, gene_name)(
                dataframe,
                timeperiod=gene_timeperiod,
            )
            return normalize(result)
        # For
        elif gene_len == 3:
            # print('gene_len == 3\t', indicator)
            gene_timeperiod = int(gene[2])
            gene_index = int(gene[1])
            result = getattr(talib, gene_name)(
                dataframe,
                timeperiod=gene_timeperiod,
            ).iloc[:, gene_index]
            return normalize(result)
        # For trend operators(MA-5-SMA-4)
        elif gene_len == 4:
            # print('gene_len == 4\t', indicator)
            gene_timeperiod = int(gene[1])
            sharp_indicator = f'{gene_name}-{gene_timeperiod}'
            dataframe[sharp_indicator] = getattr(talib, gene_name)(
                dataframe,
                timeperiod=gene_timeperiod,
            )
            return normalize(talib.SMA(dataframe[sharp_indicator].fillna(0), TREND_CHECK_CANDLES))
        # For trend operators(STOCH-0-4-SMA-4)
        elif gene_len == 5:
            # print('gene_len == 5\t', indicator)
            gene_timeperiod = int(gene[2])
            gene_index = int(gene[1])
            sharp_indicator = f'{gene_name}-{gene_index}-{gene_timeperiod}'
            dataframe[sharp_indicator] = getattr(talib, gene_name)(
                dataframe,
                timeperiod=gene_timeperiod,
            ).iloc[:, gene_index]
            return normalize(talib.SMA(dataframe[sharp_indicator].fillna(0), TREND_CHECK_CANDLES))


def condition_generator(dataframe, operator, indicator, crossed_indicator, real_num, decalage):
    condition = (dataframe['volume'] > 10)

    # TODO : it ill callculated in populate indicators.

    dataframe[indicator] = gene_calculator(dataframe, indicator)
    dataframe[crossed_indicator] = gene_calculator(dataframe, crossed_indicator)

    indicator_trend_sma = f"{indicator}-SMA-{TREND_CHECK_CANDLES}"
    if operator in ["UT", "DT", "OT", "CUT", "CDT", "COT"]:
        dataframe[indicator_trend_sma] = gene_calculator(dataframe, indicator_trend_sma)

    if operator == ">":
        condition = (dataframe[indicator].shift(decalage) > dataframe[crossed_indicator].shift(decalage))
    elif operator == "=":
        condition = (np.isclose(dataframe[indicator].shift(decalage), dataframe[crossed_indicator].shift(decalage)))
    elif operator == "<":
        condition = (dataframe[indicator].shift(decalage) < dataframe[crossed_indicator].shift(decalage))
    elif operator == "C":
        condition = (
                (qtpylib.crossed_below(dataframe[indicator].shift(decalage),
                                       dataframe[crossed_indicator].shift(decalage))) |
                (qtpylib.crossed_above(dataframe[indicator].shift(decalage),
                                       dataframe[crossed_indicator].shift(decalage)))
        )
    elif operator == "CA":
        condition = (
            qtpylib.crossed_above(dataframe[indicator].shift(decalage), dataframe[crossed_indicator].shift(decalage)))
    elif operator == "CB":
        condition = (
            qtpylib.crossed_below(dataframe[indicator].shift(decalage), dataframe[crossed_indicator].shift(decalage)))
    elif operator == ">R":
        condition = (dataframe[indicator].shift(decalage) > real_num)
    elif operator == "=R":
        condition = (np.isclose(dataframe[indicator].shift(decalage), real_num))
    elif operator == "<R":
        condition = (dataframe[indicator].shift(decalage) < real_num)
    elif operator == "/>R":
        condition = (dataframe[indicator].shift(decalage).div(dataframe[crossed_indicator].shift(decalage)) > real_num)
    elif operator == "/=R":
        condition = (np.isclose(dataframe[indicator].shift(decalage).div(dataframe[crossed_indicator].shift(decalage)),
                                real_num))
    elif operator == "/<R":
        condition = (dataframe[indicator].shift(decalage).div(dataframe[crossed_indicator].shift(decalage)) < real_num)
    elif operator == "UT":
        condition = (dataframe[indicator].shift(decalage) > dataframe[indicator_trend_sma].shift(decalage))
    elif operator == "DT":
        condition = (dataframe[indicator].shift(decalage) < dataframe[indicator_trend_sma].shift(decalage))
    elif operator == "OT":
        condition = (np.isclose(dataframe[indicator].shift(decalage), dataframe[indicator_trend_sma].shift(decalage)))
    elif operator == "CUT":
        condition = (
            (
                    qtpylib.crossed_above(dataframe[indicator].shift(decalage),
                                          dataframe[indicator_trend_sma].shift(decalage))
            ) &
            (
                dataframe[indicator].shift(decalage) > dataframe[indicator_trend_sma].shift(decalage)
            )
        )
    elif operator == "CDT":
        condition = (
            (
                    qtpylib.crossed_below(dataframe[indicator].shift(decalage),
                                          dataframe[indicator_trend_sma].shift(decalage))
            ) &
            (
                dataframe[indicator].shift(decalage) < dataframe[indicator_trend_sma].shift(decalage)
            )
        )
    elif operator == "COT":
        condition = (
            (
                (
                            qtpylib.crossed_below(dataframe[indicator].shift(decalage),
                                                  dataframe[indicator_trend_sma].shift(decalage))
                ) |
                (
                            qtpylib.crossed_above(dataframe[indicator].shift(decalage),
                                                  dataframe[indicator_trend_sma].shift(decalage))
                )
            ) &
            (
                np.isclose(dataframe[indicator].shift(decalage), dataframe[indicator_trend_sma].shift(decalage))
            )
        )
    return condition, dataframe

class Zeus_8_3_2_B_4(IStrategy):

    # ROI table:
    minimal_roi = {
        "0": 0.564,
        "567": 0.273,
        "2814": 0.12,
        "7675": 0
    }

    # Stoploss:
    stoploss = -1 #0.256
    # Custom stoploss
    use_custom_stoploss = True

    # Buy hypers
    timeframe = '5m'

    max_open_trades = 5
    max_amount = 40

    # DCA config
    position_adjustment_enable = True

    plot_config = {
        "main_plot": {
            "min200": {
                "color": "#86c932"
            },
            "max50": {
                "color": "white"
            },
            "max200": {
                "color": "yellow"
            },
            "sma3_1d": {
                "color": "pink"
            },
            "sma5_1d": {
                "color": "blue"
            },
            "sma10_1d": {
                "color": "orange"
            },
            "close_1d": {
                "color": "#73e233",
            },
            "bb_lowerband": {
                "color": "#da59a6"},
            "bb_upperband": {
                "color": "#da59a6",
            },
            "sar": {
                "color": "#4f9f51",
            },
            "min5_1d": {
                "color": "#6aa123",
            },
            "max5_1d": {
                "color": "red"
            },
            "max3_1d": {
                "color": "blue"
            }
        },
        "subplots": {
            # "Ind": {
            #     "trend_ichimoku_base": {
            #         "color": "#dd1384"
            #     },
            #     "trend_kst_diff": {
            #         "color": "#850678"
            #     }
            # },
            # "BB": {
            #     "bb_width": {
            #         "color": "white"
            #     },
            #     "bb_lower_5": {
            #         "color": "yellow"
            #     }
            # },
            # "Cond": {
            #     "cond1": {
            #         "color": "yellow"
            #     }
            # },
            "Rsi": {
                "rsi": {
                    "color": "pink"
                },
                "rsi_1d": {
                    "color": "yellow"
                }
            },
            "Percent": {
                "max_min": {
                    "color": "#74effc"
                },
                "pct_change_1_1d": {
                    "color": "green"
                },
                "pct_change_3_1d": {
                    "color": "orange"
                },
                "pct_change_5_1d": {
                    "color": "red"
                },
                "sma5_pct": {
                    "color": "yellow"
                }
            }
        }
    }
    trades = list()
    # buy_real = DecimalParameter(0.001, 0.999, decimals=4, default=0.5392, space='buy')
    # buy_cat = CategoricalParameter([">R", "=R", "<R"], default='<R', space='buy')
    # buy_rsi_ichimoku = CategoricalParameter(["rsi", "rsi_1h", "rsi_4h", "rsi_1d"], default='rsi', space='buy')
    # buy_rsi_divisor = IntParameter(30, 70, default=50, space='buy')
    # buy_bb_pente = DecimalParameter(1, 10, decimals=1, default=5, space='buy')

    # buy_base = DecimalParameter(0, 0.5, decimals=2, default=0.19, space='buy')
    # buy_rsi = IntParameter(20, 90, default=72, space='buy')
    # buy_rsi_1h = IntParameter(20, 90, default=72, space='buy')
    # buy_rsi_1d = IntParameter(20, 90, default=72, space='buy')
    # buy_sum_rsi_1h = DecimalParameter(-20, 20, decimals=1, default=0, space='buy')
    # buy_sum_rsi_1d = DecimalParameter(-20, 20, decimals=1, default=0, space='buy')

    # buy_bb_width_n = DecimalParameter(1, 10, decimals=1, default=5, space='buy')
    # decalage_min50 = IntParameter(0, 6, default=3, space='buy')
    # percent_close_50 = DecimalParameter(1, 1.01, decimals=3, default=1.002, space='buy')
    # pct_change_1h = DecimalParameter(0, 0.01, decimals=3, default=0.002, 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_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')

    protection_percent_buy_lost = IntParameter(1, 10, default=5, space='protection')
    # protection_nb_buy_lost = IntParameter(1, 2, default=2, space='protection')

    protection_fibo = IntParameter(1, 10, default=2, space='protection')

    # trailing stoploss hyperopt parameters
    # hard stoploss profit
    pHSL = DecimalParameter(-0.200, -0.040, default=-0.08, decimals=3, space='sell', optimize=False, load=True)
    # profit threshold 1, trigger point, SL_1 is used
    pPF_1 = DecimalParameter(0.008, 0.020, default=0.016, decimals=3, space='sell', optimize=True, load=True)
    pSL_1 = DecimalParameter(0.008, 0.020, default=0.011, decimals=3, space='sell', optimize=True, load=True)

    # profit threshold 2, SL_2 is used
    pPF_2 = DecimalParameter(0.040, 0.100, default=0.080, decimals=3, space='sell', optimize=True, load=True)
    pSL_2 = DecimalParameter(0.020, 0.070, default=0.040, decimals=3, space='sell', optimize=True, load=True)

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

        # hard stoploss profit
        HSL = self.pHSL.value
        PF_1 = self.pPF_1.value
        SL_1 = self.pSL_1.value
        PF_2 = self.pPF_2.value
        SL_2 = self.pSL_2.value

        # For profits between PF_1 and PF_2 the stoploss (sl_profit) used is linearly interpolated
        # between the values of SL_1 and SL_2. For all profits above PL_2 the sl_profit value
        # rises linearly with current profit, for profits below PF_1 the hard stoploss profit is used.

        if current_profit > PF_2:
            sl_profit = SL_2 + (current_profit - PF_2)
        elif current_profit > PF_1:
            sl_profit = SL_1 + ((current_profit - PF_1) * (SL_2 - SL_1) / (PF_2 - PF_1))
        else:
            sl_profit = HSL

        return stoploss_from_open(sl_profit, current_profit)

    def custom_exit(self, pair: str, trade: Trade, current_time, current_rate, current_profit, **kwargs):

        dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
        last_candle = dataframe.iloc[-1].squeeze()
        candle_12 = dataframe.iloc[-13].squeeze()

        expected_profit = 0.01
        #print(last_candle['buy_tag'])

        days = (current_time - trade.open_date_utc).days
        hours = (current_time - trade.open_date_utc).seconds / 3600

        # fibo_fact = fibo[hours]
        ######
        # if last_candle['percent5'] < -0.05:
        #     return "stop_loss_005"

        if last_candle['pct_change_1_1h'] <= 0: #(self.market_overview_pct5 < 0) | (last_candle['pct_change_1_4h'] < 0):
            max_percent = 0.004  # last_candle['bb_width'] / 3.5  # 0.005
            max_profit = 0.004  # last_candle['bb_width'] * 3 / 4 # 0.015

            if (current_profit > 0.01) & \
                    (last_candle['percent10'] < -0.005) & ((current_time - trade.open_date_utc).seconds >= 3600):
                return 'b_percent10'
            if (current_profit > max_profit) & \
                    ((last_candle['percent'] < - max_percent) | (last_candle['percent3'] < -max_percent) | (
                            last_candle['percent5'] < -max_percent)):
                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)\
                    & (last_candle['sma10_s2'] > last_candle['sma10']) & (last_candle['percent3'] < 0) \
                    & (last_candle['echange*pct12'] < 0.0005):
                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) \
                    & (last_candle['sma10_s2'] > last_candle['sma10']) & (last_candle['percent3'] < 0)\
                    & (last_candle['echange*pct12'] < 0.0005):
                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) \
                    & (last_candle['sma10_s2'] > last_candle['sma10']) & (last_candle['percent3'] < 0)\
                    & (last_candle['echange*pct12'] < 0.0005):
                return "b_too_old_0.03"

            if self.profit_b_quick_lost.value and (current_profit >= max_profit) & (
                    last_candle['percent3'] < -max_percent):
                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) \
                        & ((last_candle['sma5_s5'] > 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) \
                        & ((last_candle['sma10_s5'] > 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 > max_percent) \
                        & (last_candle['sma10_s2'] > last_candle['sma10']) \
                        & ((current_time - trade.open_date_utc).seconds >= 3600) \
                        & ((last_candle['sma20_s2'] > 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 False: #self.profit_b_over_rsi.value:
                if (current_profit > 0) & (last_candle['rsi_s2'] > self.sell_b_RSI.value):  # & (last_candle['percent'] < 0): #| (last_candle['rsi_s2'] > 75 & last_candle['rsi'] < 70)):
                    # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
                    return 'b_over_rsi'

                if (current_profit > 0) & (last_candle['rsi_s2'] > self.sell_b_RSI2.value) & \
                        (last_candle[
                             'percent'] < - self.sell_b_RSI2_percent.value):  # | (last_candle['rsi_s2'] > 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) & (last_candle['rsi_s2'] > self.sell_b_RSI3.value) & \
                        (last_candle['close'] >= last_candle['max200']) & (last_candle[
                                                                               'percent'] < - self.sell_b_RSI2_percent.value):  # | (last_candle['rsi_s2'] > 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) & (last_candle['percent10_s2'] > 0.04) & (
                        last_candle['percent'] < 0) \
                        & (days >= 1): #| (last_candle['rsi_s2'] > 75 & last_candle['rsi'] < 70)):
                    # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
                    return 'b_short_lost'
        else:

            max_percent = 0.005  # last_candle['bb_width'] / 3.5  # 0.005
            max_profit = 0.01  # last_candle['bb_width'] * 3 / 4 # 0.015

            if (current_profit > max_profit) & (
                    (last_candle['percent'] < -max_percent) | (last_candle['percent3'] < -max_percent) | (
                    last_candle['percent5'] < -max_percent)):
                return 'h_percent_quick'

            # if (last_candle['bb_width'] < 0.02) & (current_profit > 0) & (last_candle['close'] > bb_width_up) & \
            #     ((last_candle['percent'] < - bb_width_lim) | (last_candle['percent3'] < - bb_width_lim) | (last_candle['percent5'] < - bb_width_lim)):
            #     return 'h_bb_width_max'

            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)\
                    & (last_candle['sma10_s2'] > last_candle['sma10']) & (last_candle['percent3'] < 0)\
                    & (last_candle['echange*pct12'] < 0.001):
                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) \
                    & (last_candle['sma10_s2'] > last_candle['sma10']) & (last_candle['percent3'] < 0)\
                    & (last_candle['echange*pct12'] < 0.001):
                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) \
                    & (last_candle['sma10_s2'] > last_candle['sma10']) & (last_candle['percent3'] < 0)\
                    & (last_candle['echange*pct12'] < 0.001):
                return "h_too_old_0.03"

            if self.profit_h_quick_lost.value and (current_profit >= max_profit) & (
                    last_candle['percent3'] < -max_percent):
                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) \
                        & ((last_candle['sma5_s5'] > 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) \
                        & ((last_candle['sma10_s5'] > 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 > max_percent) \
                        & (last_candle['sma10_s2'] > last_candle['sma10']) \
                        & ((current_time - trade.open_date_utc).seconds >= 3600) \
                        & ((last_candle['sma20_s2'] > last_candle['sma20']) &
                           ((last_candle['percent'] < 0) & (last_candle['percent5'] < 0) & (last_candle['percent10'] < 0))):
                    # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
                    return 'h_sma20'

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

                if (current_profit > 0) & (last_candle['rsi_s2'] > self.sell_h_RSI2.value) & \
                        (last_candle[
                             'percent'] < - self.sell_h_RSI2_percent.value):  # | (last_candle['rsi_s2'] > 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) & (last_candle['rsi_s2'] > self.sell_h_RSI3.value) & \
                        (last_candle['close'] >= last_candle[
                            'max200']):  # | (last_candle['rsi_s2'] > 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) & (last_candle['percent10_s2'] > 0.04) & (
                        last_candle['percent'] < 0) \
                        & (days >= 1): #| (last_candle['rsi_s2'] > 75 & last_candle['rsi'] < 70)):
                    # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
                    return 'h_short_lost'


    def informative_pairs(self):
        # get access to all pairs available in whitelist.
        pairs = self.dp.current_whitelist()
        informative_pairs = [(pair, '1d') for pair in pairs]
        informative_pairs += [(pair, '4h') for pair in pairs]
        informative_pairs += [(pair, '1h') for pair in pairs]

        return informative_pairs

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

        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['pct_change'] = dataframe['close'].pct_change(5)
        dataframe['min'] = talib.MIN(dataframe['close'], timeperiod=200)
        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['min200'] = talib.MIN(dataframe['close'], timeperiod=200)
        dataframe['min50_005'] = dataframe['min50'] * 1.005
        dataframe['min200_005'] = dataframe['min200'] * 1.005
        dataframe['moy200_12'] = dataframe['min200'].rolling(12).mean() 

        dataframe['mean10'] = dataframe['close'].rolling(10).mean()
        dataframe['mean20'] = dataframe['close'].rolling(20).mean()
        dataframe['mean50'] = dataframe['close'].rolling(50).mean()
        dataframe['mean100'] = dataframe['close'].rolling(100).mean()


        dataframe['max50'] = talib.MAX(dataframe['close'], timeperiod=50)
        dataframe['min_max_50'] = (dataframe['max50'] - dataframe['min50']) / dataframe['min50']

        dataframe['max200'] = talib.MAX(dataframe['close'], timeperiod=200)
        dataframe['min_max200'] = (dataframe['max200'] - dataframe['min200']) / dataframe['min200']
        dataframe['rsi'] = talib.RSI(dataframe)
        dataframe['rsi_pente'] = dataframe['rsi'].pct_change(1)
        dataframe['rsi_acc'] = dataframe['rsi_pente'].pct_change(1)
        dataframe['sum_rsi'] = (dataframe['rsi'].rolling(5).sum() - 250) / 5

        dataframe['rsi5'] = talib.RSI(dataframe, timeperiod=5)
        dataframe['sma5'] = talib.SMA(dataframe, timeperiod=5)
        dataframe['sma10'] = talib.SMA(dataframe, timeperiod=10)
        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["volume5"] = dataframe["volume"].rolling(5).sum()
        dataframe["volume10"] = dataframe["volume"].rolling(10).sum()

        dataframe['sma5_s2'] = dataframe['sma5'].shift(1)
        dataframe['sma10_s2'] = dataframe['sma10'].shift(1)
        dataframe['sma20_s2'] = dataframe['sma20'].shift(1)
        dataframe['percent10_s2'] = dataframe['percent10'].shift(1)
        dataframe['rsi_s2'] = dataframe['rsi'].shift(1)

        dataframe['sma5_s5'] = dataframe['sma5'].shift(4)
        dataframe['sma10_s5'] = dataframe['sma10'].shift(4)
        dataframe['sma20_s5'] = dataframe['sma20'].shift(4)
        # print(metadata['pair'])
        # print(circulation[metadata['pair']])
        if circulation[metadata['pair']]:
            dataframe["echange"] = 10000 * dataframe["volume"] / circulation[metadata['pair']]
            dataframe["echange*pct"] = dataframe["echange"] * dataframe["percent"]
            dataframe["echange5"] = 10000 * dataframe["volume5"] / circulation[metadata['pair']]
            dataframe["echange*pct5"] = dataframe["echange5"] * dataframe["percent5"]
            dataframe["pct_echange5"] = dataframe["echange5"].pct_change()
            dataframe["acc_echange5"] = dataframe["echange*pct5"] / dataframe["echange*pct5"].shift(1)
            for i in range(1, 4):
                n = i * 12
                dataframe["echange*pct" + str(n)] = 10000 * dataframe["volume"].rolling(n).sum() / circulation[metadata['pair']] \
                                               * dataframe["percent"].rolling(n).sum()

        dataframe["pente20"] = (dataframe["close"] - dataframe['close'].shift(20)) / dataframe["close"]

        # 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_ecart"] = ((dataframe["bb_upperband"] - dataframe["bb_lowerband"]))
        dataframe["bb_width"] = (
            (dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
        )
        dataframe['bb_lower_var_5'] = (dataframe['bb_lowerband'] - dataframe['min50']).rolling(5).var()
        dataframe['bb_lower_5'] = 100 * ((dataframe['bb_lowerband'].rolling(5).mean() / dataframe['bb_lowerband']) - 1)
        # dataframe['bb_lower_width_5'] = (dataframe['bb_lowerband'] * (1 + dataframe['bb_width'] / self.buy_bb_width_n.value))
        dataframe["bb_pente"] = (dataframe["bb_lowerband"] - dataframe['bb_lowerband'].shift(3)) / dataframe["bb_lowerband"]
        dataframe["bb_pente_inv"] = (dataframe["bb_pente"].shift(2) > dataframe["bb_pente"].shift(1)) & \
                            (dataframe["bb_pente"] > dataframe["bb_pente"].shift(1))
        dataframe["bb_max_width"] = (dataframe["bb_ecart"].shift(2) < dataframe["bb_ecart"].shift(1)) & \
                                    (dataframe["bb_ecart"] < dataframe["bb_ecart"].shift(1))
        dataframe["bb_tag"] = dataframe["bb_pente_inv"] & dataframe["bb_max_width"]
        # dataframe['bb_min'] = talib.MIN(dataframe['bb_lowerband'], timeperiod=36)

        dataframe['distance_min'] = (dataframe['close'] - dataframe['min']) / dataframe['close']
        dataframe['min50_1.01'] = 1.01 * dataframe['min50']
        dataframe['min50_1.02'] = 1.02 * dataframe['min50']
        dataframe['min50_1.03'] = 1.03 * dataframe['min50']
        dataframe['normal'] = 100 * (dataframe['close'] / dataframe['close'].rolling(200).mean())
        # dataframe['normal_var_20'] = dataframe['normal'].rolling(20).var()
        # dataframe['normal_var_50'] = dataframe['normal'].rolling(50).var()

        dataframe['min_max_close'] = (
                    (dataframe['max200'] - dataframe['close']) / (dataframe['close'] - dataframe['min200']))
        dataframe['sar'] = talib.SAR(dataframe)
        # Normalization
        tib = dataframe['trend_ichimoku_base']
        dataframe['trend_ichimoku_base'] = normalize(tib) #(tib-tib.min())/(tib.max()-tib.min())
        dataframe["trend_ichimoku_pente"] = (dataframe["trend_ichimoku_base"] - dataframe['trend_ichimoku_base'].shift(3)) / dataframe["trend_ichimoku_base"]

        tkd = dataframe['trend_kst_diff']
        dataframe['trend_kst_diff'] = normalize(tkd) #(tkd-tkd.min())/(tkd.max()-tkd.min())

        # dataframe['trend_ichimoku_base_50'] = talib.MIN(dataframe['trend_ichimoku_base'], timeperiod=50)
        # dataframe['trend_ichimoku_base_5'] = talib.MIN(dataframe['trend_ichimoku_base'], timeperiod=5)
        # dataframe['trend_ichimoku_base_sma5'] = talib.SMA(dataframe['trend_ichimoku_base'], timeperiod=5)
        # dataframe['trend_ichimoku_base_pct'] = dataframe['trend_ichimoku_base'].pct_change(3)

        dataframe[buy_crossed_indicator0] = gene_calculator(dataframe, buy_crossed_indicator0)
        dataframe[buy_crossed_indicator1] = gene_calculator(dataframe, buy_crossed_indicator1)
        dataframe[buy_crossed_indicator2] = gene_calculator(dataframe, buy_crossed_indicator2)

        dataframe[buy_indicator0] = gene_calculator(dataframe, buy_indicator0)
        dataframe[buy_indicator1] = gene_calculator(dataframe, buy_indicator1)
        dataframe[buy_indicator2] = gene_calculator(dataframe, buy_indicator2)

        dataframe["cond1"] = dataframe[buy_indicator0].div(dataframe[buy_crossed_indicator0])
        dataframe['cond_50'] = talib.MIN(dataframe['cond1'], timeperiod=50)
        dataframe['cond_5'] = talib.MIN(dataframe['cond1'], timeperiod=5)
        dataframe['cond_sma5'] = talib.SMA(dataframe['cond1'], timeperiod=5)
        dataframe['cond_pct'] = dataframe['cond1'].pct_change(3)
        dataframe['atr'] = talib.ATR(dataframe, timeperiod=14)

        #FreqAI / Rewards
        # dataframe["%-raw_close"] = dataframe["close"]
        # dataframe["%-raw_open"] = dataframe["open"]
        # dataframe["%-raw_high"] = dataframe["high"]
        # dataframe["%-raw_low"] = dataframe["low"]

        ################### INFORMATIVE 1D
        informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1d")
        informative["rsi"] = talib.RSI(informative, timeperiod=7)
        informative['sum_rsi'] = (informative['rsi'].rolling(5).sum() - 250) / 5
        informative["max3"] = talib.MAX(informative['close'], timeperiod=3)
        informative["min3"] = talib.MIN(informative['close'], timeperiod=3)
        informative['min5'] = talib.MIN(informative['close'], timeperiod=5)
        informative['max3'] = talib.MAX(informative['close'], timeperiod=3)
        informative['max5'] = talib.MAX(informative['close'], timeperiod=5)
        informative['pct_change_1'] = informative['close'].pct_change(1)
        informative['pct_change_3'] = informative['close'].pct_change(3)
        informative['pct_change_5'] = informative['close'].pct_change(5)
        informative['sma3'] = talib.SMA(informative, timeperiod=3)
        informative['sma5'] = talib.SMA(informative, timeperiod=5)
        informative['sma10'] = talib.SMA(informative, timeperiod=10)
        # informative['sar'] = talib.SAR(informative)

        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"]
        )

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

        ######################## INFORMATIVE 4h
        informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="4h")
        informative["rsi"] = talib.RSI(informative)
        informative['pct_change_1'] = informative['close'].pct_change(1)
        informative['pct_change_3'] = informative['close'].pct_change(3)
        informative['pct_change_5'] = informative['close'].pct_change(5)
        informative['sma3'] = talib.SMA(informative, timeperiod=3)
        informative['sma5'] = talib.SMA(informative, timeperiod=5)
        informative['sma10'] = talib.SMA(informative, timeperiod=10)

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

        ######################## INFORMATIVE 1h
        informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h")
        informative["rsi"] = talib.RSI(informative)
        informative["mrsi3"] = informative["rsi"].rolling(3).mean()
        informative['pct_change_1'] = informative['close'].pct_change(1)
        informative['pct_change_3'] = informative['close'].pct_change(3)
        informative['pct_change_5'] = informative['close'].pct_change(5)
        informative['sma3'] = talib.SMA(informative, timeperiod=3)
        informative['sma5'] = talib.SMA(informative, timeperiod=5)
        informative['sma10'] = talib.SMA(informative, timeperiod=10)
        informative['min3'] = talib.MIN(informative['close'], timeperiod=3)
        informative['min5'] = talib.MIN(informative['close'], timeperiod=5)
        informative['rsi_pente'] = informative['rsi'].pct_change(1)
        informative['rsi_acc'] = informative['rsi_pente'].pct_change(1)
        informative['sum_rsi'] = (informative['rsi'].rolling(5).sum() - 250) / 5

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

        # dataframe['support'] = min(dataframe['close_1d'], dataframe['sma3_1d'], dataframe['sma3_1d'])
        return dataframe

    # 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:
    #
    #     # {'symbol': 'FTM/USDT', 'timestamp': 1646494199570, 'datetime': '2022-03-05T15:29:59.570Z', 'high': 1.7489,
    #     #  'low': 1.6084, 'bid': 1.6505, 'bidVolume': 2135.0, 'ask': 1.6508, 'askVolume': 2815.0, 'vwap': 1.66852198,
    #     #  'open': 1.7313, 'close': 1.6505, 'last': 1.6505, 'previousClose': '1.73170000', 'change': -0.0808,
    #     #  'percentage': -4.667, 'average': 1.6909, 'baseVolume': 124656725.0, 'quoteVolume': 207992485.7799,
    #     #  'info':
    #     #  {'symbol': 'FTMUSDT', 'priceChange': '-0.08080000', 'priceChangePercent': '-4.667',
    #     #       'weightedAvgPrice': '1.66852198', 'prevClosePrice': '1.73170000', 'lastPrice': '1.65050000',
    #     #       'lastQty': '143.00000000', 'bidPrice': '1.65050000', 'bidQty': '2135.00000000',
    #     #       'askPrice': '1.65080000', 'askQty': '2815.00000000', 'openPrice': '1.73130000',
    #     #       'highPrice': '1.74890000', 'lowPrice': '1.60840000', 'volume': '124656725.00000000',
    #     #       'quoteVolume': '207992485.77990000', 'openTime': '1646407799570', 'closeTime': '1646494199570',
    #     #       'firstId': '137149614', 'lastId': '137450289', 'count': '300676'}} - 0.9817468621938484
    #
    #     allow_to_buy = True
    #     max_gain = -100
    #     sum_gain = 0
    #     max_time = 0
    #
    #     if self.dp:
    #         if self.dp.runmode.value in ('live', 'dry_run'):
    #             if len(self.trades) == 0:
    #                 print('search')
    #                 self.trades = Trade.get_open_trades()
    #
    #             if len(self.trades) >= self.config['max_open_trades'] / 2:
    #                 for trade in self.trades:
    #                     ticker = self.dp.ticker(trade.pair)
    #                     last_price = ticker['last']
    #                     gain = (last_price - trade.open_rate) / trade.open_rate
    #                     max_gain = max(max_gain, gain)
    #                     sum_gain += gain
    #                     max_time = max(max_time, datetime.timestamp(trade.open_date))
    #                     print(trade.pair, ticker['datetime'], ticker['timestamp'] / 1000, datetime.timestamp(trade.open_date),
    #                           datetime.timestamp(trade.open_date) - int(ticker['timestamp'] / 1000))
    #                 now = datetime.now()
    #                 diff = (datetime.timestamp(now) - max_time / 3600)
    #                 if (max_gain <= -0.05) & (len(self.trades) >= self.config['max_open_trades'] / 2) & (diff < 6):
    #                     print("allow_to_buy=false")
    #                     allow_to_buy = False
    #                 print(pair, allow_to_buy, len(self.trades),
    #                       "max gain=", max_gain,
    #                       "sum_gain=", sum_gain,
    #                       "now=", now,
    #                       "max=", max_time,
    #                       "diff=", datetime.timestamp(now) - max_time)
    #
    #             if allow_to_buy:
    #                 self.trades = list()
    #
    #     return allow_to_buy

    def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # enter_long_conditions = [dataframe["do_predict"] == 1] #, dataframe["&-s_close"] > dataframe["target_roi"]]
        #
        # if enter_long_conditions:
        #     dataframe.loc[
        #         reduce(lambda x, y: x & y, enter_long_conditions), ["enter_long", "enter_tag"]
        #     ] = (1, "long")

        base = 0.33 #self.buy_base.value
        # base = base / dataframe[self.buy_rsi_ichimoku.value] * self.buy_rsi_divisor.value
        base = base / dataframe['rsi'] * 52

        decalage = 3
        dataframe.loc[
            (
               # (reduce(lambda x, y: x & y, enter_long_conditions))
               (dataframe['trend_ichimoku_base'].shift(decalage) <= base)
               # & (dataframe['close'] > dataframe['close_1d'])
               & (dataframe['rsi'].shift(decalage) < 60)
               & (dataframe['close'].shift(decalage) < dataframe['sma10'].shift(decalage))
               & (dataframe['close'].shift(decalage) < dataframe['bb_middleband'].shift(decalage))
               & (dataframe['bb_width'].shift(decalage) > 0.025)
               # & (dataframe['close'].shift(decalage) < dataframe['bb_lower_width_5'].shift(decalage))
               & ((dataframe['close'].shift(decalage) <= dataframe['min50'].shift(decalage) * 1.002) |
                  (dataframe['pct_change_1_1h'].shift(decalage) > - 0.002)
                  )
               # & (dataframe['close'] <= dataframe['bb_upperband'])
               # & (dataframe['close'] <= dataframe['min_200_001'])
               & (dataframe['close'].shift(decalage) <= dataframe['close_1h'].shift(decalage))
               & ((dataframe['close'].shift(decalage) < dataframe['bb_lowerband'].shift(decalage)) |
                  (dataframe['pct_change_1_1h'].shift(decalage) > - 0.002)
                  )
               & (dataframe['close'] < dataframe['bb_upperband'])
               & (dataframe['open'] < dataframe['bb_upperband'])
               & ((dataframe['bb_pente_inv'] == 1) | (dataframe['bb_pente_inv'].shift(1) == 1) | (dataframe['bb_pente_inv'].shift(2) == 1)
               | (dataframe['bb_pente_inv'].shift(3) == 1))
               # & (dataframe['close_1d'] < dataframe['bb_upperband_1d'])
            ), ['buy', 'enter_tag']] = (1, 'buy_ichimoku')

        return dataframe

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

        return dataframe

    def adjust_trade_position(self, trade: Trade, current_time: datetime,
                              current_rate: float, current_profit: float, min_stake: float,
                              max_stake: float, **kwargs):
        dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe)
        if True: #(len(dataframe) < 1):
            return None
        # print(dataframe)
        last_candle = dataframe.iloc[-1].squeeze()
        # last_candle_5 = dataframe.iloc[-3].squeeze()

        min_d = min(last_candle['sma3_4h'], last_candle['close_1d'])

        filled_buys = trade.select_filled_orders('buy')
        count_of_buys = len(filled_buys)
        days = (current_time - trade.open_date_utc).days
        minutes = (current_time - trade.open_date_utc).seconds / 60
        # condition = (last_candle['cond1'] <= 0.75) & (last_candle['bb_width'] > 0.018) & (
        #             last_candle['rsi'] < 72) & (last_candle['close'] < last_candle['min50'] * 1.006)# & (last_candle['min_max_close'] > 2)

        condition = (last_candle['enter_long'] == 1) # & (last_candle['close'] <= last_candle['close_1h'])
        p = self.protection_percent_buy_lost.value
        percents = [p, p * 2, p * 3, p * 4, p * 5, p * 6, p * 7, p * 8, p * 9]

        # self.protection_nb_buy_lost.value
        if (0 < count_of_buys <= 2) \
                & (current_profit < - (percents[count_of_buys - 1] / 100)) & (condition):
            try:
                p = self.config['stake_amount']
                if last_candle['close'] < last_candle['min5_1h']:
                    factors = [1.5 * p, 1.75 * p, 2 * p, 2 * p, 3 * p, 4 * p, 5 * p, 6 * p]
                else:
                    if last_candle['close'] < last_candle['min3_1h']:
                        factors = [1.25 * p, 1.5 * p, 2 * p, 2 * p, 3 * p, 4 * p, 5 * p, 6 * p]
                    else:
                        factors = [1 * p, 1.25 * p, 2 * p, 2 * p, 3 * p, 4 * p, 5 * p, 6 * p]
                stake_amount = factors[count_of_buys - 1]# filled_buys[0].cost
                # This then calculates current safety order size
                # stake_amount = stake_amount * pow(1.5, count_of_buys)
                # print("-----------" + trade.pair + " " + str(current_profit) + " " + str(count_of_buys) + " " + str(stake_amount) + "---------------------")
                return stake_amount
            except Exception as exception:
                print(exception)
                return None
        return None
