Cleanup in pairlistmanager
This commit is contained in:
parent
63b6f171f9
commit
4c4fb0c9be
@ -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):
|
||||||
|
@ -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(
|
||||||
exchange=exchange,
|
pairlist_handler_config['method'],
|
||||||
pairlistmanager=self,
|
exchange=exchange,
|
||||||
config=config,
|
pairlistmanager=self,
|
||||||
pairlistconfig=pl,
|
config=config,
|
||||||
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:
|
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:
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user