Cleanup in pairlistmanager

This commit is contained in:
hroff-1902 2020-05-19 03:35:01 +03:00
parent 63b6f171f9
commit 4c4fb0c9be
3 changed files with 41 additions and 41 deletions

View File

@ -1,5 +1,5 @@
""" """
PairList base class PairList Handler base class
""" """
import logging import logging
from abc import ABC, abstractmethod, abstractproperty from abc import ABC, abstractmethod, abstractproperty
@ -21,10 +21,10 @@ class IPairList(ABC):
pairlist_pos: int) -> None: pairlist_pos: int) -> None:
""" """
:param exchange: Exchange instance :param exchange: Exchange instance
:param pairlistmanager: Instanciating Pairlist manager :param pairlistmanager: Instantiated Pairlist manager
:param config: Global bot configuration :param config: Global bot configuration
:param pairlistconfig: Configuration for this pairlist - can be empty. :param pairlistconfig: Configuration for this Pairlist Handler - can be empty.
:param pairlist_pos: Position of the filter in the pairlist-filter-list :param pairlist_pos: Position of the Pairlist Handler in the chain
""" """
self._exchange = exchange self._exchange = exchange
self._pairlistmanager = pairlistmanager self._pairlistmanager = pairlistmanager
@ -93,10 +93,10 @@ class IPairList(ABC):
""" """
Verify and remove items from pairlist - returning a filtered pairlist. Verify and remove items from pairlist - returning a filtered pairlist.
Logs a warning or info depending on `aswarning`. 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 pairlist: Pairlist to validate
:param blacklist: Blacklist to validate pairlist against :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 :return: pairlist - blacklisted pairs
""" """
for pair in deepcopy(pairlist): for pair in deepcopy(pairlist):

View File

@ -23,24 +23,25 @@ class PairListManager():
self._config = config self._config = config
self._whitelist = self._config['exchange'].get('pair_whitelist') self._whitelist = self._config['exchange'].get('pair_whitelist')
self._blacklist = self._config['exchange'].get('pair_blacklist', []) self._blacklist = self._config['exchange'].get('pair_blacklist', [])
self._pairlists: List[IPairList] = [] self._pairlist_handlers: List[IPairList] = []
self._tickers_needed = False self._tickers_needed = False
for pl in self._config.get('pairlists', None): for pairlist_handler_config in self._config.get('pairlists', None):
if 'method' not in pl: if 'method' not in pairlist_handler_config:
logger.warning(f"No method in {pl}") logger.warning(f"No method found in {pairlist_handler_config}, ignoring.")
continue continue
pairl = PairListResolver.load_pairlist(pl.get('method'), pairlist_handler = PairListResolver.load_pairlist(
pairlist_handler_config['method'],
exchange=exchange, exchange=exchange,
pairlistmanager=self, pairlistmanager=self,
config=config, config=config,
pairlistconfig=pl, pairlistconfig=pairlist_handler_config,
pairlist_pos=len(self._pairlists) pairlist_pos=len(self._pairlist_handlers)
) )
self._tickers_needed = pairl.needstickers or self._tickers_needed self._tickers_needed |= pairlist_handler.needstickers
self._pairlists.append(pairl) self._pairlist_handlers.append(pairlist_handler)
if not self._pairlists: if not self._pairlist_handlers:
raise OperationalException("No Pairlist defined!") raise OperationalException("No Pairlist Handlers defined")
@property @property
def whitelist(self) -> List[str]: def whitelist(self) -> List[str]:
@ -60,15 +61,15 @@ class PairListManager():
@property @property
def name_list(self) -> List[str]: 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]: 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)) @cached(TTLCache(maxsize=1, ttl=1800))
def _get_cached_tickers(self): def _get_cached_tickers(self):
@ -76,7 +77,7 @@ class PairListManager():
def refresh_pairlist(self) -> None: 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 should be cached to avoid calling the exchange on each call.
tickers: Dict = {} tickers: Dict = {}
@ -86,19 +87,19 @@ class PairListManager():
# Adjust whitelist if filters are using tickers # Adjust whitelist if filters are using tickers
pairlist = self._prepare_whitelist(self._whitelist.copy(), tickers) pairlist = self._prepare_whitelist(self._whitelist.copy(), tickers)
# Process all pairlists in chain # Process all Pairlist Handlers in the chain
for pl in self._pairlists: for pairlist_handler in self._pairlist_handlers:
pairlist = pl.filter_pairlist(pairlist, tickers) pairlist = pairlist_handler.filter_pairlist(pairlist, tickers)
# Validation against blacklist happens after the pairlists to ensure # Validation against blacklist happens after the chain of Pairlist Handlers
# blacklist is respected. # to ensure blacklist is respected.
pairlist = IPairList.verify_blacklist(pairlist, self.blacklist, True) pairlist = IPairList.verify_blacklist(pairlist, self.blacklist, True)
self._whitelist = pairlist self._whitelist = pairlist
def _prepare_whitelist(self, pairlist: List[str], tickers) -> List[str]: 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 pairs that do not have ticker available
""" """
if self._tickers_needed: if self._tickers_needed:

View File

@ -10,8 +10,6 @@ from freqtrade.pairlist.pairlistmanager import PairListManager
from freqtrade.resolvers import PairListResolver from freqtrade.resolvers import PairListResolver
from tests.conftest import get_patched_freqtradebot, log_has, log_has_re from tests.conftest import get_patched_freqtradebot, log_has, log_has_re
# whitelist, blacklist
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def whitelist_conf(default_conf): 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) freqtrade = get_patched_freqtradebot(mocker, static_pl_conf)
logmock = MagicMock() logmock = MagicMock()
# Assign starting whitelist # Assign starting whitelist
pl = freqtrade.pairlists._pairlists[0] pl = freqtrade.pairlists._pairlist_handlers[0]
pl.log_on_refresh(logmock, 'Hello world') pl.log_on_refresh(logmock, 'Hello world')
assert logmock.call_count == 1 assert logmock.call_count == 1
pl.log_on_refresh(logmock, 'Hello world') pl.log_on_refresh(logmock, 'Hello world')
@ -290,7 +288,8 @@ def test__whitelist_for_active_markets(mocker, whitelist_conf, markets, pairlist
caplog.clear() caplog.clear()
# Assign starting whitelist # 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 set(new_whitelist) == set(['ETH/BTC', 'TKN/BTC'])
assert log_message in caplog.text assert log_message in caplog.text
@ -313,17 +312,17 @@ def test_volumepairlist_caching(mocker, markets, whitelist_conf, tickers):
get_tickers=tickers get_tickers=tickers
) )
freqtrade = get_patched_freqtradebot(mocker, whitelist_conf) 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 assert tickers.call_count == 0
freqtrade.pairlists.refresh_pairlist() freqtrade.pairlists.refresh_pairlist()
assert tickers.call_count == 1 assert tickers.call_count == 1
assert freqtrade.pairlists._pairlists[0]._last_refresh != 0 assert freqtrade.pairlists._pairlist_handlers[0]._last_refresh != 0
lrf = freqtrade.pairlists._pairlists[0]._last_refresh lrf = freqtrade.pairlists._pairlist_handlers[0]._last_refresh
freqtrade.pairlists.refresh_pairlist() freqtrade.pairlists.refresh_pairlist()
assert tickers.call_count == 1 assert tickers.call_count == 1
# Time should not be updated. # 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): def test_pairlistmanager_no_pairlist(mocker, markets, whitelist_conf, caplog):
@ -332,5 +331,5 @@ def test_pairlistmanager_no_pairlist(mocker, markets, whitelist_conf, caplog):
whitelist_conf['pairlists'] = [] whitelist_conf['pairlists'] = []
with pytest.raises(OperationalException, with pytest.raises(OperationalException,
match=r"No Pairlist defined!"): match=r"No Pairlist Handlers defined"):
get_patched_freqtradebot(mocker, whitelist_conf) get_patched_freqtradebot(mocker, whitelist_conf)