We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
`test-pairlist` fails if no markets loaded
`test-pairlist` fails in unexpected way if markets were not able to be loaded (due to 4xx error, for example);

This should be handled gracefully with a DependencyException (for example, or OperationalException) exception raised, an error message and exit code 1, it should not crash with traceback.

```
$ freqtrade test-pairlist -c config_kraken.json
2020-06-09 12:46:47,312 - freqtrade.loggers - INFO - Verbosity set to 0
2020-06-09 12:46:47,312 - freqtrade.configuration.configuration - INFO - Using user-data directory: /home/user/freqtrade-wrk/github-hroff-1902/freqtrade/user_data ...
2020-06-09 12:46:47,313 - freqtrade.configuration.configuration - INFO - Using data directory: /home/user/freqtrade-wrk/github-hroff-1902/freqtrade/user_data/data/kraken ...
2020-06-09 12:46:47,313 - freqtrade.configuration.check_exchange - INFO - Checking exchange...
2020-06-09 12:46:47,313 - freqtrade.configuration.check_exchange - INFO - Exchange "kraken" is officially supported by the Freqtrade development team.
2020-06-09 12:46:47,313 - freqtrade.configuration.configuration - INFO - Using pairlist from configuration.
2020-06-09 12:46:47,313 - freqtrade.configuration.config_validation - INFO - Validating configuration ...
2020-06-09 12:46:47,315 - freqtrade.exchange.exchange - INFO - Instance is running with dry_run enabled
2020-06-09 12:46:47,315 - freqtrade.exchange.exchange - INFO - Applying additional ccxt config: {'enableRateLimit': True}
2020-06-09 12:46:47,317 - freqtrade.exchange.exchange - INFO - Applying additional ccxt config: {'enableRateLimit': True, 'rateLimit': 3100}
2020-06-09 12:46:47,320 - freqtrade.exchange.exchange - INFO - Using Exchange "Kraken"
2020-06-09 12:46:47,320 - freqtrade.resolvers.exchange_resolver - INFO - Using resolved exchange 'Kraken'...
2020-06-09 12:46:47,324 - freqtrade.resolvers.iresolver - INFO - Using resolved pairlist StaticPairList from '/home/user/freqtrade-wrk/github-hroff-1902/freqtrade/freqtrade/pairlist/StaticPairList.py'...
2020-06-09 12:46:47,324 - freqtrade.exchange.exchange - WARNING - Markets were not loaded. Loading them now..
2020-06-09 12:46:53,817 - freqtrade.exchange.exchange - WARNING - Unable to initialize markets. Reason: GET https://kraken.zendesk.com/api/v2/help_center/en-us/articles/205893708 429 Too Many Requests Number of allowed API requests per minute exceeded
2020-06-09 12:46:53,818 - freqtrade - ERROR - Fatal exception!
Traceback (most recent call last):
  File "/home/user/freqtrade-wrk/github-hroff-1902/freqtrade/freqtrade/main.py", line 36, in main
    return_code = args['func'](args)
  File "/home/user/freqtrade-wrk/github-hroff-1902/freqtrade/freqtrade/commands/pairlist_commands.py", line 30, in start_test_pairlist
    pairlists.refresh_pairlist()
  File "/home/user/freqtrade-wrk/github-hroff-1902/freqtrade/freqtrade/pairlist/pairlistmanager.py", line 91, in refresh_pairlist
    pairlist = self._pairlist_handlers[0].gen_pairlist(self._whitelist, tickers)
  File "/home/user/freqtrade-wrk/github-hroff-1902/freqtrade/freqtrade/pairlist/StaticPairList.py", line 50, in gen_pairlist
    return self._whitelist_for_active_markets(self._config['exchange']['pair_whitelist'])
  File "/home/user/freqtrade-wrk/github-hroff-1902/freqtrade/freqtrade/pairlist/IPairList.py", line 157, in _whitelist_for_active_markets
    if pair not in markets:
TypeError: argument of type 'NoneType' is not iterable
```

--- 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/IPairList.py`
Content:
```
1 """
2 PairList Handler base class
3 """
4 import logging
5 from abc import ABC, abstractmethod, abstractproperty
6 from copy import deepcopy
7 from typing import Any, Dict, List
8 
9 from cachetools import TTLCache, cached
10 
11 from freqtrade.exceptions import OperationalException
12 from freqtrade.exchange import market_is_active
13 
14 
15 logger = logging.getLogger(__name__)
16 
17 
18 class IPairList(ABC):
19 
20     def __init__(self, exchange, pairlistmanager,
21                  config: Dict[str, Any], pairlistconfig: Dict[str, Any],
22                  pairlist_pos: int) -> None:
23         """
24         :param exchange: Exchange instance
25         :param pairlistmanager: Instantiated Pairlist manager
26         :param config: Global bot configuration
27         :param pairlistconfig: Configuration for this Pairlist Handler - can be empty.
28         :param pairlist_pos: Position of the Pairlist Handler in the chain
29         """
30         self._enabled = True
31 
32         self._exchange = exchange
33         self._pairlistmanager = pairlistmanager
34         self._config = config
35         self._pairlistconfig = pairlistconfig
36         self._pairlist_pos = pairlist_pos
37         self.refresh_period = self._pairlistconfig.get('refresh_period', 1800)
38         self._last_refresh = 0
39         self._log_cache = TTLCache(maxsize=1024, ttl=self.refresh_period)
40 
41     @property
42     def name(self) -> str:
43         """
44         Gets name of the class
45         -> no need to overwrite in subclasses
46         """
47         return self.__class__.__name__
48 
49     def log_on_refresh(self, logmethod, message: str) -> None:
50         """
51         Logs message - not more often than "refresh_period" to avoid log spamming
52         Logs the log-message as debug as well to simplify debugging.
53         :param logmethod: Function that'll be called. Most likely `logger.info`.
54         :param message: String containing the message to be sent to the function.
55         :return: None.
56         """
57 
58         @cached(cache=self._log_cache)
59         def _log_on_refresh(message: str):
60             logmethod(message)
61 
62         # Log as debug first
63         logger.debug(message)
64         # Call hidden function.
65         _log_on_refresh(message)
66 
67     @abstractproperty
68     def needstickers(self) -> bool:
69         """
70         Boolean property defining if tickers are necessary.
71         If no Pairlist requries tickers, an empty List is passed
72         as tickers argument to filter_pairlist
73         """
74 
75     @abstractmethod
76     def short_desc(self) -> str:
77         """
78         Short whitelist method description - used for startup-messages
79         -> Please overwrite in subclasses
80         """
81 
82     def _validate_pair(self, ticker) -> bool:
83         """
84         Check one pair against Pairlist Handler's specific conditions.
85 
86         Either implement it in the Pairlist Handler or override the generic
87         filter_pairlist() method.
88 
89         :param ticker: ticker dict as returned from ccxt.load_markets()
90         :return: True if the pair can stay, false if it should be removed
91         """
92         raise NotImplementedError()
93 
94     def gen_pairlist(self, cached_pairlist: List[str], tickers: Dict) -> List[str]:
95         """
96         Generate the pairlist.
97 
98         This method is called once by the pairlistmanager in the refresh_pairlist()
99         method to supply the starting pairlist for the chain of the Pairlist Handlers.
100         Pairlist Filters (those Pairlist Handlers that cannot be used at the first
101         position in the chain) shall not override this base implementation --
102         it will raise the exception if a Pairlist Handler is used at the first
103         position in the chain.
104 
105         :param cached_pairlist: Previously generated pairlist (cached)
106         :param tickers: Tickers (from exchange.get_tickers()).
107         :return: List of pairs
108         """
109         raise OperationalException("This Pairlist Handler should not be used "
110                                    "at the first position in the list of Pairlist Handlers.")
111 
112     def filter_pairlist(self, pairlist: List[str], tickers: Dict) -> List[str]:
113         """
114         Filters and sorts pairlist and returns the whitelist again.
115 
116         Called on each bot iteration - please use internal caching if necessary
117         This generic implementation calls self._validate_pair() for each pair
118         in the pairlist.
119 
120         Some Pairlist Handlers override this generic implementation and employ
121         own filtration.
122 
123         :param pairlist: pairlist to filter or sort
124         :param tickers: Tickers (from exchange.get_tickers()). May be cached.
125         :return: new whitelist
126         """
127         if self._enabled:
128             # Copy list since we're modifying this list
129             for p in deepcopy(pairlist):
130                 # Filter out assets
131                 if not self._validate_pair(tickers[p]):
132                     pairlist.remove(p)
133 
134         return pairlist
135 
136     def verify_blacklist(self, pairlist: List[str], logmethod) -> List[str]:
137         """
138         Proxy method to verify_blacklist for easy access for child classes.
139         :param pairlist: Pairlist to validate
140         :param logmethod: Function that'll be called, `logger.info` or `logger.warning`.
141         :return: pairlist - blacklisted pairs
142         """
143         return self._pairlistmanager.verify_blacklist(pairlist, logmethod)
144 
145     def _whitelist_for_active_markets(self, pairlist: List[str]) -> List[str]:
146         """
147         Check available markets and remove pair from whitelist if necessary
148         :param whitelist: the sorted list of pairs the user might want to trade
149         :return: the list of pairs the user wants to trade without those unavailable or
150         black_listed
151         """
152         markets = self._exchange.markets
153 
154         sanitized_whitelist: List[str] = []
155         for pair in pairlist:
156             # pair is not in the generated dynamic market or has the wrong stake currency
157             if pair not in markets:
158                 logger.warning(f"Pair {pair} is not compatible with exchange "
159                                f"{self._exchange.name}. Removing it from whitelist..")
160                 continue
161 
162             if self._exchange.get_pair_quote_currency(pair) != self._config['stake_currency']:
163                 logger.warning(f"Pair {pair} is not compatible with your stake currency "
164                                f"{self._config['stake_currency']}. Removing it from whitelist..")
165                 continue
166 
167             # Check if market is active
168             market = markets[pair]
169             if not market_is_active(market):
170                 logger.info(f"Ignoring {pair} from whitelist. Market is not active.")
171                 continue
172             if pair not in sanitized_whitelist:
173                 sanitized_whitelist.append(pair)
174 
175         # We need to remove pairs that are unknown
176         return sanitized_whitelist
177
```
--- 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
@@ -150,6 +150,9 @@
         black_listed
         """
         markets = self._exchange.markets
+        if not markets:
+            raise OperationalException(
+                    'Markets not loaded. Make sure that exchange is initialized correctly.')
 
         sanitized_whitelist: List[str] = []
         for pair in 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@@ -150,6 +150,9 @@\n         black_listed\n         \"\"\"\n         markets = self._exchange.markets\n+        if not markets:\n+            raise OperationalException(\n+                    'Markets not loaded. Make sure that exchange is initialized correctly.')\n \n         sanitized_whitelist: List[str] = []\n         for pair in pairlist:\n", "issue": "`test-pairlist` fails if no markets loaded\n`test-pairlist` fails in unexpected way if markets were not able to be loaded (due to 4xx error, for example);\r\n\r\nThis should be handled gracefully with a DependencyException (for example, or OperationalException) exception raised, an error message and exit code 1, it should not crash with traceback.\r\n\r\n```\r\n$ freqtrade test-pairlist -c config_kraken.json\r\n2020-06-09 12:46:47,312 - freqtrade.loggers - INFO - Verbosity set to 0\r\n2020-06-09 12:46:47,312 - freqtrade.configuration.configuration - INFO - Using user-data directory: /home/user/freqtrade-wrk/github-hroff-1902/freqtrade/user_data ...\r\n2020-06-09 12:46:47,313 - freqtrade.configuration.configuration - INFO - Using data directory: /home/user/freqtrade-wrk/github-hroff-1902/freqtrade/user_data/data/kraken ...\r\n2020-06-09 12:46:47,313 - freqtrade.configuration.check_exchange - INFO - Checking exchange...\r\n2020-06-09 12:46:47,313 - freqtrade.configuration.check_exchange - INFO - Exchange \"kraken\" is officially supported by the Freqtrade development team.\r\n2020-06-09 12:46:47,313 - freqtrade.configuration.configuration - INFO - Using pairlist from configuration.\r\n2020-06-09 12:46:47,313 - freqtrade.configuration.config_validation - INFO - Validating configuration ...\r\n2020-06-09 12:46:47,315 - freqtrade.exchange.exchange - INFO - Instance is running with dry_run enabled\r\n2020-06-09 12:46:47,315 - freqtrade.exchange.exchange - INFO - Applying additional ccxt config: {'enableRateLimit': True}\r\n2020-06-09 12:46:47,317 - freqtrade.exchange.exchange - INFO - Applying additional ccxt config: {'enableRateLimit': True, 'rateLimit': 3100}\r\n2020-06-09 12:46:47,320 - freqtrade.exchange.exchange - INFO - Using Exchange \"Kraken\"\r\n2020-06-09 12:46:47,320 - freqtrade.resolvers.exchange_resolver - INFO - Using resolved exchange 'Kraken'...\r\n2020-06-09 12:46:47,324 - freqtrade.resolvers.iresolver - INFO - Using resolved pairlist StaticPairList from '/home/user/freqtrade-wrk/github-hroff-1902/freqtrade/freqtrade/pairlist/StaticPairList.py'...\r\n2020-06-09 12:46:47,324 - freqtrade.exchange.exchange - WARNING - Markets were not loaded. Loading them now..\r\n2020-06-09 12:46:53,817 - freqtrade.exchange.exchange - WARNING - Unable to initialize markets. Reason: GET https://kraken.zendesk.com/api/v2/help_center/en-us/articles/205893708 429 Too Many Requests Number of allowed API requests per minute exceeded\r\n2020-06-09 12:46:53,818 - freqtrade - ERROR - Fatal exception!\r\nTraceback (most recent call last):\r\n  File \"/home/user/freqtrade-wrk/github-hroff-1902/freqtrade/freqtrade/main.py\", line 36, in main\r\n    return_code = args['func'](args)\r\n  File \"/home/user/freqtrade-wrk/github-hroff-1902/freqtrade/freqtrade/commands/pairlist_commands.py\", line 30, in start_test_pairlist\r\n    pairlists.refresh_pairlist()\r\n  File \"/home/user/freqtrade-wrk/github-hroff-1902/freqtrade/freqtrade/pairlist/pairlistmanager.py\", line 91, in refresh_pairlist\r\n    pairlist = self._pairlist_handlers[0].gen_pairlist(self._whitelist, tickers)\r\n  File \"/home/user/freqtrade-wrk/github-hroff-1902/freqtrade/freqtrade/pairlist/StaticPairList.py\", line 50, in gen_pairlist\r\n    return self._whitelist_for_active_markets(self._config['exchange']['pair_whitelist'])\r\n  File \"/home/user/freqtrade-wrk/github-hroff-1902/freqtrade/freqtrade/pairlist/IPairList.py\", line 157, in _whitelist_for_active_markets\r\n    if pair not in markets:\r\nTypeError: argument of type 'NoneType' is not iterable\r\n```\n", "before_files": [{"content": "\"\"\"\nPairList Handler base class\n\"\"\"\nimport logging\nfrom abc import ABC, abstractmethod, abstractproperty\nfrom copy import deepcopy\nfrom typing import Any, Dict, List\n\nfrom cachetools import TTLCache, cached\n\nfrom freqtrade.exceptions import OperationalException\nfrom freqtrade.exchange import market_is_active\n\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: Instantiated Pairlist manager\n        :param config: Global bot configuration\n        :param pairlistconfig: Configuration for this Pairlist Handler - can be empty.\n        :param pairlist_pos: Position of the Pairlist Handler in the chain\n        \"\"\"\n        self._enabled = True\n\n        self._exchange = exchange\n        self._pairlistmanager = pairlistmanager\n        self._config = config\n        self._pairlistconfig = pairlistconfig\n        self._pairlist_pos = pairlist_pos\n        self.refresh_period = self._pairlistconfig.get('refresh_period', 1800)\n        self._last_refresh = 0\n        self._log_cache = TTLCache(maxsize=1024, ttl=self.refresh_period)\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    def log_on_refresh(self, logmethod, message: str) -> None:\n        \"\"\"\n        Logs message - not more often than \"refresh_period\" to avoid log spamming\n        Logs the log-message as debug as well to simplify debugging.\n        :param logmethod: Function that'll be called. Most likely `logger.info`.\n        :param message: String containing the message to be sent to the function.\n        :return: None.\n        \"\"\"\n\n        @cached(cache=self._log_cache)\n        def _log_on_refresh(message: str):\n            logmethod(message)\n\n        # Log as debug first\n        logger.debug(message)\n        # Call hidden function.\n        _log_on_refresh(message)\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    def _validate_pair(self, ticker) -> bool:\n        \"\"\"\n        Check one pair against Pairlist Handler's specific conditions.\n\n        Either implement it in the Pairlist Handler or override the generic\n        filter_pairlist() method.\n\n        :param ticker: ticker dict as returned from ccxt.load_markets()\n        :return: True if the pair can stay, false if it should be removed\n        \"\"\"\n        raise NotImplementedError()\n\n    def gen_pairlist(self, cached_pairlist: List[str], tickers: Dict) -> List[str]:\n        \"\"\"\n        Generate the pairlist.\n\n        This method is called once by the pairlistmanager in the refresh_pairlist()\n        method to supply the starting pairlist for the chain of the Pairlist Handlers.\n        Pairlist Filters (those Pairlist Handlers that cannot be used at the first\n        position in the chain) shall not override this base implementation --\n        it will raise the exception if a Pairlist Handler is used at the first\n        position in the chain.\n\n        :param cached_pairlist: Previously generated pairlist (cached)\n        :param tickers: Tickers (from exchange.get_tickers()).\n        :return: List of pairs\n        \"\"\"\n        raise OperationalException(\"This Pairlist Handler should not be used \"\n                                   \"at the first position in the list of Pairlist Handlers.\")\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\n        Called on each bot iteration - please use internal caching if necessary\n        This generic implementation calls self._validate_pair() for each pair\n        in the pairlist.\n\n        Some Pairlist Handlers override this generic implementation and employ\n        own filtration.\n\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        if self._enabled:\n            # Copy list since we're modifying this list\n            for p in deepcopy(pairlist):\n                # Filter out assets\n                if not self._validate_pair(tickers[p]):\n                    pairlist.remove(p)\n\n        return pairlist\n\n    def verify_blacklist(self, pairlist: List[str], logmethod) -> List[str]:\n        \"\"\"\n        Proxy method to verify_blacklist for easy access for child classes.\n        :param pairlist: Pairlist to validate\n        :param logmethod: Function that'll be called, `logger.info` or `logger.warning`.\n        :return: pairlist - blacklisted pairs\n        \"\"\"\n        return self._pairlistmanager.verify_blacklist(pairlist, logmethod)\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"}], "after_files": [{"content": "\"\"\"\nPairList Handler base class\n\"\"\"\nimport logging\nfrom abc import ABC, abstractmethod, abstractproperty\nfrom copy import deepcopy\nfrom typing import Any, Dict, List\n\nfrom cachetools import TTLCache, cached\n\nfrom freqtrade.exceptions import OperationalException\nfrom freqtrade.exchange import market_is_active\n\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: Instantiated Pairlist manager\n        :param config: Global bot configuration\n        :param pairlistconfig: Configuration for this Pairlist Handler - can be empty.\n        :param pairlist_pos: Position of the Pairlist Handler in the chain\n        \"\"\"\n        self._enabled = True\n\n        self._exchange = exchange\n        self._pairlistmanager = pairlistmanager\n        self._config = config\n        self._pairlistconfig = pairlistconfig\n        self._pairlist_pos = pairlist_pos\n        self.refresh_period = self._pairlistconfig.get('refresh_period', 1800)\n        self._last_refresh = 0\n        self._log_cache = TTLCache(maxsize=1024, ttl=self.refresh_period)\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    def log_on_refresh(self, logmethod, message: str) -> None:\n        \"\"\"\n        Logs message - not more often than \"refresh_period\" to avoid log spamming\n        Logs the log-message as debug as well to simplify debugging.\n        :param logmethod: Function that'll be called. Most likely `logger.info`.\n        :param message: String containing the message to be sent to the function.\n        :return: None.\n        \"\"\"\n\n        @cached(cache=self._log_cache)\n        def _log_on_refresh(message: str):\n            logmethod(message)\n\n        # Log as debug first\n        logger.debug(message)\n        # Call hidden function.\n        _log_on_refresh(message)\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    def _validate_pair(self, ticker) -> bool:\n        \"\"\"\n        Check one pair against Pairlist Handler's specific conditions.\n\n        Either implement it in the Pairlist Handler or override the generic\n        filter_pairlist() method.\n\n        :param ticker: ticker dict as returned from ccxt.load_markets()\n        :return: True if the pair can stay, false if it should be removed\n        \"\"\"\n        raise NotImplementedError()\n\n    def gen_pairlist(self, cached_pairlist: List[str], tickers: Dict) -> List[str]:\n        \"\"\"\n        Generate the pairlist.\n\n        This method is called once by the pairlistmanager in the refresh_pairlist()\n        method to supply the starting pairlist for the chain of the Pairlist Handlers.\n        Pairlist Filters (those Pairlist Handlers that cannot be used at the first\n        position in the chain) shall not override this base implementation --\n        it will raise the exception if a Pairlist Handler is used at the first\n        position in the chain.\n\n        :param cached_pairlist: Previously generated pairlist (cached)\n        :param tickers: Tickers (from exchange.get_tickers()).\n        :return: List of pairs\n        \"\"\"\n        raise OperationalException(\"This Pairlist Handler should not be used \"\n                                   \"at the first position in the list of Pairlist Handlers.\")\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\n        Called on each bot iteration - please use internal caching if necessary\n        This generic implementation calls self._validate_pair() for each pair\n        in the pairlist.\n\n        Some Pairlist Handlers override this generic implementation and employ\n        own filtration.\n\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        if self._enabled:\n            # Copy list since we're modifying this list\n            for p in deepcopy(pairlist):\n                # Filter out assets\n                if not self._validate_pair(tickers[p]):\n                    pairlist.remove(p)\n\n        return pairlist\n\n    def verify_blacklist(self, pairlist: List[str], logmethod) -> List[str]:\n        \"\"\"\n        Proxy method to verify_blacklist for easy access for child classes.\n        :param pairlist: Pairlist to validate\n        :param logmethod: Function that'll be called, `logger.info` or `logger.warning`.\n        :return: pairlist - blacklisted pairs\n        \"\"\"\n        return self._pairlistmanager.verify_blacklist(pairlist, logmethod)\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        if not markets:\n            raise OperationalException(\n                    'Markets not loaded. Make sure that exchange is initialized correctly.')\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"}]}