# source: https://raw.githubusercontent.com/rmallarapu-bc/brahma/9287745fc036c2f4c00c586e598290885c2883b9/archive/Vashishta.py
# --- Do not remove these libs ---
from typing import Optional

from pandas import DataFrame
import talib.abstract as tal
import freqtrade.vendor.qtpylib.indicators as qtpylib
from datetime import datetime
from freqtrade.persistence import Trade
from freqtrade.strategy import DecimalParameter, IntParameter, IStrategy, merge_informative_pair
from functools import reduce
import logging
import warnings
import pandas as pd

log = logging.getLogger(__name__)
log.setLevel(logging.INFO)
warnings.simplefilter(action='ignore', category=pd.errors.PerformanceWarning)


import pandas_ta as ta
import pandas as pd
import numpy as np


def guppy(df):
    """
    Uses a dataframe of at least 70 rows and a columned name 'close' as input
    Returns trend prediction based on Super Guppy
    """

    if type(df) != pd.DataFrame:
        if type(df) == list:
            df = pd.DataFrame(df, columns=["close"])
        elif type(df) == np.ndarray:
            df = pd.DataFrame(data=df, columns=["close"])
        else:
            #print(f"Your input type is not supported: {type(df)}")

    # Make the fast and slow EMAs
    guppies = [{"kind": "ema", "length": f} for f in list(range(3, 25, 2))]
    guppies += [{"kind": "ema", "length": s} for s in list(range(25, 73, 3))]

    # Create your own Custom Strategy
    super_guppy = ta.Strategy(
        name="Super Guppy",
        description="7 Fast EMAs, 16 slow EMAs",
        ta=guppies
    )

    # Run the strategy over close prices
    df.ta.strategy(super_guppy, close="close")

    # Remove all NaN rows, which are the first 70 rows
    df = df.dropna()

    # To ignore the warning
    df = df.copy()

    df['colfastL'] = np.where((df["EMA_3"] > df["EMA_5"]) &
                              (df["EMA_5"] > df["EMA_7"]) &
                              (df["EMA_7"] > df["EMA_9"]) &
                              (df["EMA_9"] > df["EMA_11"]) &
                              (df["EMA_11"] > df["EMA_13"]) &
                              (df["EMA_13"] > df["EMA_15"]) &
                              (df["EMA_15"] > df["EMA_17"]) &
                              (df["EMA_17"] > df["EMA_19"]) &
                              (df["EMA_19"] > df["EMA_21"]) &
                              (df["EMA_21"] > df["EMA_23"]), True, False)

    df['colfastS'] = np.where((df["EMA_3"] < df["EMA_5"]) &
                              (df["EMA_5"] < df["EMA_7"]) &
                              (df["EMA_7"] < df["EMA_9"]) &
                              (df["EMA_9"] < df["EMA_11"]) &
                              (df["EMA_11"] < df["EMA_13"]) &
                              (df["EMA_13"] < df["EMA_15"]) &
                              (df["EMA_15"] < df["EMA_17"]) &
                              (df["EMA_17"] < df["EMA_19"]) &
                              (df["EMA_19"] < df["EMA_21"]) &
                              (df["EMA_21"] < df["EMA_23"]), True, False)

    df["colslowL"] = np.where((df["EMA_25"] > df["EMA_28"]) &
                              (df["EMA_28"] > df["EMA_31"]) &
                              (df["EMA_31"] > df["EMA_34"]) &
                              (df["EMA_34"] > df["EMA_37"]) &
                              (df["EMA_37"] > df["EMA_40"]) &
                              (df["EMA_40"] > df["EMA_43"]) &
                              (df["EMA_43"] > df["EMA_46"]) &
                              (df["EMA_46"] > df["EMA_49"]) &
                              (df["EMA_49"] > df["EMA_52"]) &
                              (df["EMA_52"] > df["EMA_55"]) &
                              (df["EMA_55"] > df["EMA_58"]) &
                              (df["EMA_58"] > df["EMA_61"]) &
                              (df["EMA_61"] > df["EMA_64"]) &
                              (df["EMA_64"] > df["EMA_67"]) &
                              (df["EMA_67"] > df["EMA_70"]), True, False)

    df["colslowS"] = np.where((df["EMA_25"] < df["EMA_28"]) &
                              (df["EMA_28"] < df["EMA_31"]) &
                              (df["EMA_31"] < df["EMA_34"]) &
                              (df["EMA_34"] < df["EMA_37"]) &
                              (df["EMA_37"] < df["EMA_40"]) &
                              (df["EMA_40"] < df["EMA_43"]) &
                              (df["EMA_43"] < df["EMA_46"]) &
                              (df["EMA_46"] < df["EMA_49"]) &
                              (df["EMA_49"] < df["EMA_52"]) &
                              (df["EMA_52"] < df["EMA_55"]) &
                              (df["EMA_55"] < df["EMA_58"]) &
                              (df["EMA_58"] < df["EMA_61"]) &
                              (df["EMA_61"] < df["EMA_64"]) &
                              (df["EMA_64"] < df["EMA_67"]) &
                              (df["EMA_67"] < df["EMA_70"]), True, False)

    # Fast EMA color rules
    df["colFinal"] = np.where((df["colfastL"] == True) & (df["EMA_25"] > df["EMA_70"]), "aqua", "gray")  # Aqua = Buy
    df["colFinal"] = np.where((df["colslowL"] == True) & (df["EMA_25"] < df["EMA_70"]), "blue",
                              df["colFinal"])  # Blue = Sell

    df["colFinal2"] = np.where((df["colfastL"] == True), "lime", "gray")  # Lime = Buy
    df["colFinal2"] = np.where((df["colslowS"] == True), "red", "gray")  # Red = Sell

    # Custom buy signals, 1 = Buy, 0 = Hold, -1 = Sell
    df["guppy"] = np.where((df["colFinal"] == "aqua") | (df["colFinal2"] == "lime"), 1, 0)  # Aqua = Buy
    df["guppy"] = np.where((df["colFinal"] == "blue") | (df["colFinal2"] == "red"), -1, df["guppy"])
    df["guppy"] = np.where((df["colFinal"] == "gray") & (df["colFinal2"] == "gray"), 0, df["guppy"])

    return df


class Github_rmallarapu_bc_brahma__Vashishta__20240229_213751(IStrategy):
    INTERFACE_VERSION: int = 3
    minimal_roi = {"0": 0.5}

    can_short = True

    # Exit criteria
    use_exit_signal = False
    exit_profit_only = False
    ignore_roi_if_entry_signal = True

    # Trailing stoploss
    trailing_stop = True
    trailing_stop_positive = 0.001
    trailing_stop_positive_offset = 0.01
    trailing_only_offset_is_reached = True

    stoploss = -0.1
    timeframe = '1d'
    informative_timeframe = '1w'

    position_adjustment_enable = True
    max_entry_position_adjustment = 10

    # Strategy parameters
    rsi_length = IntParameter(10, 40, default=14, space="buy")
    bb_window = IntParameter(10, 40, default=17, space="buy")
    bb_std = IntParameter(1, 6, default=1, space="buy")
    buy_rsi = IntParameter(10, 40, default=37, space="buy")
    sell_rsi = IntParameter(60, 90, default=76, space="sell")

    # timeframe = '5m'

    buy_params = {"buy_limit": 0.943}
    buy_limit = DecimalParameter(0.90, 0.98, default=0.98, space='buy', decimals=3, optimize=True, load=True)

    process_only_new_candles = False
    startup_candle_count = 10
    use_custom_stoploss = False

    def informative_pairs(self):
        pairs = self.dp.current_whitelist()
        informative_pairs = [(pair, self.informative_timeframe) for pair in pairs]
        return informative_pairs

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        pairs = self.dp.current_whitelist()[0]  # Take the first pair
        informative = self.dp.get_pair_dataframe(pair=pairs, timeframe=self.informative_timeframe)
        # calculate SMA20 on informative pair
        informative['sma20'] = informative['close'].rolling(20).mean()

        # Combine the 2 dataframe
        # This will result in a column named 'closeETH' or 'closeBTC' - depending on stake_currency.
        dataframe['rsi'] = tal.RSI(dataframe, timeperiod=self.rsi_length.value)

        # TEMA - Triple Exponential Moving Average
        dataframe["tema"] = tal.TEMA(dataframe, timeperiod=9)

        # Bollinger bands
        bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=self.bb_window.value,
                                            stds=self.bb_std.value)
        dataframe['bb_lowerband'] = bollinger['lower']
        dataframe['bb_middleband'] = bollinger['mid']
        dataframe['bb_upperband'] = bollinger['upper']

        dataframe['ema20'] = tal.EMA(dataframe, timeperiod=20)
        dataframe['ema50'] = tal.EMA(dataframe, timeperiod=50)
        dataframe['ema100'] = tal.EMA(dataframe, timeperiod=100)

        dataframe = merge_informative_pair(dataframe, informative,
                                           self.timeframe, self.informative_timeframe, ffill=True)

        dataframe = guppy(dataframe)
        return dataframe

    # def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
    #     dataframe = guppy(dataframe)
    #     return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                    # (dataframe['ema20'] > dataframe['ema50']) &
                    # # (dataframe['close_15m'] > dataframe['sma20_15m']) &
                    # (dataframe['close_1h'] > dataframe['sma20_1h']) &
                    # (dataframe['rsi'] < self.buy_rsi.value) &
                    # (dataframe['close'] < dataframe['bb_lowerband']) &
                    (dataframe["guppy"] == 1)
            ),
            'enter_long'] = 1
        dataframe.loc[
            (
                    # (dataframe['ema20'] > dataframe['ema50']) &
                    # # (dataframe['close_15m'] > dataframe['sma20_15m']) &
                    # (dataframe['close_1h'] > dataframe['sma20_1h']) &
                    # (dataframe['rsi'] < self.buy_rsi.value) &
                    # (dataframe['close'] < dataframe['bb_lowerband']) &
                    (dataframe["guppy"] == -1)
            ),
            'enter_short'] = 1

        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                (dataframe["guppy"] == -1)
            ),
            'exit_long'] = 1
        dataframe.loc[
            (
                (dataframe["guppy"] == 1)
            ),
            'exit_short'] = 1

        return dataframe
