From a8b1dcf3c8b5d8fde4e0ea7c7f0ea22d1b189092 Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Tue, 19 May 2020 22:20:53 +0300 Subject: [PATCH 1/3] Minor: cleanup in get_signal() --- freqtrade/strategy/interface.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index 8031c7932..ad11fe33a 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -310,7 +310,6 @@ class IStrategy(ABC): logger.warning('Empty candle (OHLCV) data for pair %s', pair) return False, False - latest_date = dataframe['date'].max() try: df_len, df_close, df_date = self.preserve_df(dataframe) dataframe = strategy_safe_wrapper( @@ -326,17 +325,17 @@ class IStrategy(ABC): logger.warning('Empty dataframe for pair %s', pair) return False, False + latest_date = dataframe['date'].max() latest = dataframe.loc[dataframe['date'] == latest_date].iloc[-1] # Check if dataframe is out of date - signal_date = arrow.get(latest['date']) interval_minutes = timeframe_to_minutes(interval) offset = self.config.get('exchange', {}).get('outdated_offset', 5) - if signal_date < (arrow.utcnow().shift(minutes=-(interval_minutes * 2 + offset))): + if latest_date < (arrow.utcnow().shift(minutes=-(interval_minutes * 2 + offset))): logger.warning( 'Outdated history for pair %s. Last tick is %s minutes old', pair, - (arrow.utcnow() - signal_date).seconds // 60 + (arrow.utcnow() - latest_date).seconds // 60 ) return False, False From e96e28df074e333d4b0df5d7b4a267d69f41bb8f Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Tue, 19 May 2020 23:13:51 +0300 Subject: [PATCH 2/3] Refactor verify_blacklist() --- freqtrade/pairlist/IPairList.py | 31 +++------------------------ freqtrade/pairlist/VolumePairList.py | 2 +- freqtrade/pairlist/pairlistmanager.py | 20 ++++++++++++++++- 3 files changed, 23 insertions(+), 30 deletions(-) diff --git a/freqtrade/pairlist/IPairList.py b/freqtrade/pairlist/IPairList.py index d0ac30df1..4afbe1c72 100644 --- a/freqtrade/pairlist/IPairList.py +++ b/freqtrade/pairlist/IPairList.py @@ -3,7 +3,6 @@ PairList Handler base class """ import logging from abc import ABC, abstractmethod, abstractproperty -from copy import deepcopy from typing import Any, Dict, List from cachetools import TTLCache, cached @@ -87,38 +86,14 @@ class IPairList(ABC): :return: new whitelist """ - @staticmethod - def verify_blacklist(pairlist: List[str], blacklist: List[str], - aswarning: bool) -> List[str]: - """ - Verify and remove items from pairlist - returning a filtered pairlist. - Logs a warning or info depending on `aswarning`. - Pairlist Handlers explicitly using this method shall use `aswarning=False`! - :param pairlist: Pairlist to validate - :param blacklist: Blacklist to validate pairlist against - :param aswarning: Log message as Warning or Info - :return: pairlist - blacklisted pairs - """ - for pair in deepcopy(pairlist): - if pair in blacklist: - if aswarning: - logger.warning(f"Pair {pair} in your blacklist. Removing it from whitelist...") - else: - logger.info(f"Pair {pair} in your blacklist. Removing it from whitelist...") - pairlist.remove(pair) - return pairlist - - def _verify_blacklist(self, pairlist: List[str], aswarning: bool = True) -> List[str]: + def verify_blacklist(self, pairlist: List[str]) -> List[str]: """ Proxy method to verify_blacklist for easy access for child classes. - Logs a warning or info depending on `aswarning`. - Pairlists explicitly using this method shall use aswarning=False! + Uses `aswarning=False`, as it should be for Pairlist Handlers. :param pairlist: Pairlist to validate - :param aswarning: Log message as Warning or info. :return: pairlist - blacklisted pairs """ - return IPairList.verify_blacklist(pairlist, self._pairlistmanager.blacklist, - aswarning=aswarning) + return self._pairlistmanager.verify_blacklist(pairlist, aswarning=False) def _whitelist_for_active_markets(self, pairlist: List[str]) -> List[str]: """ diff --git a/freqtrade/pairlist/VolumePairList.py b/freqtrade/pairlist/VolumePairList.py index 981e9915e..b254921cf 100644 --- a/freqtrade/pairlist/VolumePairList.py +++ b/freqtrade/pairlist/VolumePairList.py @@ -115,7 +115,7 @@ class VolumePairList(IPairList): # Validate whitelist to only have active market pairs pairs = self._whitelist_for_active_markets([s['symbol'] for s in sorted_tickers]) - pairs = self._verify_blacklist(pairs, aswarning=False) + pairs = self.verify_blacklist(pairs) # Limit pairlist to the requested number of pairs pairs = pairs[:self._number_pairs] diff --git a/freqtrade/pairlist/pairlistmanager.py b/freqtrade/pairlist/pairlistmanager.py index 0cf283cca..a953a586f 100644 --- a/freqtrade/pairlist/pairlistmanager.py +++ b/freqtrade/pairlist/pairlistmanager.py @@ -93,7 +93,7 @@ class PairListManager(): # Validation against blacklist happens after the chain of Pairlist Handlers # to ensure blacklist is respected. - pairlist = IPairList.verify_blacklist(pairlist, self.blacklist, True) + pairlist = self.verify_blacklist(pairlist, True) self._whitelist = pairlist @@ -110,6 +110,24 @@ class PairListManager(): return pairlist + def verify_blacklist(self, pairlist: List[str], aswarning: bool) -> List[str]: + """ + Verify and remove items from pairlist - returning a filtered pairlist. + Logs a warning or info depending on `aswarning`. + Pairlist Handlers explicitly using this method shall use `aswarning=False`! + :param pairlist: Pairlist to validate + :param aswarning: Log message as Warning or Info + :return: pairlist - blacklisted pairs + """ + for pair in deepcopy(pairlist): + if pair in self._blacklist: + if aswarning: + logger.warning(f"Pair {pair} in your blacklist. Removing it from whitelist...") + else: + logger.info(f"Pair {pair} in your blacklist. Removing it from whitelist...") + pairlist.remove(pair) + return pairlist + def create_pair_list(self, pairs: List[str], timeframe: str = None) -> ListPairsWithTimeframes: """ Create list of pair tuples with (pair, ticker_interval) From 696c7e87f24dad77df7820cdaa1e88a3768e468f Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Tue, 19 May 2020 23:51:39 +0300 Subject: [PATCH 3/3] Use proper logging (using the Filter's logger) --- freqtrade/pairlist/IPairList.py | 6 +++--- freqtrade/pairlist/VolumePairList.py | 2 +- freqtrade/pairlist/pairlistmanager.py | 14 ++++++-------- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/freqtrade/pairlist/IPairList.py b/freqtrade/pairlist/IPairList.py index 4afbe1c72..bd8e843e6 100644 --- a/freqtrade/pairlist/IPairList.py +++ b/freqtrade/pairlist/IPairList.py @@ -86,14 +86,14 @@ class IPairList(ABC): :return: new whitelist """ - def verify_blacklist(self, pairlist: List[str]) -> List[str]: + def verify_blacklist(self, pairlist: List[str], logmethod) -> List[str]: """ Proxy method to verify_blacklist for easy access for child classes. - Uses `aswarning=False`, as it should be for Pairlist Handlers. :param pairlist: Pairlist to validate + :param logmethod: Function that'll be called, `logger.info` or `logger.warning`. :return: pairlist - blacklisted pairs """ - return self._pairlistmanager.verify_blacklist(pairlist, aswarning=False) + return self._pairlistmanager.verify_blacklist(pairlist, logmethod) def _whitelist_for_active_markets(self, pairlist: List[str]) -> List[str]: """ diff --git a/freqtrade/pairlist/VolumePairList.py b/freqtrade/pairlist/VolumePairList.py index b254921cf..b792ab037 100644 --- a/freqtrade/pairlist/VolumePairList.py +++ b/freqtrade/pairlist/VolumePairList.py @@ -115,7 +115,7 @@ class VolumePairList(IPairList): # Validate whitelist to only have active market pairs pairs = self._whitelist_for_active_markets([s['symbol'] for s in sorted_tickers]) - pairs = self.verify_blacklist(pairs) + pairs = self.verify_blacklist(pairs, logger.info) # Limit pairlist to the requested number of pairs pairs = pairs[:self._number_pairs] diff --git a/freqtrade/pairlist/pairlistmanager.py b/freqtrade/pairlist/pairlistmanager.py index a953a586f..6ad6c610b 100644 --- a/freqtrade/pairlist/pairlistmanager.py +++ b/freqtrade/pairlist/pairlistmanager.py @@ -93,7 +93,7 @@ class PairListManager(): # Validation against blacklist happens after the chain of Pairlist Handlers # to ensure blacklist is respected. - pairlist = self.verify_blacklist(pairlist, True) + pairlist = self.verify_blacklist(pairlist, logger.warning) self._whitelist = pairlist @@ -110,21 +110,19 @@ class PairListManager(): return pairlist - def verify_blacklist(self, pairlist: List[str], aswarning: bool) -> List[str]: + def verify_blacklist(self, pairlist: List[str], logmethod) -> List[str]: """ Verify and remove items from pairlist - returning a filtered pairlist. Logs a warning or info depending on `aswarning`. - Pairlist Handlers explicitly using this method shall use `aswarning=False`! + Pairlist Handlers explicitly using this method shall use + `logmethod=logger.info` to avoid spamming with warning messages :param pairlist: Pairlist to validate - :param aswarning: Log message as Warning or Info + :param logmethod: Function that'll be called, `logger.info` or `logger.warning`. :return: pairlist - blacklisted pairs """ for pair in deepcopy(pairlist): if pair in self._blacklist: - if aswarning: - logger.warning(f"Pair {pair} in your blacklist. Removing it from whitelist...") - else: - logger.info(f"Pair {pair} in your blacklist. Removing it from whitelist...") + logmethod(f"Pair {pair} in your blacklist. Removing it from whitelist...") pairlist.remove(pair) return pairlist