diff --git a/freqtrade/pairlist/AgeFilter.py b/freqtrade/pairlist/AgeFilter.py index ae2132637..f909014ba 100644 --- a/freqtrade/pairlist/AgeFilter.py +++ b/freqtrade/pairlist/AgeFilter.py @@ -49,11 +49,12 @@ class AgeFilter(IPairList): return (f"{self.name} - Filtering pairs with age less than " f"{self._min_days_listed} {plural(self._min_days_listed, 'day')}.") - def _validate_pair(self, ticker: Dict) -> bool: + def _validate_pair(self, pair: str, ticker: Dict[str, Any]) -> bool: """ Validate age for the ticker + :param pair: Pair that's currently validated :param ticker: ticker dict as returned from ccxt.load_markets() - :return: True if the pair can stay, False if it should be removed + :return: True if the pair can stay, false if it should be removed """ # Check symbol in cache diff --git a/freqtrade/pairlist/IPairList.py b/freqtrade/pairlist/IPairList.py index 5f29241ce..865aa90d6 100644 --- a/freqtrade/pairlist/IPairList.py +++ b/freqtrade/pairlist/IPairList.py @@ -60,13 +60,14 @@ class IPairList(LoggingMixin, ABC): -> Please overwrite in subclasses """ - def _validate_pair(self, ticker) -> bool: + def _validate_pair(self, pair: str, ticker: Dict[str, Any]) -> bool: """ Check one pair against Pairlist Handler's specific conditions. Either implement it in the Pairlist Handler or override the generic filter_pairlist() method. + :param pair: Pair that's currently validated :param ticker: ticker dict as returned from ccxt.load_markets() :return: True if the pair can stay, false if it should be removed """ @@ -109,7 +110,7 @@ class IPairList(LoggingMixin, ABC): # Copy list since we're modifying this list for p in deepcopy(pairlist): # Filter out assets - if not self._validate_pair(tickers[p]): + if not self._validate_pair(p, tickers[p] if p in tickers else {}): pairlist.remove(p) return pairlist diff --git a/freqtrade/pairlist/PrecisionFilter.py b/freqtrade/pairlist/PrecisionFilter.py index db05d5883..c0d2893a1 100644 --- a/freqtrade/pairlist/PrecisionFilter.py +++ b/freqtrade/pairlist/PrecisionFilter.py @@ -43,19 +43,20 @@ class PrecisionFilter(IPairList): """ return f"{self.name} - Filtering untradable pairs." - def _validate_pair(self, ticker: dict) -> bool: + def _validate_pair(self, pair: str, ticker: Dict[str, Any]) -> bool: """ Check if pair has enough room to add a stoploss to avoid "unsellable" buys of very low value pairs. + :param pair: Pair that's currently validated :param ticker: ticker dict as returned from ccxt.load_markets() - :return: True if the pair can stay, False if it should be removed + :return: True if the pair can stay, false if it should be removed """ stop_price = ticker['ask'] * self._stoploss # Adjust stop-prices to precision - sp = self._exchange.price_to_precision(ticker["symbol"], stop_price) + sp = self._exchange.price_to_precision(pair, stop_price) - stop_gap_price = self._exchange.price_to_precision(ticker["symbol"], stop_price * 0.99) + stop_gap_price = self._exchange.price_to_precision(pair, stop_price * 0.99) logger.debug(f"{ticker['symbol']} - {sp} : {stop_gap_price}") if sp <= stop_gap_price: diff --git a/freqtrade/pairlist/PriceFilter.py b/freqtrade/pairlist/PriceFilter.py index 3686cd138..20a260b46 100644 --- a/freqtrade/pairlist/PriceFilter.py +++ b/freqtrade/pairlist/PriceFilter.py @@ -57,31 +57,32 @@ class PriceFilter(IPairList): return f"{self.name} - No price filters configured." - def _validate_pair(self, ticker) -> bool: + def _validate_pair(self, pair: str, ticker: Dict[str, Any]) -> bool: """ Check if if one price-step (pip) is > than a certain barrier. + :param pair: Pair that's currently validated :param ticker: ticker dict as returned from ccxt.load_markets() :return: True if the pair can stay, false if it should be removed """ if ticker['last'] is None or ticker['last'] == 0: - self.log_once(f"Removed {ticker['symbol']} from whitelist, because " + self.log_once(f"Removed {pair} from whitelist, because " "ticker['last'] is empty (Usually no trade in the last 24h).", logger.info) return False # Perform low_price_ratio check. if self._low_price_ratio != 0: - compare = self._exchange.price_get_one_pip(ticker['symbol'], ticker['last']) + compare = self._exchange.price_get_one_pip(pair, ticker['last']) changeperc = compare / ticker['last'] if changeperc > self._low_price_ratio: - self.log_once(f"Removed {ticker['symbol']} from whitelist, " + self.log_once(f"Removed {pair} from whitelist, " f"because 1 unit is {changeperc * 100:.3f}%", logger.info) return False # Perform min_price check. if self._min_price != 0: if ticker['last'] < self._min_price: - self.log_once(f"Removed {ticker['symbol']} from whitelist, " + self.log_once(f"Removed {pair} from whitelist, " f"because last price < {self._min_price:.8f}", logger.info) return False diff --git a/freqtrade/pairlist/SpreadFilter.py b/freqtrade/pairlist/SpreadFilter.py index 6c4e9f12f..cbbfb9626 100644 --- a/freqtrade/pairlist/SpreadFilter.py +++ b/freqtrade/pairlist/SpreadFilter.py @@ -36,16 +36,17 @@ class SpreadFilter(IPairList): return (f"{self.name} - Filtering pairs with ask/bid diff above " f"{self._max_spread_ratio * 100}%.") - def _validate_pair(self, ticker: dict) -> bool: + def _validate_pair(self, pair: str, ticker: Dict[str, Any]) -> bool: """ Validate spread for the ticker + :param pair: Pair that's currently validated :param ticker: ticker dict as returned from ccxt.load_markets() - :return: True if the pair can stay, False if it should be removed + :return: True if the pair can stay, false if it should be removed """ if 'bid' in ticker and 'ask' in ticker: spread = 1 - ticker['bid'] / ticker['ask'] if spread > self._max_spread_ratio: - self.log_once(f"Removed {ticker['symbol']} from whitelist, because spread " + self.log_once(f"Removed {pair} from whitelist, because spread " f"{spread * 100:.3f}% > {self._max_spread_ratio * 100}%", logger.info) return False diff --git a/freqtrade/pairlist/rangestabilityfilter.py b/freqtrade/pairlist/rangestabilityfilter.py index 756368355..f1fecc59c 100644 --- a/freqtrade/pairlist/rangestabilityfilter.py +++ b/freqtrade/pairlist/rangestabilityfilter.py @@ -42,7 +42,7 @@ class RangeStabilityFilter(IPairList): If no Pairlist requires tickers, an empty List is passed as tickers argument to filter_pairlist """ - return True + return False def short_desc(self) -> str: """ @@ -51,13 +51,13 @@ class RangeStabilityFilter(IPairList): return (f"{self.name} - Filtering pairs with rate of change below " f"{self._min_rate_of_change} over the last {plural(self._days, 'day')}.") - def _validate_pair(self, ticker: Dict) -> bool: + def _validate_pair(self, pair: str, ticker: Dict[str, Any]) -> bool: """ Validate trading range + :param pair: Pair that's currently validated :param ticker: ticker dict as returned from ccxt.load_markets() - :return: True if the pair can stay, False if it should be removed + :return: True if the pair can stay, false if it should be removed """ - pair = ticker['symbol'] # Check symbol in cache if pair in self._pair_cache: return self._pair_cache[pair]