Repository: freqtrade/freqtrade

Issue:
Warning log level when VolumePairList and a blacklist are associated
Hi,

Given i have set a VolumePairList and a blacklist containing ` [BNB/USDT]`
When the bot refresh the markets
Then I have a warning message
`2020-02-28 16:01:47,568 - freqtrade.pairlist.IPairList - WARNING - Pair BNB/USDT in your blacklist. Removing it from whitelist...`

I understand a warning in the case i have put in your whitelist and blacklist the same market (has it can be human mistake), but in this case i don't understand why.

Maybe a make an error in my config file ?

Many tks.


Discussion:
why? volumepairlist would have selected it - but blacklist removed it.

assuming, you have volumepairlist configured for 20 pairs - you'll end up with 19 pairs, because BNB/USDT has been removed.
blacklist handling happens after ALL pairlists have ran - to make sure no pairlist can add a pair in the blacklist.
 What i tried to explain is i don't understand why the log level is a `warning`. I tried to manage the logs with elk stack and this `warning` is more an `info` for me. that's all.


Resolving patch:
diff --git a/freqtrade/pairlist/IPairList.py b/freqtrade/pairlist/IPairList.py
--- a/freqtrade/pairlist/IPairList.py
+++ b/freqtrade/pairlist/IPairList.py
@@ -67,21 +67,37 @@ def filter_pairlist(self, pairlist: List[str], tickers: Dict) -> List[str]:
         """
 
     @staticmethod
-    def verify_blacklist(pairlist: List[str], blacklist: List[str]) -> List[str]:
+    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`.
+        Pairlists 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:
-                logger.warning(f"Pair {pair} in your blacklist. Removing it from whitelist...")
+                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]) -> List[str]:
+    def _verify_blacklist(self, pairlist: List[str], aswarning: bool = True) -> 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!
+        :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)
+        return IPairList.verify_blacklist(pairlist, self._pairlistmanager.blacklist,
+                                          aswarning=aswarning)
 
     def _whitelist_for_active_markets(self, pairlist: List[str]) -> List[str]:
         """
@@ -113,6 +129,5 @@ def _whitelist_for_active_markets(self, pairlist: List[str]) -> List[str]:
             if pair not in sanitized_whitelist:
                 sanitized_whitelist.append(pair)
 
-        sanitized_whitelist = self._verify_blacklist(sanitized_whitelist)
         # We need to remove pairs that are unknown
         return sanitized_whitelist
diff --git a/freqtrade/pairlist/VolumePairList.py b/freqtrade/pairlist/VolumePairList.py
--- a/freqtrade/pairlist/VolumePairList.py
+++ b/freqtrade/pairlist/VolumePairList.py
@@ -106,7 +106,7 @@ def _gen_pair_whitelist(self, pairlist: List[str], tickers: Dict,
 
         # 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, aswarning=False)
         # Limit to X number of pairs
         pairs = pairs[:self._number_pairs]
         logger.info(f"Searching {self._number_pairs} pairs: {pairs}")
diff --git a/freqtrade/pairlist/pairlistmanager.py b/freqtrade/pairlist/pairlistmanager.py
--- a/freqtrade/pairlist/pairlistmanager.py
+++ b/freqtrade/pairlist/pairlistmanager.py
@@ -91,6 +91,6 @@ def refresh_pairlist(self) -> None:
             pairlist = pl.filter_pairlist(pairlist, tickers)
 
         # Validation against blacklist happens after the pairlists to ensure blacklist is respected.
-        pairlist = IPairList.verify_blacklist(pairlist, self.blacklist)
+        pairlist = IPairList.verify_blacklist(pairlist, self.blacklist, True)
 
         self._whitelist = pairlist


Test patch:
diff --git a/tests/pairlist/test_pairlist.py b/tests/pairlist/test_pairlist.py
--- a/tests/pairlist/test_pairlist.py
+++ b/tests/pairlist/test_pairlist.py
@@ -240,8 +240,6 @@ def test_pairlist_class(mocker, whitelist_conf, markets, pairlist):
     (['ETH/BTC', 'TKN/BTC', 'ETH/USDT'], "is not compatible with your stake currency"),
     # BCH/BTC not available
     (['ETH/BTC', 'TKN/BTC', 'BCH/BTC'], "is not compatible with exchange"),
-    # BLK/BTC in blacklist
-    (['ETH/BTC', 'TKN/BTC', 'BLK/BTC'], "in your blacklist. Removing "),
     # BTT/BTC is inactive
     (['ETH/BTC', 'TKN/BTC', 'BTT/BTC'], "Market is not active")
 ])