We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN 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.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `freqtrade/pairlist/pairlistmanager.py`
Content:
```
1 """
2 Static List provider
3 
4 Provides lists as configured in config.json
5 
6  """
7 import logging
8 from typing import Dict, List
9 
10 from cachetools import TTLCache, cached
11 
12 from freqtrade.exceptions import OperationalException
13 from freqtrade.pairlist.IPairList import IPairList
14 from freqtrade.resolvers import PairListResolver
15 
16 logger = logging.getLogger(__name__)
17 
18 
19 class PairListManager():
20 
21     def __init__(self, exchange, config: dict) -> None:
22         self._exchange = exchange
23         self._config = config
24         self._whitelist = self._config['exchange'].get('pair_whitelist')
25         self._blacklist = self._config['exchange'].get('pair_blacklist', [])
26         self._pairlists: List[IPairList] = []
27         self._tickers_needed = False
28         for pl in self._config.get('pairlists', None):
29             if 'method' not in pl:
30                 logger.warning(f"No method in {pl}")
31                 continue
32             pairl = PairListResolver.load_pairlist(pl.get('method'),
33                                                    exchange=exchange,
34                                                    pairlistmanager=self,
35                                                    config=config,
36                                                    pairlistconfig=pl,
37                                                    pairlist_pos=len(self._pairlists)
38                                                    )
39             self._tickers_needed = pairl.needstickers or self._tickers_needed
40             self._pairlists.append(pairl)
41 
42         if not self._pairlists:
43             raise OperationalException("No Pairlist defined!")
44 
45     @property
46     def whitelist(self) -> List[str]:
47         """
48         Has the current whitelist
49         """
50         return self._whitelist
51 
52     @property
53     def blacklist(self) -> List[str]:
54         """
55         Has the current blacklist
56         -> no need to overwrite in subclasses
57         """
58         return self._blacklist
59 
60     @property
61     def name_list(self) -> List[str]:
62         """
63         Get list of loaded pairlists names
64         """
65         return [p.name for p in self._pairlists]
66 
67     def short_desc(self) -> List[Dict]:
68         """
69         List of short_desc for each pairlist
70         """
71         return [{p.name: p.short_desc()} for p in self._pairlists]
72 
73     @cached(TTLCache(maxsize=1, ttl=1800))
74     def _get_cached_tickers(self):
75         return self._exchange.get_tickers()
76 
77     def refresh_pairlist(self) -> None:
78         """
79         Run pairlist through all configured pairlists.
80         """
81 
82         pairlist = self._whitelist.copy()
83 
84         # tickers should be cached to avoid calling the exchange on each call.
85         tickers: Dict = {}
86         if self._tickers_needed:
87             tickers = self._get_cached_tickers()
88 
89         # Process all pairlists in chain
90         for pl in self._pairlists:
91             pairlist = pl.filter_pairlist(pairlist, tickers)
92 
93         # Validation against blacklist happens after the pairlists to ensure blacklist is respected.
94         pairlist = IPairList.verify_blacklist(pairlist, self.blacklist)
95 
96         self._whitelist = pairlist
97
```

Path: `freqtrade/pairlist/IPairList.py`
Content:
```
1 """
2 Static List provider
3 
4 Provides lists as configured in config.json
5 
6  """
7 import logging
8 from abc import ABC, abstractmethod, abstractproperty
9 from copy import deepcopy
10 from typing import Any, Dict, List
11 
12 from freqtrade.exchange import market_is_active
13 
14 logger = logging.getLogger(__name__)
15 
16 
17 class IPairList(ABC):
18 
19     def __init__(self, exchange, pairlistmanager,
20                  config: Dict[str, Any], pairlistconfig: Dict[str, Any],
21                  pairlist_pos: int) -> None:
22         """
23         :param exchange: Exchange instance
24         :param pairlistmanager: Instanciating Pairlist manager
25         :param config: Global bot configuration
26         :param pairlistconfig: Configuration for this pairlist - can be empty.
27         :param pairlist_pos: Position of the filter in the pairlist-filter-list
28         """
29         self._exchange = exchange
30         self._pairlistmanager = pairlistmanager
31         self._config = config
32         self._pairlistconfig = pairlistconfig
33         self._pairlist_pos = pairlist_pos
34 
35     @property
36     def name(self) -> str:
37         """
38         Gets name of the class
39         -> no need to overwrite in subclasses
40         """
41         return self.__class__.__name__
42 
43     @abstractproperty
44     def needstickers(self) -> bool:
45         """
46         Boolean property defining if tickers are necessary.
47         If no Pairlist requries tickers, an empty List is passed
48         as tickers argument to filter_pairlist
49         """
50 
51     @abstractmethod
52     def short_desc(self) -> str:
53         """
54         Short whitelist method description - used for startup-messages
55         -> Please overwrite in subclasses
56         """
57 
58     @abstractmethod
59     def filter_pairlist(self, pairlist: List[str], tickers: Dict) -> List[str]:
60         """
61         Filters and sorts pairlist and returns the whitelist again.
62         Called on each bot iteration - please use internal caching if necessary
63         -> Please overwrite in subclasses
64         :param pairlist: pairlist to filter or sort
65         :param tickers: Tickers (from exchange.get_tickers()). May be cached.
66         :return: new whitelist
67         """
68 
69     @staticmethod
70     def verify_blacklist(pairlist: List[str], blacklist: List[str]) -> List[str]:
71         """
72         Verify and remove items from pairlist - returning a filtered pairlist.
73         """
74         for pair in deepcopy(pairlist):
75             if pair in blacklist:
76                 logger.warning(f"Pair {pair} in your blacklist. Removing it from whitelist...")
77                 pairlist.remove(pair)
78         return pairlist
79 
80     def _verify_blacklist(self, pairlist: List[str]) -> List[str]:
81         """
82         Proxy method to verify_blacklist for easy access for child classes.
83         """
84         return IPairList.verify_blacklist(pairlist, self._pairlistmanager.blacklist)
85 
86     def _whitelist_for_active_markets(self, pairlist: List[str]) -> List[str]:
87         """
88         Check available markets and remove pair from whitelist if necessary
89         :param whitelist: the sorted list of pairs the user might want to trade
90         :return: the list of pairs the user wants to trade without those unavailable or
91         black_listed
92         """
93         markets = self._exchange.markets
94 
95         sanitized_whitelist: List[str] = []
96         for pair in pairlist:
97             # pair is not in the generated dynamic market or has the wrong stake currency
98             if pair not in markets:
99                 logger.warning(f"Pair {pair} is not compatible with exchange "
100                                f"{self._exchange.name}. Removing it from whitelist..")
101                 continue
102 
103             if self._exchange.get_pair_quote_currency(pair) != self._config['stake_currency']:
104                 logger.warning(f"Pair {pair} is not compatible with your stake currency "
105                                f"{self._config['stake_currency']}. Removing it from whitelist..")
106                 continue
107 
108             # Check if market is active
109             market = markets[pair]
110             if not market_is_active(market):
111                 logger.info(f"Ignoring {pair} from whitelist. Market is not active.")
112                 continue
113             if pair not in sanitized_whitelist:
114                 sanitized_whitelist.append(pair)
115 
116         sanitized_whitelist = self._verify_blacklist(sanitized_whitelist)
117         # We need to remove pairs that are unknown
118         return sanitized_whitelist
119
```

Path: `freqtrade/pairlist/VolumePairList.py`
Content:
```
1 """
2 Volume PairList provider
3 
4 Provides lists as configured in config.json
5 
6  """
7 import logging
8 from datetime import datetime
9 from typing import Any, Dict, List
10 
11 from freqtrade.exceptions import OperationalException
12 from freqtrade.pairlist.IPairList import IPairList
13 
14 logger = logging.getLogger(__name__)
15 
16 SORT_VALUES = ['askVolume', 'bidVolume', 'quoteVolume']
17 
18 
19 class VolumePairList(IPairList):
20 
21     def __init__(self, exchange, pairlistmanager, config: Dict[str, Any], pairlistconfig: dict,
22                  pairlist_pos: int) -> None:
23         super().__init__(exchange, pairlistmanager, config, pairlistconfig, pairlist_pos)
24 
25         if 'number_assets' not in self._pairlistconfig:
26             raise OperationalException(
27                 f'`number_assets` not specified. Please check your configuration '
28                 'for "pairlist.config.number_assets"')
29         self._number_pairs = self._pairlistconfig['number_assets']
30         self._sort_key = self._pairlistconfig.get('sort_key', 'quoteVolume')
31         self._min_value = self._pairlistconfig.get('min_value', 0)
32         self.refresh_period = self._pairlistconfig.get('refresh_period', 1800)
33 
34         if not self._exchange.exchange_has('fetchTickers'):
35             raise OperationalException(
36                 'Exchange does not support dynamic whitelist.'
37                 'Please edit your config and restart the bot'
38             )
39         if not self._validate_keys(self._sort_key):
40             raise OperationalException(
41                 f'key {self._sort_key} not in {SORT_VALUES}')
42         self._last_refresh = 0
43 
44     @property
45     def needstickers(self) -> bool:
46         """
47         Boolean property defining if tickers are necessary.
48         If no Pairlist requries tickers, an empty List is passed
49         as tickers argument to filter_pairlist
50         """
51         return True
52 
53     def _validate_keys(self, key):
54         return key in SORT_VALUES
55 
56     def short_desc(self) -> str:
57         """
58         Short whitelist method description - used for startup-messages
59         """
60         return f"{self.name} - top {self._pairlistconfig['number_assets']} volume pairs."
61 
62     def filter_pairlist(self, pairlist: List[str], tickers: Dict) -> List[str]:
63         """
64         Filters and sorts pairlist and returns the whitelist again.
65         Called on each bot iteration - please use internal caching if necessary
66         :param pairlist: pairlist to filter or sort
67         :param tickers: Tickers (from exchange.get_tickers()). May be cached.
68         :return: new whitelist
69         """
70         # Generate dynamic whitelist
71         if self._last_refresh + self.refresh_period < datetime.now().timestamp():
72             self._last_refresh = int(datetime.now().timestamp())
73             return self._gen_pair_whitelist(pairlist,
74                                             tickers,
75                                             self._config['stake_currency'],
76                                             self._sort_key,
77                                             self._min_value
78                                             )
79         else:
80             return pairlist
81 
82     def _gen_pair_whitelist(self, pairlist: List[str], tickers: Dict,
83                             base_currency: str, key: str, min_val: int) -> List[str]:
84         """
85         Updates the whitelist with with a dynamically generated list
86         :param base_currency: base currency as str
87         :param key: sort key (defaults to 'quoteVolume')
88         :param tickers: Tickers (from exchange.get_tickers()).
89         :return: List of pairs
90         """
91 
92         if self._pairlist_pos == 0:
93             # If VolumePairList is the first in the list, use fresh pairlist
94             # Check if pair quote currency equals to the stake currency.
95             filtered_tickers = [v for k, v in tickers.items()
96                                 if (self._exchange.get_pair_quote_currency(k) == base_currency
97                                     and v[key] is not None)]
98         else:
99             # If other pairlist is in front, use the incomming pairlist.
100             filtered_tickers = [v for k, v in tickers.items() if k in pairlist]
101 
102         if min_val > 0:
103             filtered_tickers = list(filter(lambda t: t[key] > min_val, filtered_tickers))
104 
105         sorted_tickers = sorted(filtered_tickers, reverse=True, key=lambda t: t[key])
106 
107         # Validate whitelist to only have active market pairs
108         pairs = self._whitelist_for_active_markets([s['symbol'] for s in sorted_tickers])
109         pairs = self._verify_blacklist(pairs)
110         # Limit to X number of pairs
111         pairs = pairs[:self._number_pairs]
112         logger.info(f"Searching {self._number_pairs} pairs: {pairs}")
113 
114         return pairs
115
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

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 @@
         """
 
     @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 @@
             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 @@
 
         # 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 @@
             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

{"golden_diff": "diff --git a/freqtrade/pairlist/IPairList.py b/freqtrade/pairlist/IPairList.py\n--- a/freqtrade/pairlist/IPairList.py\n+++ b/freqtrade/pairlist/IPairList.py\n@@ -67,21 +67,37 @@\n         \"\"\"\n \n     @staticmethod\n-    def verify_blacklist(pairlist: List[str], blacklist: List[str]) -> List[str]:\n+    def verify_blacklist(pairlist: List[str], blacklist: List[str],\n+                         aswarning: bool) -> List[str]:\n         \"\"\"\n         Verify and remove items from pairlist - returning a filtered pairlist.\n+        Logs a warning or info depending on `aswarning`.\n+        Pairlists explicitly using this method shall use `aswarning=False`!\n+        :param pairlist: Pairlist to validate\n+        :param blacklist: Blacklist to validate pairlist against\n+        :param aswarning: Log message as Warning or info\n+        :return: pairlist - blacklisted pairs\n         \"\"\"\n         for pair in deepcopy(pairlist):\n             if pair in blacklist:\n-                logger.warning(f\"Pair {pair} in your blacklist. Removing it from whitelist...\")\n+                if aswarning:\n+                    logger.warning(f\"Pair {pair} in your blacklist. Removing it from whitelist...\")\n+                else:\n+                    logger.info(f\"Pair {pair} in your blacklist. Removing it from whitelist...\")\n                 pairlist.remove(pair)\n         return pairlist\n \n-    def _verify_blacklist(self, pairlist: List[str]) -> List[str]:\n+    def _verify_blacklist(self, pairlist: List[str], aswarning: bool = True) -> List[str]:\n         \"\"\"\n         Proxy method to verify_blacklist for easy access for child classes.\n+        Logs a warning or info depending on `aswarning`.\n+        Pairlists explicitly using this method shall use aswarning=False!\n+        :param pairlist: Pairlist to validate\n+        :param aswarning: Log message as Warning or info.\n+        :return: pairlist - blacklisted pairs\n         \"\"\"\n-        return IPairList.verify_blacklist(pairlist, self._pairlistmanager.blacklist)\n+        return IPairList.verify_blacklist(pairlist, self._pairlistmanager.blacklist,\n+                                          aswarning=aswarning)\n \n     def _whitelist_for_active_markets(self, pairlist: List[str]) -> List[str]:\n         \"\"\"\n@@ -113,6 +129,5 @@\n             if pair not in sanitized_whitelist:\n                 sanitized_whitelist.append(pair)\n \n-        sanitized_whitelist = self._verify_blacklist(sanitized_whitelist)\n         # We need to remove pairs that are unknown\n         return sanitized_whitelist\ndiff --git a/freqtrade/pairlist/VolumePairList.py b/freqtrade/pairlist/VolumePairList.py\n--- a/freqtrade/pairlist/VolumePairList.py\n+++ b/freqtrade/pairlist/VolumePairList.py\n@@ -106,7 +106,7 @@\n \n         # Validate whitelist to only have active market pairs\n         pairs = self._whitelist_for_active_markets([s['symbol'] for s in sorted_tickers])\n-        pairs = self._verify_blacklist(pairs)\n+        pairs = self._verify_blacklist(pairs, aswarning=False)\n         # Limit to X number of pairs\n         pairs = pairs[:self._number_pairs]\n         logger.info(f\"Searching {self._number_pairs} pairs: {pairs}\")\ndiff --git a/freqtrade/pairlist/pairlistmanager.py b/freqtrade/pairlist/pairlistmanager.py\n--- a/freqtrade/pairlist/pairlistmanager.py\n+++ b/freqtrade/pairlist/pairlistmanager.py\n@@ -91,6 +91,6 @@\n             pairlist = pl.filter_pairlist(pairlist, tickers)\n \n         # Validation against blacklist happens after the pairlists to ensure blacklist is respected.\n-        pairlist = IPairList.verify_blacklist(pairlist, self.blacklist)\n+        pairlist = IPairList.verify_blacklist(pairlist, self.blacklist, True)\n \n         self._whitelist = pairlist\n", "issue": "Warning log level when VolumePairList and a blacklist are associated\nHi,\r\n\r\nGiven i have set a VolumePairList and a blacklist containing ` [BNB/USDT]`\r\nWhen the bot refresh the markets\r\nThen I have a warning message\r\n`2020-02-28 16:01:47,568 - freqtrade.pairlist.IPairList - WARNING - Pair BNB/USDT in your blacklist. Removing it from whitelist...`\r\n\r\nI 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.\r\n\r\nMaybe a make an error in my config file ?\r\n\r\nMany tks.\n", "before_files": [{"content": "\"\"\"\nStatic List provider\n\nProvides lists as configured in config.json\n\n \"\"\"\nimport logging\nfrom typing import Dict, List\n\nfrom cachetools import TTLCache, cached\n\nfrom freqtrade.exceptions import OperationalException\nfrom freqtrade.pairlist.IPairList import IPairList\nfrom freqtrade.resolvers import PairListResolver\n\nlogger = logging.getLogger(__name__)\n\n\nclass PairListManager():\n\n    def __init__(self, exchange, config: dict) -> None:\n        self._exchange = exchange\n        self._config = config\n        self._whitelist = self._config['exchange'].get('pair_whitelist')\n        self._blacklist = self._config['exchange'].get('pair_blacklist', [])\n        self._pairlists: List[IPairList] = []\n        self._tickers_needed = False\n        for pl in self._config.get('pairlists', None):\n            if 'method' not in pl:\n                logger.warning(f\"No method in {pl}\")\n                continue\n            pairl = PairListResolver.load_pairlist(pl.get('method'),\n                                                   exchange=exchange,\n                                                   pairlistmanager=self,\n                                                   config=config,\n                                                   pairlistconfig=pl,\n                                                   pairlist_pos=len(self._pairlists)\n                                                   )\n            self._tickers_needed = pairl.needstickers or self._tickers_needed\n            self._pairlists.append(pairl)\n\n        if not self._pairlists:\n            raise OperationalException(\"No Pairlist defined!\")\n\n    @property\n    def whitelist(self) -> List[str]:\n        \"\"\"\n        Has the current whitelist\n        \"\"\"\n        return self._whitelist\n\n    @property\n    def blacklist(self) -> List[str]:\n        \"\"\"\n        Has the current blacklist\n        -> no need to overwrite in subclasses\n        \"\"\"\n        return self._blacklist\n\n    @property\n    def name_list(self) -> List[str]:\n        \"\"\"\n        Get list of loaded pairlists names\n        \"\"\"\n        return [p.name for p in self._pairlists]\n\n    def short_desc(self) -> List[Dict]:\n        \"\"\"\n        List of short_desc for each pairlist\n        \"\"\"\n        return [{p.name: p.short_desc()} for p in self._pairlists]\n\n    @cached(TTLCache(maxsize=1, ttl=1800))\n    def _get_cached_tickers(self):\n        return self._exchange.get_tickers()\n\n    def refresh_pairlist(self) -> None:\n        \"\"\"\n        Run pairlist through all configured pairlists.\n        \"\"\"\n\n        pairlist = self._whitelist.copy()\n\n        # tickers should be cached to avoid calling the exchange on each call.\n        tickers: Dict = {}\n        if self._tickers_needed:\n            tickers = self._get_cached_tickers()\n\n        # Process all pairlists in chain\n        for pl in self._pairlists:\n            pairlist = pl.filter_pairlist(pairlist, tickers)\n\n        # Validation against blacklist happens after the pairlists to ensure blacklist is respected.\n        pairlist = IPairList.verify_blacklist(pairlist, self.blacklist)\n\n        self._whitelist = pairlist\n", "path": "freqtrade/pairlist/pairlistmanager.py"}, {"content": "\"\"\"\nStatic List provider\n\nProvides lists as configured in config.json\n\n \"\"\"\nimport logging\nfrom abc import ABC, abstractmethod, abstractproperty\nfrom copy import deepcopy\nfrom typing import Any, Dict, List\n\nfrom freqtrade.exchange import market_is_active\n\nlogger = logging.getLogger(__name__)\n\n\nclass IPairList(ABC):\n\n    def __init__(self, exchange, pairlistmanager,\n                 config: Dict[str, Any], pairlistconfig: Dict[str, Any],\n                 pairlist_pos: int) -> None:\n        \"\"\"\n        :param exchange: Exchange instance\n        :param pairlistmanager: Instanciating Pairlist manager\n        :param config: Global bot configuration\n        :param pairlistconfig: Configuration for this pairlist - can be empty.\n        :param pairlist_pos: Position of the filter in the pairlist-filter-list\n        \"\"\"\n        self._exchange = exchange\n        self._pairlistmanager = pairlistmanager\n        self._config = config\n        self._pairlistconfig = pairlistconfig\n        self._pairlist_pos = pairlist_pos\n\n    @property\n    def name(self) -> str:\n        \"\"\"\n        Gets name of the class\n        -> no need to overwrite in subclasses\n        \"\"\"\n        return self.__class__.__name__\n\n    @abstractproperty\n    def needstickers(self) -> bool:\n        \"\"\"\n        Boolean property defining if tickers are necessary.\n        If no Pairlist requries tickers, an empty List is passed\n        as tickers argument to filter_pairlist\n        \"\"\"\n\n    @abstractmethod\n    def short_desc(self) -> str:\n        \"\"\"\n        Short whitelist method description - used for startup-messages\n        -> Please overwrite in subclasses\n        \"\"\"\n\n    @abstractmethod\n    def filter_pairlist(self, pairlist: List[str], tickers: Dict) -> List[str]:\n        \"\"\"\n        Filters and sorts pairlist and returns the whitelist again.\n        Called on each bot iteration - please use internal caching if necessary\n        -> Please overwrite in subclasses\n        :param pairlist: pairlist to filter or sort\n        :param tickers: Tickers (from exchange.get_tickers()). May be cached.\n        :return: new whitelist\n        \"\"\"\n\n    @staticmethod\n    def verify_blacklist(pairlist: List[str], blacklist: List[str]) -> List[str]:\n        \"\"\"\n        Verify and remove items from pairlist - returning a filtered pairlist.\n        \"\"\"\n        for pair in deepcopy(pairlist):\n            if pair in blacklist:\n                logger.warning(f\"Pair {pair} in your blacklist. Removing it from whitelist...\")\n                pairlist.remove(pair)\n        return pairlist\n\n    def _verify_blacklist(self, pairlist: List[str]) -> List[str]:\n        \"\"\"\n        Proxy method to verify_blacklist for easy access for child classes.\n        \"\"\"\n        return IPairList.verify_blacklist(pairlist, self._pairlistmanager.blacklist)\n\n    def _whitelist_for_active_markets(self, pairlist: List[str]) -> List[str]:\n        \"\"\"\n        Check available markets and remove pair from whitelist if necessary\n        :param whitelist: the sorted list of pairs the user might want to trade\n        :return: the list of pairs the user wants to trade without those unavailable or\n        black_listed\n        \"\"\"\n        markets = self._exchange.markets\n\n        sanitized_whitelist: List[str] = []\n        for pair in pairlist:\n            # pair is not in the generated dynamic market or has the wrong stake currency\n            if pair not in markets:\n                logger.warning(f\"Pair {pair} is not compatible with exchange \"\n                               f\"{self._exchange.name}. Removing it from whitelist..\")\n                continue\n\n            if self._exchange.get_pair_quote_currency(pair) != self._config['stake_currency']:\n                logger.warning(f\"Pair {pair} is not compatible with your stake currency \"\n                               f\"{self._config['stake_currency']}. Removing it from whitelist..\")\n                continue\n\n            # Check if market is active\n            market = markets[pair]\n            if not market_is_active(market):\n                logger.info(f\"Ignoring {pair} from whitelist. Market is not active.\")\n                continue\n            if pair not in sanitized_whitelist:\n                sanitized_whitelist.append(pair)\n\n        sanitized_whitelist = self._verify_blacklist(sanitized_whitelist)\n        # We need to remove pairs that are unknown\n        return sanitized_whitelist\n", "path": "freqtrade/pairlist/IPairList.py"}, {"content": "\"\"\"\nVolume PairList provider\n\nProvides lists as configured in config.json\n\n \"\"\"\nimport logging\nfrom datetime import datetime\nfrom typing import Any, Dict, List\n\nfrom freqtrade.exceptions import OperationalException\nfrom freqtrade.pairlist.IPairList import IPairList\n\nlogger = logging.getLogger(__name__)\n\nSORT_VALUES = ['askVolume', 'bidVolume', 'quoteVolume']\n\n\nclass VolumePairList(IPairList):\n\n    def __init__(self, exchange, pairlistmanager, config: Dict[str, Any], pairlistconfig: dict,\n                 pairlist_pos: int) -> None:\n        super().__init__(exchange, pairlistmanager, config, pairlistconfig, pairlist_pos)\n\n        if 'number_assets' not in self._pairlistconfig:\n            raise OperationalException(\n                f'`number_assets` not specified. Please check your configuration '\n                'for \"pairlist.config.number_assets\"')\n        self._number_pairs = self._pairlistconfig['number_assets']\n        self._sort_key = self._pairlistconfig.get('sort_key', 'quoteVolume')\n        self._min_value = self._pairlistconfig.get('min_value', 0)\n        self.refresh_period = self._pairlistconfig.get('refresh_period', 1800)\n\n        if not self._exchange.exchange_has('fetchTickers'):\n            raise OperationalException(\n                'Exchange does not support dynamic whitelist.'\n                'Please edit your config and restart the bot'\n            )\n        if not self._validate_keys(self._sort_key):\n            raise OperationalException(\n                f'key {self._sort_key} not in {SORT_VALUES}')\n        self._last_refresh = 0\n\n    @property\n    def needstickers(self) -> bool:\n        \"\"\"\n        Boolean property defining if tickers are necessary.\n        If no Pairlist requries tickers, an empty List is passed\n        as tickers argument to filter_pairlist\n        \"\"\"\n        return True\n\n    def _validate_keys(self, key):\n        return key in SORT_VALUES\n\n    def short_desc(self) -> str:\n        \"\"\"\n        Short whitelist method description - used for startup-messages\n        \"\"\"\n        return f\"{self.name} - top {self._pairlistconfig['number_assets']} volume pairs.\"\n\n    def filter_pairlist(self, pairlist: List[str], tickers: Dict) -> List[str]:\n        \"\"\"\n        Filters and sorts pairlist and returns the whitelist again.\n        Called on each bot iteration - please use internal caching if necessary\n        :param pairlist: pairlist to filter or sort\n        :param tickers: Tickers (from exchange.get_tickers()). May be cached.\n        :return: new whitelist\n        \"\"\"\n        # Generate dynamic whitelist\n        if self._last_refresh + self.refresh_period < datetime.now().timestamp():\n            self._last_refresh = int(datetime.now().timestamp())\n            return self._gen_pair_whitelist(pairlist,\n                                            tickers,\n                                            self._config['stake_currency'],\n                                            self._sort_key,\n                                            self._min_value\n                                            )\n        else:\n            return pairlist\n\n    def _gen_pair_whitelist(self, pairlist: List[str], tickers: Dict,\n                            base_currency: str, key: str, min_val: int) -> List[str]:\n        \"\"\"\n        Updates the whitelist with with a dynamically generated list\n        :param base_currency: base currency as str\n        :param key: sort key (defaults to 'quoteVolume')\n        :param tickers: Tickers (from exchange.get_tickers()).\n        :return: List of pairs\n        \"\"\"\n\n        if self._pairlist_pos == 0:\n            # If VolumePairList is the first in the list, use fresh pairlist\n            # Check if pair quote currency equals to the stake currency.\n            filtered_tickers = [v for k, v in tickers.items()\n                                if (self._exchange.get_pair_quote_currency(k) == base_currency\n                                    and v[key] is not None)]\n        else:\n            # If other pairlist is in front, use the incomming pairlist.\n            filtered_tickers = [v for k, v in tickers.items() if k in pairlist]\n\n        if min_val > 0:\n            filtered_tickers = list(filter(lambda t: t[key] > min_val, filtered_tickers))\n\n        sorted_tickers = sorted(filtered_tickers, reverse=True, key=lambda t: t[key])\n\n        # Validate whitelist to only have active market pairs\n        pairs = self._whitelist_for_active_markets([s['symbol'] for s in sorted_tickers])\n        pairs = self._verify_blacklist(pairs)\n        # Limit to X number of pairs\n        pairs = pairs[:self._number_pairs]\n        logger.info(f\"Searching {self._number_pairs} pairs: {pairs}\")\n\n        return pairs\n", "path": "freqtrade/pairlist/VolumePairList.py"}], "after_files": [{"content": "\"\"\"\nStatic List provider\n\nProvides lists as configured in config.json\n\n \"\"\"\nimport logging\nfrom typing import Dict, List\n\nfrom cachetools import TTLCache, cached\n\nfrom freqtrade.exceptions import OperationalException\nfrom freqtrade.pairlist.IPairList import IPairList\nfrom freqtrade.resolvers import PairListResolver\n\nlogger = logging.getLogger(__name__)\n\n\nclass PairListManager():\n\n    def __init__(self, exchange, config: dict) -> None:\n        self._exchange = exchange\n        self._config = config\n        self._whitelist = self._config['exchange'].get('pair_whitelist')\n        self._blacklist = self._config['exchange'].get('pair_blacklist', [])\n        self._pairlists: List[IPairList] = []\n        self._tickers_needed = False\n        for pl in self._config.get('pairlists', None):\n            if 'method' not in pl:\n                logger.warning(f\"No method in {pl}\")\n                continue\n            pairl = PairListResolver.load_pairlist(pl.get('method'),\n                                                   exchange=exchange,\n                                                   pairlistmanager=self,\n                                                   config=config,\n                                                   pairlistconfig=pl,\n                                                   pairlist_pos=len(self._pairlists)\n                                                   )\n            self._tickers_needed = pairl.needstickers or self._tickers_needed\n            self._pairlists.append(pairl)\n\n        if not self._pairlists:\n            raise OperationalException(\"No Pairlist defined!\")\n\n    @property\n    def whitelist(self) -> List[str]:\n        \"\"\"\n        Has the current whitelist\n        \"\"\"\n        return self._whitelist\n\n    @property\n    def blacklist(self) -> List[str]:\n        \"\"\"\n        Has the current blacklist\n        -> no need to overwrite in subclasses\n        \"\"\"\n        return self._blacklist\n\n    @property\n    def name_list(self) -> List[str]:\n        \"\"\"\n        Get list of loaded pairlists names\n        \"\"\"\n        return [p.name for p in self._pairlists]\n\n    def short_desc(self) -> List[Dict]:\n        \"\"\"\n        List of short_desc for each pairlist\n        \"\"\"\n        return [{p.name: p.short_desc()} for p in self._pairlists]\n\n    @cached(TTLCache(maxsize=1, ttl=1800))\n    def _get_cached_tickers(self):\n        return self._exchange.get_tickers()\n\n    def refresh_pairlist(self) -> None:\n        \"\"\"\n        Run pairlist through all configured pairlists.\n        \"\"\"\n\n        pairlist = self._whitelist.copy()\n\n        # tickers should be cached to avoid calling the exchange on each call.\n        tickers: Dict = {}\n        if self._tickers_needed:\n            tickers = self._get_cached_tickers()\n\n        # Process all pairlists in chain\n        for pl in self._pairlists:\n            pairlist = pl.filter_pairlist(pairlist, tickers)\n\n        # Validation against blacklist happens after the pairlists to ensure blacklist is respected.\n        pairlist = IPairList.verify_blacklist(pairlist, self.blacklist, True)\n\n        self._whitelist = pairlist\n", "path": "freqtrade/pairlist/pairlistmanager.py"}, {"content": "\"\"\"\nStatic List provider\n\nProvides lists as configured in config.json\n\n \"\"\"\nimport logging\nfrom abc import ABC, abstractmethod, abstractproperty\nfrom copy import deepcopy\nfrom typing import Any, Dict, List\n\nfrom freqtrade.exchange import market_is_active\n\nlogger = logging.getLogger(__name__)\n\n\nclass IPairList(ABC):\n\n    def __init__(self, exchange, pairlistmanager,\n                 config: Dict[str, Any], pairlistconfig: Dict[str, Any],\n                 pairlist_pos: int) -> None:\n        \"\"\"\n        :param exchange: Exchange instance\n        :param pairlistmanager: Instanciating Pairlist manager\n        :param config: Global bot configuration\n        :param pairlistconfig: Configuration for this pairlist - can be empty.\n        :param pairlist_pos: Position of the filter in the pairlist-filter-list\n        \"\"\"\n        self._exchange = exchange\n        self._pairlistmanager = pairlistmanager\n        self._config = config\n        self._pairlistconfig = pairlistconfig\n        self._pairlist_pos = pairlist_pos\n\n    @property\n    def name(self) -> str:\n        \"\"\"\n        Gets name of the class\n        -> no need to overwrite in subclasses\n        \"\"\"\n        return self.__class__.__name__\n\n    @abstractproperty\n    def needstickers(self) -> bool:\n        \"\"\"\n        Boolean property defining if tickers are necessary.\n        If no Pairlist requries tickers, an empty List is passed\n        as tickers argument to filter_pairlist\n        \"\"\"\n\n    @abstractmethod\n    def short_desc(self) -> str:\n        \"\"\"\n        Short whitelist method description - used for startup-messages\n        -> Please overwrite in subclasses\n        \"\"\"\n\n    @abstractmethod\n    def filter_pairlist(self, pairlist: List[str], tickers: Dict) -> List[str]:\n        \"\"\"\n        Filters and sorts pairlist and returns the whitelist again.\n        Called on each bot iteration - please use internal caching if necessary\n        -> Please overwrite in subclasses\n        :param pairlist: pairlist to filter or sort\n        :param tickers: Tickers (from exchange.get_tickers()). May be cached.\n        :return: new whitelist\n        \"\"\"\n\n    @staticmethod\n    def verify_blacklist(pairlist: List[str], blacklist: List[str],\n                         aswarning: bool) -> List[str]:\n        \"\"\"\n        Verify and remove items from pairlist - returning a filtered pairlist.\n        Logs a warning or info depending on `aswarning`.\n        Pairlists explicitly using this method shall use `aswarning=False`!\n        :param pairlist: Pairlist to validate\n        :param blacklist: Blacklist to validate pairlist against\n        :param aswarning: Log message as Warning or info\n        :return: pairlist - blacklisted pairs\n        \"\"\"\n        for pair in deepcopy(pairlist):\n            if pair in blacklist:\n                if aswarning:\n                    logger.warning(f\"Pair {pair} in your blacklist. Removing it from whitelist...\")\n                else:\n                    logger.info(f\"Pair {pair} in your blacklist. Removing it from whitelist...\")\n                pairlist.remove(pair)\n        return pairlist\n\n    def _verify_blacklist(self, pairlist: List[str], aswarning: bool = True) -> List[str]:\n        \"\"\"\n        Proxy method to verify_blacklist for easy access for child classes.\n        Logs a warning or info depending on `aswarning`.\n        Pairlists explicitly using this method shall use aswarning=False!\n        :param pairlist: Pairlist to validate\n        :param aswarning: Log message as Warning or info.\n        :return: pairlist - blacklisted pairs\n        \"\"\"\n        return IPairList.verify_blacklist(pairlist, self._pairlistmanager.blacklist,\n                                          aswarning=aswarning)\n\n    def _whitelist_for_active_markets(self, pairlist: List[str]) -> List[str]:\n        \"\"\"\n        Check available markets and remove pair from whitelist if necessary\n        :param whitelist: the sorted list of pairs the user might want to trade\n        :return: the list of pairs the user wants to trade without those unavailable or\n        black_listed\n        \"\"\"\n        markets = self._exchange.markets\n\n        sanitized_whitelist: List[str] = []\n        for pair in pairlist:\n            # pair is not in the generated dynamic market or has the wrong stake currency\n            if pair not in markets:\n                logger.warning(f\"Pair {pair} is not compatible with exchange \"\n                               f\"{self._exchange.name}. Removing it from whitelist..\")\n                continue\n\n            if self._exchange.get_pair_quote_currency(pair) != self._config['stake_currency']:\n                logger.warning(f\"Pair {pair} is not compatible with your stake currency \"\n                               f\"{self._config['stake_currency']}. Removing it from whitelist..\")\n                continue\n\n            # Check if market is active\n            market = markets[pair]\n            if not market_is_active(market):\n                logger.info(f\"Ignoring {pair} from whitelist. Market is not active.\")\n                continue\n            if pair not in sanitized_whitelist:\n                sanitized_whitelist.append(pair)\n\n        # We need to remove pairs that are unknown\n        return sanitized_whitelist\n", "path": "freqtrade/pairlist/IPairList.py"}, {"content": "\"\"\"\nVolume PairList provider\n\nProvides lists as configured in config.json\n\n \"\"\"\nimport logging\nfrom datetime import datetime\nfrom typing import Any, Dict, List\n\nfrom freqtrade.exceptions import OperationalException\nfrom freqtrade.pairlist.IPairList import IPairList\n\nlogger = logging.getLogger(__name__)\n\nSORT_VALUES = ['askVolume', 'bidVolume', 'quoteVolume']\n\n\nclass VolumePairList(IPairList):\n\n    def __init__(self, exchange, pairlistmanager, config: Dict[str, Any], pairlistconfig: dict,\n                 pairlist_pos: int) -> None:\n        super().__init__(exchange, pairlistmanager, config, pairlistconfig, pairlist_pos)\n\n        if 'number_assets' not in self._pairlistconfig:\n            raise OperationalException(\n                f'`number_assets` not specified. Please check your configuration '\n                'for \"pairlist.config.number_assets\"')\n        self._number_pairs = self._pairlistconfig['number_assets']\n        self._sort_key = self._pairlistconfig.get('sort_key', 'quoteVolume')\n        self._min_value = self._pairlistconfig.get('min_value', 0)\n        self.refresh_period = self._pairlistconfig.get('refresh_period', 1800)\n\n        if not self._exchange.exchange_has('fetchTickers'):\n            raise OperationalException(\n                'Exchange does not support dynamic whitelist.'\n                'Please edit your config and restart the bot'\n            )\n        if not self._validate_keys(self._sort_key):\n            raise OperationalException(\n                f'key {self._sort_key} not in {SORT_VALUES}')\n        self._last_refresh = 0\n\n    @property\n    def needstickers(self) -> bool:\n        \"\"\"\n        Boolean property defining if tickers are necessary.\n        If no Pairlist requries tickers, an empty List is passed\n        as tickers argument to filter_pairlist\n        \"\"\"\n        return True\n\n    def _validate_keys(self, key):\n        return key in SORT_VALUES\n\n    def short_desc(self) -> str:\n        \"\"\"\n        Short whitelist method description - used for startup-messages\n        \"\"\"\n        return f\"{self.name} - top {self._pairlistconfig['number_assets']} volume pairs.\"\n\n    def filter_pairlist(self, pairlist: List[str], tickers: Dict) -> List[str]:\n        \"\"\"\n        Filters and sorts pairlist and returns the whitelist again.\n        Called on each bot iteration - please use internal caching if necessary\n        :param pairlist: pairlist to filter or sort\n        :param tickers: Tickers (from exchange.get_tickers()). May be cached.\n        :return: new whitelist\n        \"\"\"\n        # Generate dynamic whitelist\n        if self._last_refresh + self.refresh_period < datetime.now().timestamp():\n            self._last_refresh = int(datetime.now().timestamp())\n            return self._gen_pair_whitelist(pairlist,\n                                            tickers,\n                                            self._config['stake_currency'],\n                                            self._sort_key,\n                                            self._min_value\n                                            )\n        else:\n            return pairlist\n\n    def _gen_pair_whitelist(self, pairlist: List[str], tickers: Dict,\n                            base_currency: str, key: str, min_val: int) -> List[str]:\n        \"\"\"\n        Updates the whitelist with with a dynamically generated list\n        :param base_currency: base currency as str\n        :param key: sort key (defaults to 'quoteVolume')\n        :param tickers: Tickers (from exchange.get_tickers()).\n        :return: List of pairs\n        \"\"\"\n\n        if self._pairlist_pos == 0:\n            # If VolumePairList is the first in the list, use fresh pairlist\n            # Check if pair quote currency equals to the stake currency.\n            filtered_tickers = [v for k, v in tickers.items()\n                                if (self._exchange.get_pair_quote_currency(k) == base_currency\n                                    and v[key] is not None)]\n        else:\n            # If other pairlist is in front, use the incomming pairlist.\n            filtered_tickers = [v for k, v in tickers.items() if k in pairlist]\n\n        if min_val > 0:\n            filtered_tickers = list(filter(lambda t: t[key] > min_val, filtered_tickers))\n\n        sorted_tickers = sorted(filtered_tickers, reverse=True, key=lambda t: t[key])\n\n        # Validate whitelist to only have active market pairs\n        pairs = self._whitelist_for_active_markets([s['symbol'] for s in sorted_tickers])\n        pairs = self._verify_blacklist(pairs, aswarning=False)\n        # Limit to X number of pairs\n        pairs = pairs[:self._number_pairs]\n        logger.info(f\"Searching {self._number_pairs} pairs: {pairs}\")\n\n        return pairs\n", "path": "freqtrade/pairlist/VolumePairList.py"}]}