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 NormalizerStrategyHO2(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