# source: https://raw.githubusercontent.com/HuynhLeVu5598/tradingAI/816bb3e09414081bae29b6b10c313644c4cf3da4/user_data/strategies/MyStrategy3.py

# --- Do not remove these libs ---
from freqtrade.strategy import IStrategy
from typing import Dict, List
from functools import reduce
from pandas import DataFrame
# --------------------------------

import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
import numpy # noqa


class github_HuynhLeVu5598_tradingAI__MyStrategy3__20230412_094018(IStrategy):
    """
    Strategy 001
    author@: Gerald Lonlas
    github@: https://github.com/freqtrade/freqtrade-strategies

    How to use it?
    > python3 ./freqtrade/main.py -s Strategy001
    """

    INTERFACE_VERSION: int = 3
    # Minimal ROI designed for the strategy.
    # This attribute will be overridden if the config file contains "minimal_roi"
    # minimal_roi = {
    #     "60":  0.01,
    #     "30":  0.03,
    #     "20":  0.04,
    #     "0":  0.05
    # }

    # Optimal stoploss designed for the strategy
    # This attribute will be overridden if the config file contains "stoploss"
    stoploss = -0.10

    # Optimal timeframe for the strategy
    timeframe = '5m'

    # https://www.freqtrade.io/en/latest/stoploss/#trailing-stop-loss-custom-positive-loss
    # trailing stoploss
    trailing_stop = True
    trailing_stop_positive = 0.035
    trailing_stop_positive_offset = 0.036
    trailing_only_offset_is_reached = True

    # run "populate_indicators" only for new candle
    process_only_new_candles = False

    # Experimental settings (configuration will overide these if set)
    # Cho phép xác định tín hiệu thoát tùy chỉnh, cho biết nên bán vị trí đã chỉ định. Điều này rất hữu ích khi chúng ta cần tùy chỉnh các điều kiện thoát cho từng giao dịch riêng lẻ hoặc nếu bạn cần dữ liệu giao dịch để đưa ra quyết định thoát.
    use_exit_signal = True
    # cho phép bạn thoát khỏi một lệnh giao dịch chỉ khi lợi nhuận đạt được một mức độ cụ thể. Nếu giá trị này được đặt thành True, robot chỉ thoát khỏi vị thế giao dịch nếu lợi nhuận đã đạt được trước đó được xác định. Nếu giá trị này là False, robot sẽ đóng vị thế giao dịch với lợi nhuận bất kỳ.
    exit_profit_only = True
    # Không thoát nếu tín hiệu vào vẫn còn hoạt động. Cài đặt này ưu tiên hơn minimum_roi và use_exit_signa
    ignore_roi_if_entry_signal = False

    # Optional order type mapping
    order_types = {
        # "limit" là một kiểu đặt lệnh trong giao dịch tài chính, được sử dụng để chỉ định giá mua hoặc giá bán tối đa mà người dùng sẽ chấp nhận thực hiện giao dịch. Nếu giá thị trường đạt đến hoặc vượt qua giá giới hạn này, lệnh sẽ được kích hoạt và giao dịch sẽ được thực hiện.
        'entry': 'limit',
        'exit': 'limit',
        # lệnh 'market', tức là bán ra ngay lập tức với giá thị trường khi giá của tài sản đạt đến mức stop-loss
        'stoploss': 'market',
        # trạng thái của lệnh stop-loss trên sàn giao dịch (True nếu sử dụng lệnh stop-loss trên sàn giao dịch, False nếu sử dụng lệnh stop-loss trong phần mềm Freqtrade).
        'stoploss_on_exchange': False
    }



    # Hàm informative_pairs() được sử dụng để định nghĩa các cặp đôi/thời gian bổ sung, không thể giao dịch trên sàn, trừ khi chúng được liệt kê trong danh sách trắng (whitelist). Các cặp đôi/thời gian này sẽ được lưu trữ trong bộ nhớ đệm của bot. Hàm trả về một danh sách các bộ giá trị tuple trong định dạng (pair, interval). Ví dụ: [("ETH/USDT", "5m"), ("BTC/USDT", "15m")].
    def informative_pairs(self):

        return []

    # Hàm populate_indicators được dùng để thêm một số chỉ báo kỹ thuật khác nhau vào DataFrame đã cho
    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:

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

        heikinashi = qtpylib.heikinashi(dataframe)
        dataframe['ha_open'] = heikinashi['open']
        dataframe['ha_close'] = heikinashi['close']

        # RSI
        dataframe['rsi'] = ta.RSI(dataframe)

        # Inverse Fisher transform on RSI, values [-1.0, 1.0] (https://goo.gl/2JGGoy)
        rsi = 0.1 * (dataframe['rsi'] - 50)
        dataframe['fisher_rsi'] = (numpy.exp(2 * rsi) - 1) / (numpy.exp(2 * rsi) + 1)

        # Bollinger bands
        bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
        dataframe['bb_lowerband'] = bollinger['lower']

        # Hammer: values [0, 100]
        dataframe['CDLHAMMER'] = ta.CDLHAMMER(dataframe)

        # MACD
        macd = ta.MACD(dataframe)
        dataframe['macd'] = macd['macd']
        dataframe['macdsignal'] = macd['macdsignal']
        dataframe['mean-volume'] = dataframe['volume'].rolling(12).mean()

        return dataframe

    # Hàm populate_entry_trend trong Python dùng để tính toán tín hiệu mua (buy signal) dựa trên các chỉ báo kỹ thuật (TA indicators) và trả về một DataFrame mới chứa cột enter_long cho biết tín hiệu mua.
    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                qtpylib.crossed_above(dataframe['ema20'], dataframe['ema50']) &
                (dataframe['ha_close'] > dataframe['ema20']) &
                (dataframe['ha_open'] < dataframe['ha_close']) &
                (dataframe['rsi'] < 30) &
                (dataframe['rsi'] > 0) &
                (dataframe['bb_lowerband'] > dataframe['close']) &
                (dataframe['CDLHAMMER'] == 100) &
                (dataframe['fisher_rsi'] < -0.94) &
                (dataframe['macd'] > 0) &
                (dataframe['macd'] > dataframe['macdsignal']) &
                (dataframe['mean-volume'] > 0.75) 
            ),
            'enter_long'] = 1        
        
        last_enter_long = dataframe.iloc[-1]['enter_long']

        if last_enter_long == 1:
            #print("dataframe: ",dataframe)

        return dataframe


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

        return dataframe
