diff --git a/freqtrade/pairlist/VolumePairList.py b/freqtrade/pairlist/VolumePairList.py index 5e20f0fb1..44dbd0ecf 100644 --- a/freqtrade/pairlist/VolumePairList.py +++ b/freqtrade/pairlist/VolumePairList.py @@ -56,6 +56,27 @@ class VolumePairList(IPairList): self._whitelist = self._gen_pair_whitelist( self._config['stake_currency'], self._sort_key) + def _validate_precision_filter(self, ticker: dict, stoploss: float) -> bool: + """ + Check if pair has enough room to add a stoploss to avoid "unsellable" buys of very + low value pairs. + :param ticker: ticker dict as returned from ccxt.load_markets() + :param stoploss: stoploss value as set in the configuration + (already cleaned to be guaranteed negative) + :return: True if the pair can stay, false if it should be removed + """ + stop_price = (self._freqtrade.get_target_bid(ticker["symbol"], ticker) * stoploss) + # Adjust stop-prices to precision + sp = self._freqtrade.exchange.symbol_price_prec(ticker["symbol"], stop_price) + stop_gap_price = self._freqtrade.exchange.symbol_price_prec(ticker["symbol"], + stop_price * 0.99) + logger.debug(f"{ticker['symbol']} - {sp} : {stop_gap_price}") + if sp <= stop_gap_price: + logger.info(f"Removed {ticker['symbol']} from whitelist, " + f"because stop price {sp} would be <= stop limit {stop_gap_price}") + return False + return True + @cached(TTLCache(maxsize=1, ttl=1800)) def _gen_pair_whitelist(self, base_currency: str, key: str) -> List[str]: """ @@ -75,21 +96,16 @@ class VolumePairList(IPairList): valid_pairs = self._validate_whitelist([s['symbol'] for s in sorted_tickers]) valid_tickers = [t for t in sorted_tickers if t["symbol"] in valid_pairs] - if self._freqtrade.strategy.stoploss is not None and self._precision_filter: - # Precalculate correct stoploss value + stoploss = None + if self._freqtrade.strategy.stoploss is not None: + # Precalculate sanitized stoploss value to avoid recalculation for every pair stoploss = 1 - abs(self._freqtrade.strategy.stoploss) - for i, t in enumerate(valid_tickers): - stop_price = (self._freqtrade.get_target_bid(t["symbol"], t) * stoploss) - # Adjust stop-prices to precision - sp = self._freqtrade.exchange.symbol_price_prec(t["symbol"], stop_price) - stop_gap_price = self._freqtrade.exchange.symbol_price_prec(t["symbol"], - stop_price * 0.99) - logger.debug(f"{t['symbol']} - {sp} : {stop_gap_price}") - if sp <= stop_gap_price: - logger.info(f"Removed {t['symbol']} from whitelist, " - f"because stop price {sp} would be <= stop limit {stop_gap_price}") - valid_tickers.remove(t) + for t in valid_tickers: + # Filter out assets which would not allow setting a stoploss + if (stoploss and self._precision_filter + and not self._validate_precision_filter(t, stoploss)): + valid_tickers.remove(t) pairs = [s['symbol'] for s in valid_tickers] logger.info(f"Searching pairs: {pairs[:self._number_pairs]}")