Merge pull request #3339 from hroff-1902/cleanup-pairlistmanager

Cleanup in pairlistmanager
This commit is contained in:
Matthias 2020-05-19 14:04:39 +02:00 committed by GitHub
commit d438af342c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 41 deletions

View File

@ -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):

View File

@ -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'),
exchange=exchange,
pairlistmanager=self,
config=config,
pairlistconfig=pl,
pairlist_pos=len(self._pairlists)
)
self._tickers_needed = pairl.needstickers or self._tickers_needed
self._pairlists.append(pairl)
pairlist_handler = PairListResolver.load_pairlist(
pairlist_handler_config['method'],
exchange=exchange,
pairlistmanager=self,
config=config,
pairlistconfig=pairlist_handler_config,
pairlist_pos=len(self._pairlist_handlers)
)
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:

View File

@ -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)