Merge pull request #3339 from hroff-1902/cleanup-pairlistmanager
Cleanup in pairlistmanager
This commit is contained in:
		| @@ -1,5 +1,5 @@ | ||||
| """ | ||||
| PairList base class | ||||
| PairList Handler base class | ||||
| """ | ||||
| import logging | ||||
| from abc import ABC, abstractmethod, abstractproperty | ||||
| @@ -21,10 +21,10 @@ class IPairList(ABC): | ||||
|                  pairlist_pos: int) -> None: | ||||
|         """ | ||||
|         :param exchange: Exchange instance | ||||
|         :param pairlistmanager: Instanciating Pairlist manager | ||||
|         :param pairlistmanager: Instantiated Pairlist manager | ||||
|         :param config: Global bot configuration | ||||
|         :param pairlistconfig: Configuration for this pairlist - can be empty. | ||||
|         :param pairlist_pos: Position of the filter in the pairlist-filter-list | ||||
|         :param pairlistconfig: Configuration for this Pairlist Handler - can be empty. | ||||
|         :param pairlist_pos: Position of the Pairlist Handler in the chain | ||||
|         """ | ||||
|         self._exchange = exchange | ||||
|         self._pairlistmanager = pairlistmanager | ||||
| @@ -93,10 +93,10 @@ class IPairList(ABC): | ||||
|         """ | ||||
|         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`! | ||||
|         Pairlist Handlers 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 | ||||
|         :param aswarning: Log message as Warning or Info | ||||
|         :return: pairlist - blacklisted pairs | ||||
|         """ | ||||
|         for pair in deepcopy(pairlist): | ||||
|   | ||||
| @@ -23,24 +23,25 @@ class PairListManager(): | ||||
|         self._config = config | ||||
|         self._whitelist = self._config['exchange'].get('pair_whitelist') | ||||
|         self._blacklist = self._config['exchange'].get('pair_blacklist', []) | ||||
|         self._pairlists: List[IPairList] = [] | ||||
|         self._pairlist_handlers: List[IPairList] = [] | ||||
|         self._tickers_needed = False | ||||
|         for pl in self._config.get('pairlists', None): | ||||
|             if 'method' not in pl: | ||||
|                 logger.warning(f"No method in {pl}") | ||||
|         for pairlist_handler_config in self._config.get('pairlists', None): | ||||
|             if 'method' not in pairlist_handler_config: | ||||
|                 logger.warning(f"No method found in {pairlist_handler_config}, ignoring.") | ||||
|                 continue | ||||
|             pairl = PairListResolver.load_pairlist(pl.get('method'), | ||||
|             pairlist_handler = PairListResolver.load_pairlist( | ||||
|                     pairlist_handler_config['method'], | ||||
|                     exchange=exchange, | ||||
|                     pairlistmanager=self, | ||||
|                     config=config, | ||||
|                                                    pairlistconfig=pl, | ||||
|                                                    pairlist_pos=len(self._pairlists) | ||||
|                     pairlistconfig=pairlist_handler_config, | ||||
|                     pairlist_pos=len(self._pairlist_handlers) | ||||
|                     ) | ||||
|             self._tickers_needed = pairl.needstickers or self._tickers_needed | ||||
|             self._pairlists.append(pairl) | ||||
|             self._tickers_needed |= pairlist_handler.needstickers | ||||
|             self._pairlist_handlers.append(pairlist_handler) | ||||
|  | ||||
|         if not self._pairlists: | ||||
|             raise OperationalException("No Pairlist defined!") | ||||
|         if not self._pairlist_handlers: | ||||
|             raise OperationalException("No Pairlist Handlers defined") | ||||
|  | ||||
|     @property | ||||
|     def whitelist(self) -> List[str]: | ||||
| @@ -60,15 +61,15 @@ class PairListManager(): | ||||
|     @property | ||||
|     def name_list(self) -> List[str]: | ||||
|         """ | ||||
|         Get list of loaded pairlists names | ||||
|         Get list of loaded Pairlist Handler names | ||||
|         """ | ||||
|         return [p.name for p in self._pairlists] | ||||
|         return [p.name for p in self._pairlist_handlers] | ||||
|  | ||||
|     def short_desc(self) -> List[Dict]: | ||||
|         """ | ||||
|         List of short_desc for each pairlist | ||||
|         List of short_desc for each Pairlist Handler | ||||
|         """ | ||||
|         return [{p.name: p.short_desc()} for p in self._pairlists] | ||||
|         return [{p.name: p.short_desc()} for p in self._pairlist_handlers] | ||||
|  | ||||
|     @cached(TTLCache(maxsize=1, ttl=1800)) | ||||
|     def _get_cached_tickers(self): | ||||
| @@ -76,7 +77,7 @@ class PairListManager(): | ||||
|  | ||||
|     def refresh_pairlist(self) -> None: | ||||
|         """ | ||||
|         Run pairlist through all configured pairlists. | ||||
|         Run pairlist through all configured Pairlist Handlers. | ||||
|         """ | ||||
|         # Tickers should be cached to avoid calling the exchange on each call. | ||||
|         tickers: Dict = {} | ||||
| @@ -86,19 +87,19 @@ class PairListManager(): | ||||
|         # Adjust whitelist if filters are using tickers | ||||
|         pairlist = self._prepare_whitelist(self._whitelist.copy(), tickers) | ||||
|  | ||||
|         # Process all pairlists in chain | ||||
|         for pl in self._pairlists: | ||||
|             pairlist = pl.filter_pairlist(pairlist, tickers) | ||||
|         # Process all Pairlist Handlers in the chain | ||||
|         for pairlist_handler in self._pairlist_handlers: | ||||
|             pairlist = pairlist_handler.filter_pairlist(pairlist, tickers) | ||||
|  | ||||
|         # Validation against blacklist happens after the pairlists to ensure | ||||
|         # blacklist is respected. | ||||
|         # Validation against blacklist happens after the chain of Pairlist Handlers | ||||
|         # to ensure blacklist is respected. | ||||
|         pairlist = IPairList.verify_blacklist(pairlist, self.blacklist, True) | ||||
|  | ||||
|         self._whitelist = pairlist | ||||
|  | ||||
|     def _prepare_whitelist(self, pairlist: List[str], tickers) -> List[str]: | ||||
|         """ | ||||
|         Prepare sanitized pairlist for Pairlist Filters that use tickers data - remove | ||||
|         Prepare sanitized pairlist for Pairlist Handlers that use tickers data - remove | ||||
|         pairs that do not have ticker available | ||||
|         """ | ||||
|         if self._tickers_needed: | ||||
|   | ||||
| @@ -10,8 +10,6 @@ from freqtrade.pairlist.pairlistmanager import PairListManager | ||||
| from freqtrade.resolvers import PairListResolver | ||||
| from tests.conftest import get_patched_freqtradebot, log_has, log_has_re | ||||
|  | ||||
| # whitelist, blacklist | ||||
|  | ||||
|  | ||||
| @pytest.fixture(scope="function") | ||||
| def whitelist_conf(default_conf): | ||||
| @@ -55,7 +53,7 @@ def test_log_on_refresh(mocker, static_pl_conf, markets, tickers): | ||||
|     freqtrade = get_patched_freqtradebot(mocker, static_pl_conf) | ||||
|     logmock = MagicMock() | ||||
|     # Assign starting whitelist | ||||
|     pl = freqtrade.pairlists._pairlists[0] | ||||
|     pl = freqtrade.pairlists._pairlist_handlers[0] | ||||
|     pl.log_on_refresh(logmock, 'Hello world') | ||||
|     assert logmock.call_count == 1 | ||||
|     pl.log_on_refresh(logmock, 'Hello world') | ||||
| @@ -321,7 +319,8 @@ def test__whitelist_for_active_markets(mocker, whitelist_conf, markets, pairlist | ||||
|     caplog.clear() | ||||
|  | ||||
|     # Assign starting whitelist | ||||
|     new_whitelist = freqtrade.pairlists._pairlists[0]._whitelist_for_active_markets(whitelist) | ||||
|     pairlist_handler = freqtrade.pairlists._pairlist_handlers[0] | ||||
|     new_whitelist = pairlist_handler._whitelist_for_active_markets(whitelist) | ||||
|  | ||||
|     assert set(new_whitelist) == set(['ETH/BTC', 'TKN/BTC']) | ||||
|     assert log_message in caplog.text | ||||
| @@ -344,17 +343,17 @@ def test_volumepairlist_caching(mocker, markets, whitelist_conf, tickers): | ||||
|                           get_tickers=tickers | ||||
|                           ) | ||||
|     freqtrade = get_patched_freqtradebot(mocker, whitelist_conf) | ||||
|     assert freqtrade.pairlists._pairlists[0]._last_refresh == 0 | ||||
|     assert freqtrade.pairlists._pairlist_handlers[0]._last_refresh == 0 | ||||
|     assert tickers.call_count == 0 | ||||
|     freqtrade.pairlists.refresh_pairlist() | ||||
|     assert tickers.call_count == 1 | ||||
|  | ||||
|     assert freqtrade.pairlists._pairlists[0]._last_refresh != 0 | ||||
|     lrf = freqtrade.pairlists._pairlists[0]._last_refresh | ||||
|     assert freqtrade.pairlists._pairlist_handlers[0]._last_refresh != 0 | ||||
|     lrf = freqtrade.pairlists._pairlist_handlers[0]._last_refresh | ||||
|     freqtrade.pairlists.refresh_pairlist() | ||||
|     assert tickers.call_count == 1 | ||||
|     # Time should not be updated. | ||||
|     assert freqtrade.pairlists._pairlists[0]._last_refresh == lrf | ||||
|     assert freqtrade.pairlists._pairlist_handlers[0]._last_refresh == lrf | ||||
|  | ||||
|  | ||||
| def test_pairlistmanager_no_pairlist(mocker, markets, whitelist_conf, caplog): | ||||
| @@ -363,5 +362,5 @@ def test_pairlistmanager_no_pairlist(mocker, markets, whitelist_conf, caplog): | ||||
|     whitelist_conf['pairlists'] = [] | ||||
|  | ||||
|     with pytest.raises(OperationalException, | ||||
|                        match=r"No Pairlist defined!"): | ||||
|                        match=r"No Pairlist Handlers defined"): | ||||
|         get_patched_freqtradebot(mocker, whitelist_conf) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user