# source: https://raw.githubusercontent.com/DerSalvador/freqtrade-helm-chart/a669dc11b640b0eb63aa8f8b51e9f181fd7ee43c/chart/deployed_strategies/binance-michael-k8s-namespace/NormalizerStrategyHO2.py
import freqtrade.vendor.qtpylib.indicators as qtpylib
import numpy as np
import talib.abstract as ta
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
from datetime import datetime, timedelta
'\n=============== SUMMARY METRICS ===============\n| Metric                | Value               |\n|-----------------------+---------------------|\n| Backtesting from      | 2021-05-01 00:00:00 |\n| Backtesting to        | 2021-06-09 17:00:00 |\n| Max open trades       | 10                  |\n|                       |                     |\n| Total trades          | 447                 |\n| Starting balance      | 1000.000 USDT       |\n| Final balance         | 1714.575 USDT       |\n| Absolute profit       | 714.575 USDT        |\n| Total profit %        | 71.46%              |\n| Trades per day        | 11.46               |\n| Avg. stake amount     | 180.278 USDT        |\n| Total trade volume    | 80584.326 USDT      |\n|                       |                     |\n| Best Pair             | ALICE/USDT 24.7%    |\n| Worst Pair            | HARD/USDT -35.15%   |\n| Best trade            | PSG/USDT 17.98%     |\n| Worst trade           | XVS/USDT -26.03%    |\n| Best day              | 351.588 USDT        |\n| Worst day             | -256.636 USDT       |\n| Days win/draw/lose    | 25 / 8 / 4          |\n| Avg. Duration Winners | 1:36:00             |\n| Avg. Duration Loser   | 9:33:00             |\n|                       |                     |\n| Min balance           | 962.929 USDT        |\n| Max balance           | 1714.575 USDT       |\n| Drawdown              | 240.78%             |\n| Drawdown              | 289.267 USDT        |\n| Drawdown high         | 252.196 USDT        |\n| Drawdown low          | -37.071 USDT        |\n| Drawdown Start        | 2021-05-19 03:00:00 |\n| Drawdown End          | 2021-05-19 20:00:00 |\n| Market change         | -34.99%             |\n===============================================\n\n'

class Github_DerSalvador_freqtrade_helm_chart__NormalizerStrategyHO2__20260115_122204(IStrategy):
    INTERFACE_VERSION = 3
    minimal_roi = {'0': 0.35, '405': 0.248, '875': 0.091, '1585': 0}
    stoploss = -0.99  # effectively disabled.
    timeframe = '1h'
    # Sell signal
    use_exit_signal = True
    exit_profit_only = True
    exit_profit_offset = 0.001  # it doesn't meant anything, just to guarantee there is a minimal profit.
    ignore_roi_if_entry_signal = True
    # Trailing stop:
    trailing_stop = True
    trailing_stop_positive = 0.3
    trailing_stop_positive_offset = 0.379
    trailing_only_offset_is_reached = False
    # Custom stoploss
    use_custom_stoploss = True
    # Run "populate_indicators()" only for new candle.
    process_only_new_candles = False
    # Number of candles the strategy requires before producing valid signals
    startup_candle_count: int = 610
    # Optional order type mapping.
    order_types = {'entry': 'limit', 'exit': 'limit', 'stoploss': 'market', 'stoploss_on_exchange': False}

    def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, current_rate: float, current_profit: float, **kwargs) -> float:
        # Manage losing trades and open room for better ones.
        if (current_profit < 0) & (current_time - timedelta(minutes=300) > trade.open_date_utc):
            return 0.01
        return 0.99

    def fischer_norm(self, x, lookback):
        res = np.zeros_like(x)
        for i in range(lookback, len(x)):
            x_min = np.min(x[i - lookback:i + 1])
            x_max = np.max(x[i - lookback:i + 1])
            #res[i] = (2*(x[i] - x_min) / (x_max - x_min)) - 1
            res[i] = (x[i] - x_min) / (x_max - x_min)
        return res

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        lookback = [13, 21, 34, 55, 89, 144, 233, 377, 610]
        for look in lookback:
            dataframe[f'norm_{look}'] = self.fischer_norm(dataframe['close'].values, look)
        collist = [col for col in dataframe.columns if col.startswith('norm')]
        dataframe['pct_sum'] = dataframe[collist].sum(axis=1)
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:  # Make sure Volume is not 0
        dataframe.loc[(dataframe['pct_sum'] < 0.2) & (dataframe['volume'] > 0), 'entry'] = 1
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:  # Make sure Volume is not 0
        dataframe.loc[(dataframe['pct_sum'] > 8) & (dataframe['volume'] > 0), 'exit'] = 1
        return dataframe