# source: https://raw.githubusercontent.com/devsmitra/trading/bf4f22e69aa9ff5749ff504ee48c0665aef6a7a7/user_data/strategies/Candlestick.py
# --- Do not remove these libs ---
from datetime import datetime
from typing import Any, Optional
from freqtrade.strategy import IStrategy, stoploss_from_absolute
from pandas import DataFrame
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
from freqtrade.persistence import Trade

from support import identify_df_trends

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


class github_devsmitra_trading__Candlestick__20220828_142346(IStrategy):
    cache: Any = {}

    INTERFACE_VERSION: int = 3
    process_only_new_candles: bool = False
    # Optimal timeframe for the strategy
    timeframe = '15m'

    minimal_roi = {
        "0": 1
    }

    # Optimal stoploss designed for the strategy
    stoploss = -0.05
    use_custom_stoploss = True

    # @informative('5m')
    # def populate_indicators_1h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
    #     dataframe['adx'] = ta.ADX(dataframe, timeperiod=14)
    #     self.get_trend(dataframe, metadata)
    #     return dataframe

    def custom_stoploss(self, pair: str, trade: Trade, current_time: datetime,
                        current_rate: float, current_profit: float, **kwargs) -> float:
        def get_stoploss(atr):
            dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
            candle = dataframe.iloc[-1].squeeze()   
            return stoploss_from_absolute(current_rate - (candle['atr'] * atr), current_rate, is_short=trade.is_short) * -1
        if current_profit > 0.075:
            return get_stoploss(1)
        if current_profit > 0.05:
            return get_stoploss(2)
        return get_stoploss(6)

    def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
                            proposed_stake: float, min_stake: Optional[float], max_stake: float,
                            leverage: float, entry_tag: Optional[str], side: str,
                            **kwargs) -> float:
        if self.wallets is None:
            return proposed_stake
        return self.wallets.get_total_stake_amount() * .06

    def get_trend(self, dataframe: DataFrame, metadata: dict):
        pair = metadata['pair']
        prev = self.cache.get(pair,  {'date': dataframe.iloc[-2]['date'], 'Trend': 0})
        date = dataframe.iloc[-1]['date']
        if (date != prev['date']):
            df = identify_df_trends(dataframe, 'close', window_size=5)
            self.cache[pair] = {'date': date, 'Trend': df['Trend']}
        else:
            dataframe['Trend'] = prev['Trend']

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        self.get_trend(dataframe, metadata)
        dataframe['adx'] = ta.ADX(dataframe, timeperiod=14)
        dataframe['atr'] = ta.ATR(dataframe)
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        crossed = False
        for i in range(0, 2):
            crossed = crossed | (
                qtpylib.crossed_above(dataframe.shift(i)['Trend'], 0) &
                (dataframe.shift(i)['adx'] > 20)
            )

        dataframe.loc[
            crossed,
            'enter_long'
        ] = 1
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                (qtpylib.crossed_below(dataframe['adx'], 25) & (dataframe['Trend'] == -1)) |
                (qtpylib.crossed_below(dataframe['Trend'], 0) & (dataframe['adx'] < 25)) |
                (qtpylib.crossed_below(dataframe.shift()['Trend'], 0) & (dataframe['adx'] < 25))
            ),
            'exit_long'] = 1
        return dataframe

    def confirm_trade_exit(self, pair: str, trade: Trade, order_type: str, amount: float,
                           rate: float, time_in_force: str, exit_reason: str,
                           current_time: datetime, **kwargs) -> bool:
        profit = trade.calc_profit_ratio(rate)
        if (((exit_reason == 'force_exit') | (exit_reason == 'exit_signal')) and (profit < 0)):
            return False
        return True
