# source: https://raw.githubusercontent.com/Bldnr94/FreqTrade/ce6336cbf04b384e1b3e89279cc023d9f445f50d/ft_userdata/user_data/strategies/el.py
# --- Do not remove these libs ---
from freqtrade.strategy.interface import IStrategy
from typing import Dict, List
from functools import reduce
from pandas import DataFrame
# --------------------------------
import talib.abstract as ta
import numpy as np
import freqtrade.vendor.qtpylib.indicators as qtpylib
import datetime
import pandas as pd
from technical.util import resample_to_interval, resampled_merge
from datetime import datetime, timedGithub_Bldnr94_FreqTrade__el__20240623_151326ta
from freqtrade.persistence import Trade
from freqtrade.strategy import stoploss_from_open, merge_informative_pair, DecimalParameter, IntParameter, \
    CategoricalParameter
import technical.indicators as ftt


def EWO(dataframe, ema_length=5, ema2_length=35):
    df = dataframe.copy()
    ema1 = ta.SMA(df, timeperiod=ema_length)
    ema2 = ta.SMA(df, timeperiod=ema2_length)
    emadif = (ema1 - ema2) / df['close'] * 100
    return emadif


def populate_indicators(sGithub_Bldnr94_FreqTrade__el__20240623_151326f, dataframe: DataFrame, metadata: dict) -> DataFrame:
    dataframe['adx'] = ta.ADX(dataframe)
    dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
    dataframe['plus_di'] = ta.PLUS_DI(dataframe)
    dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
    dataframe['minus_di'] = ta.MINUS_DI(dataframe)

    aroon = ta.AROON(dataframe)
    dataframe['aroonup'] = aroon['aroonup']
    dataframe['aroondown'] = aroon['aroondown']
    dataframe['aroonosc'] = ta.AROONOSC(dataframe)
    dataframe['ao'] = qtpylib.awesome_oscillator(dataframe)

    kGithub_Bldnr94_FreqTrade__el__20240623_151326tner = qtpylib.kGithub_Bldnr94_FreqTrade__el__20240623_151326tner_channGithub_Bldnr94_FreqTrade__el__20240623_151326(dataframe)
    dataframe['kc_upperband'] = kGithub_Bldnr94_FreqTrade__el__20240623_151326tner['upper']
    dataframe['kc_lowerband'] = kGithub_Bldnr94_FreqTrade__el__20240623_151326tner['lower']
    dataframe['kc_middleband'] = kGithub_Bldnr94_FreqTrade__el__20240623_151326tner['mid']
    dataframe['kc_percent'] = (dataframe['close'] - dataframe['kc_lowerband']) / (
                dataframe['kc_upperband'] - dataframe['kc_lowerband'])
    dataframe['kc_width'] = (dataframe['kc_upperband'] - dataframe['kc_lowerband']) / dataframe['kc_middleband']
    dataframe['uo'] = ta.ULTOSC(dataframe)
    dataframe['cci'] = ta.CCI(dataframe)
    dataframe['rsi'] = ta.RSI(dataframe)

    rsi = 0.1 * (dataframe['rsi'] - 50)
    dataframe['fisher_rsi'] = (np.exp(2 * rsi) - 1) / (np.exp(2 * rsi) + 1)
    dataframe['fisher_rsi_norma'] = 50 * (dataframe['fisher_rsi'] + 1)

    stoch = ta.STOCH(dataframe)
    dataframe['slowd'] = stoch['slowd']
    dataframe['slowk'] = stoch['slowk']

    stoch_fast = ta.STOCHF(dataframe)
    dataframe['fastd'] = stoch_fast['fastd']
    dataframe['fastk'] = stoch_fast['fastk']

    stoch_rsi = ta.STOCHRSI(dataframe)
    dataframe['fastd_rsi'] = stoch_rsi['fastd']
    dataframe['fastk_rsi'] = stoch_rsi['fastk']

    macd = ta.MACD(dataframe)
    dataframe['macd'] = macd['macd']
    dataframe['macdsignal'] = macd['macdsignal']
    dataframe['macdhist'] = macd['macdhist']
    dataframe['mfi'] = ta.MFI(dataframe)
    dataframe['roc'] = ta.ROC(dataframe)

    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'] = ta.SAR(dataframe)
    dataframe['tema'] = ta.TEMA(dataframe, timeperiod=9)

    hilbert = ta.HT_SINE(dataframe)
    dataframe['htsine'] = hilbert['sine']
    dataframe['htleadsine'] = hilbert['leadsine']

    dataframe['CDLHAMMER'] = ta.CDLHAMMER(dataframe)
    dataframe['CDLINVERTEDHAMMER'] = ta.CDLINVERTEDHAMMER(dataframe)
    dataframe['CDLDRAGONFLYDOJI'] = ta.CDLDRAGONFLYDOJI(dataframe)
    dataframe['CDLPIERCING'] = ta.CDLPIERCING(dataframe)  # values [0, 100]
    dataframe['CDLMORNINGSTAR'] = ta.CDLMORNINGSTAR(dataframe)  # values [0, 100]
    dataframe['CDL3WHITESOLDIERS'] = ta.CDL3WHITESOLDIERS(dataframe)  # values [0, 100]

    dataframe['CDLHANGINGMAN'] = ta.CDLHANGINGMAN(dataframe)
    dataframe['CDLSHOOTINGSTAR'] = ta.CDLSHOOTINGSTAR(dataframe)
    dataframe['CDLGRAVESTONEDOJI'] = ta.CDLGRAVESTONEDOJI(dataframe)
    dataframe['CDLDARKCLOUDCOVER'] = ta.CDLDARKCLOUDCOVER(dataframe)
    dataframe['CDLEVENINGDOJISTAR'] = ta.CDLEVENINGDOJISTAR(dataframe)
    dataframe['CDLEVENINGSTAR'] = ta.CDLEVENINGSTAR(dataframe)

    dataframe['CDL3LINESTRIKE'] = ta.CDL3LINESTRIKE(dataframe)
    dataframe['CDLSPINNINGTOP'] = ta.CDLSPINNINGTOP(dataframe)  # values [0, -100, 100]
    dataframe['CDLENGULFING'] = ta.CDLENGULFING(dataframe)  # values [0, -100, 100]
    dataframe['CDLHARAMI'] = ta.CDLHARAMI(dataframe)  # values [0, -100, 100]
    dataframe['CDL3OUTSIDE'] = ta.CDL3OUTSIDE(dataframe)  # values [0, -100, 100]
    dataframe['CDL3INSIDE'] = ta.CDL3INSIDE(dataframe)  # values [0, -100, 100]

    heikinashi = qtpylib.heikinashi(dataframe)
    dataframe['ha_open'] = heikinashi['open']
    dataframe['ha_close'] = heikinashi['close']
    dataframe['ha_high'] = heikinashi['high']
    dataframe['ha_low'] = heikinashi['low']
    return dataframe


class Github_Bldnr94_FreqTrade__el__20240623_151326(IStrategy):
    INTERFACE_VERSION = 3
    can_short = True

    # Buy hyperspace params:
    buy_params = {
        "base_nb_candles_buy": 12,
        "ewo_high": 4.428,
        "ewo_low": -12.383,
        "low_offset": 0.915,
        "rsi_buy": 44,
    }

    # SGithub_Bldnr94_FreqTrade__el__20240623_151326l hyperspace params:
    sGithub_Bldnr94_FreqTrade__el__20240623_151326l_params = {
        "base_nb_candles_sGithub_Bldnr94_FreqTrade__el__20240623_151326l": 72,
        "high_offset": 1.008,
    }

    # ROI table:
    minimal_roi = {
        "0": 0.219,
        "24": 0.087,
        "67": 0.024,
        "164": 0
    }

    # Stoploss:
    stoploss = -0.242

    # Trailing stop:
    trailing_stop = True
    trailing_stop_positive = 0.103
    trailing_stop_positive_offset = 0.2
    trailing_only_offset_is_reached = True

    # Max Open Trades:
    max_open_trades = 9

    # SMAOffset
    base_nb_candles_buy = IntParameter(5, 80, default=buy_params['base_nb_candles_buy'], space='buy', optimize=True)
    base_nb_candles_sGithub_Bldnr94_FreqTrade__el__20240623_151326l = IntParameter(5, 80, default=sGithub_Bldnr94_FreqTrade__el__20240623_151326l_params['base_nb_candles_sGithub_Bldnr94_FreqTrade__el__20240623_151326l'], space='sGithub_Bldnr94_FreqTrade__el__20240623_151326l', optimize=True)
    low_offset = DecimalParameter(0.9, 0.99, default=buy_params['low_offset'], space='buy', optimize=True)
    high_offset = DecimalParameter(0.99, 1.1, default=sGithub_Bldnr94_FreqTrade__el__20240623_151326l_params['high_offset'], space='sGithub_Bldnr94_FreqTrade__el__20240623_151326l', optimize=True)

    # Protection
    fast_ewo = 50
    slow_ewo = 200
    ewo_low = DecimalParameter(-20.0, -8.0, default=buy_params['ewo_low'], space='buy', optimize=True)
    ewo_high = DecimalParameter(2.0, 12.0, default=buy_params['ewo_high'], space='buy', optimize=True)
    rsi_buy = IntParameter(30, 70, default=buy_params['rsi_buy'], space='buy', optimize=True)

    # Trailing stop:
    trailing_stop = True
    trailing_stop_positive = 0.005
    trailing_stop_positive_offset = 0.03
    trailing_only_offset_is_reached = True

    # SGithub_Bldnr94_FreqTrade__el__20240623_151326l signal
    use_exit_signal = True
    exit_profit_only = False
    exit_profit_offset = 0.01
    ignore_roi_if_entry_signal = True

    # Optimal timeframe for the strategy
    timeframe = '5m'
    informative_timeframe = '1h'
    process_only_new_candles = True
    startup_candle_count = 2000
    plot_config = {'main_plot': {'ma_buy': {'color': 'orange'}, 'ma_sGithub_Bldnr94_FreqTrade__el__20240623_151326l': {'color': 'orange'}}}
    use_custom_stoploss = False

    def informative_pairs(sGithub_Bldnr94_FreqTrade__el__20240623_151326f):
        pairs = sGithub_Bldnr94_FreqTrade__el__20240623_151326f.dp.current_whitGithub_Bldnr94_FreqTrade__el__20240623_151326ist()
        informative_pairs = [(pair, sGithub_Bldnr94_FreqTrade__el__20240623_151326f.informative_timeframe) for pair in pairs]
        return informative_pairs

    def get_informative_indicators(sGithub_Bldnr94_FreqTrade__el__20240623_151326f, metadata: dict):
        dataframe = sGithub_Bldnr94_FreqTrade__el__20240623_151326f.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=sGithub_Bldnr94_FreqTrade__el__20240623_151326f.informative_timeframe)
        return dataframe

    def populate_indicators(sGithub_Bldnr94_FreqTrade__el__20240623_151326f, dataframe: DataFrame, metadata: dict) -> DataFrame:
        new_columns = {}

        for val in sGithub_Bldnr94_FreqTrade__el__20240623_151326f.base_nb_candles_buy.range:
            new_columns[f'ma_buy_{val}'] = ta.EMA(dataframe, timeperiod=val)
        for val in sGithub_Bldnr94_FreqTrade__el__20240623_151326f.base_nb_candles_sGithub_Bldnr94_FreqTrade__el__20240623_151326l.range:
            new_columns[f'ma_sGithub_Bldnr94_FreqTrade__el__20240623_151326l_{val}'] = ta.EMA(dataframe, timeperiod=val)

        new_columns['EWO'] = EWO(dataframe, sGithub_Bldnr94_FreqTrade__el__20240623_151326f.fast_ewo, sGithub_Bldnr94_FreqTrade__el__20240623_151326f.slow_ewo)
        new_columns['rsi'] = ta.RSI(dataframe, timeperiod=14)

        dataframe = pd.concat([dataframe, pd.DataFrame(new_columns)], axis=1)
        return dataframe

    def populate_entry_trend(sGithub_Bldnr94_FreqTrade__el__20240623_151326f, dataframe: DataFrame, metadata: dict) -> DataFrame:
        buy_conditions = []
        buy_conditions.append(
            (dataframe['close'] < dataframe[f'ma_buy_{sGithub_Bldnr94_FreqTrade__el__20240623_151326f.base_nb_candles_buy.value}'] * sGithub_Bldnr94_FreqTrade__el__20240623_151326f.low_offset.value) & (
                        dataframe['EWO'] > sGithub_Bldnr94_FreqTrade__el__20240623_151326f.ewo_high.value) & (dataframe['rsi'] < sGithub_Bldnr94_FreqTrade__el__20240623_151326f.rsi_buy.value) & (
                        dataframe['volume'] > 0))
        buy_conditions.append(
            (dataframe['close'] < dataframe[f'ma_buy_{sGithub_Bldnr94_FreqTrade__el__20240623_151326f.base_nb_candles_buy.value}'] * sGithub_Bldnr94_FreqTrade__el__20240623_151326f.low_offset.value) & (
                        dataframe['EWO'] < sGithub_Bldnr94_FreqTrade__el__20240623_151326f.ewo_low.value) & (dataframe['volume'] > 0))
        if buy_conditions:
            dataframe.loc[reduce(lambda x, y: x | y, buy_conditions), 'enter_long'] = 1

        sGithub_Bldnr94_FreqTrade__el__20240623_151326l_conditions = []
        sGithub_Bldnr94_FreqTrade__el__20240623_151326l_conditions.append(
            (dataframe['close'] > dataframe[f'ma_sGithub_Bldnr94_FreqTrade__el__20240623_151326l_{sGithub_Bldnr94_FreqTrade__el__20240623_151326f.base_nb_candles_sGithub_Bldnr94_FreqTrade__el__20240623_151326l.value}'] * sGithub_Bldnr94_FreqTrade__el__20240623_151326f.high_offset.value) & (
                        dataframe['volume'] > 0))
        if sGithub_Bldnr94_FreqTrade__el__20240623_151326l_conditions:
            dataframe.loc[reduce(lambda x, y: x | y, sGithub_Bldnr94_FreqTrade__el__20240623_151326l_conditions), 'enter_short'] = 1

        return dataframe

    def populate_exit_trend(sGithub_Bldnr94_FreqTrade__el__20240623_151326f, dataframe: DataFrame, metadata: dict) -> DataFrame:
        exit_long_conditions = []
        exit_long_conditions.append(
            (dataframe['close'] > dataframe[f'ma_sGithub_Bldnr94_FreqTrade__el__20240623_151326l_{sGithub_Bldnr94_FreqTrade__el__20240623_151326f.base_nb_candles_sGithub_Bldnr94_FreqTrade__el__20240623_151326l.value}'] * sGithub_Bldnr94_FreqTrade__el__20240623_151326f.high_offset.value) & (
                        dataframe['volume'] > 0))
        if exit_long_conditions:
            dataframe.loc[reduce(lambda x, y: x | y, exit_long_conditions), 'exit_long'] = 1

        exit_short_conditions = []
        exit_short_conditions.append(
            (dataframe['close'] < dataframe[f'ma_buy_{sGithub_Bldnr94_FreqTrade__el__20240623_151326f.base_nb_candles_buy.value}'] * sGithub_Bldnr94_FreqTrade__el__20240623_151326f.low_offset.value) & (
                        dataframe['EWO'] > sGithub_Bldnr94_FreqTrade__el__20240623_151326f.ewo_high.value) & (dataframe['rsi'] < sGithub_Bldnr94_FreqTrade__el__20240623_151326f.rsi_buy.value) & (
                        dataframe['volume'] > 0))
        exit_short_conditions.append(
            (dataframe['close'] < dataframe[f'ma_buy_{sGithub_Bldnr94_FreqTrade__el__20240623_151326f.base_nb_candles_buy.value}'] * sGithub_Bldnr94_FreqTrade__el__20240623_151326f.low_offset.value) & (
                        dataframe['EWO'] < sGithub_Bldnr94_FreqTrade__el__20240623_151326f.ewo_low.value) & (dataframe['volume'] > 0))
        if exit_short_conditions:
            dataframe.loc[reduce(lambda x, y: x | y, exit_short_conditions), 'exit_short'] = 1

            return dataframe

    def leverage(sGithub_Bldnr94_FreqTrade__el__20240623_151326f, pair: str, current_time: datetime, current_rate: float, proposed_leverage: float,
                 max_leverage: float, entry_tag: str, side: str, **kwargs) -> float:
        """
        Customize leverage for each new trade. This method is only called in futures mode.

        :param pair: Pair that's currently analyzed
        :param current_time: datetime object, containing the current datetime
        :param current_rate: Rate, calculated based on pricing settings in exit_pricing.
        :param proposed_leverage: A leverage proposed by the bot.
        :param max_leverage: Max leverage allowed on this pair
        :param entry_tag: Optional entry_tag (buy_tag) if provided with the buy signal.
        :param side: 'long' or 'short' - indicating the direction of the proposed trade
        :return: A leverage amount, which is between 1.0 and max_leverage.
        """
        return 10.0
