From 7ff61f12e99ac67fa61f33e87e06d76e6d303008 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 9 Nov 2019 15:04:04 +0100 Subject: [PATCH] pass pairlist position into the pairlists --- freqtrade/pairlist/IPairList.py | 11 ++++++++++- freqtrade/pairlist/LowPriceFilter.py | 5 +++-- freqtrade/pairlist/StaticPairList.py | 3 --- freqtrade/pairlist/VolumePairList.py | 22 +++++++++++++++------- freqtrade/pairlist/pairlistmanager.py | 11 +++++++---- freqtrade/resolvers/pairlist_resolver.py | 5 +++-- tests/pairlist/test_pairlist.py | 2 +- 7 files changed, 39 insertions(+), 20 deletions(-) diff --git a/freqtrade/pairlist/IPairList.py b/freqtrade/pairlist/IPairList.py index fc4187856..231755cb0 100644 --- a/freqtrade/pairlist/IPairList.py +++ b/freqtrade/pairlist/IPairList.py @@ -16,11 +16,20 @@ logger = logging.getLogger(__name__) class IPairList(ABC): - def __init__(self, exchange, pairlistmanager, config, pairlistconfig: dict) -> None: + def __init__(self, exchange, pairlistmanager, config, pairlistconfig: dict, + pairlist_pos: int) -> None: + """ + :param exchange: Exchange instance + :param pairlistmanager: Instanciating 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 + """ self._exchange = exchange self._pairlistmanager = pairlistmanager self._config = config self._pairlistconfig = pairlistconfig + self._pairlist_pos = pairlist_pos @property def name(self) -> str: diff --git a/freqtrade/pairlist/LowPriceFilter.py b/freqtrade/pairlist/LowPriceFilter.py index 4e1ba52c8..83b6a85e6 100644 --- a/freqtrade/pairlist/LowPriceFilter.py +++ b/freqtrade/pairlist/LowPriceFilter.py @@ -9,8 +9,9 @@ logger = logging.getLogger(__name__) class LowPriceFilter(IPairList): - def __init__(self, exchange, pairlistmanager, config, pairlistconfig: dict) -> None: - super().__init__(exchange, pairlistmanager, config, pairlistconfig) + def __init__(self, exchange, pairlistmanager, config, pairlistconfig: dict, + pairlist_pos: int) -> None: + super().__init__(exchange, pairlistmanager, config, pairlistconfig, pairlist_pos) self._low_price_percent = pairlistconfig.get('low_price_percent', 0) diff --git a/freqtrade/pairlist/StaticPairList.py b/freqtrade/pairlist/StaticPairList.py index a7b71875c..0050fbd5c 100644 --- a/freqtrade/pairlist/StaticPairList.py +++ b/freqtrade/pairlist/StaticPairList.py @@ -14,9 +14,6 @@ logger = logging.getLogger(__name__) class StaticPairList(IPairList): - def __init__(self, exchange, pairlistmanager, config, pairlistconfig: dict) -> None: - super().__init__(exchange, pairlistmanager, config, pairlistconfig) - @property def needstickers(self) -> bool: """ diff --git a/freqtrade/pairlist/VolumePairList.py b/freqtrade/pairlist/VolumePairList.py index 902f7abd4..708c8d7c2 100644 --- a/freqtrade/pairlist/VolumePairList.py +++ b/freqtrade/pairlist/VolumePairList.py @@ -18,8 +18,9 @@ SORT_VALUES = ['askVolume', 'bidVolume', 'quoteVolume'] class VolumePairList(IPairList): - def __init__(self, exchange, pairlistmanager, config, pairlistconfig: dict) -> None: - super().__init__(exchange, pairlistmanager, config, pairlistconfig) + def __init__(self, exchange, pairlistmanager, config, pairlistconfig: dict, + pairlist_pos: int) -> None: + super().__init__(exchange, pairlistmanager, config, pairlistconfig, pairlist_pos) if 'number_assets' not in self._pairlistconfig: raise OperationalException( @@ -85,11 +86,18 @@ class VolumePairList(IPairList): :return: List of pairs """ - # check length so that we make sure that '/' is actually in the string - tickers = [v for k, v in tickers.items() - if (len(k.split('/')) == 2 and k.split('/')[1] == base_currency - and v[key] is not None)] - sorted_tickers = sorted(tickers, reverse=True, key=lambda t: t[key]) + if self._pairlist_pos == 0: + # If VolumePairList is the first in the list, use fresh pairlist + # check length so that we make sure that '/' is actually in the string + filtered_tickers = [v for k, v in tickers.items() + if (len(k.split('/')) == 2 and k.split('/')[1] == base_currency + and v[key] is not None)] + else: + # If other pairlist is in front, use the incomming pairlist. + filtered_tickers = [v for k, v in tickers.items() if k in pairlist] + + sorted_tickers = sorted(filtered_tickers, reverse=True, key=lambda t: t[key]) + # Validate whitelist to only have active market pairs pairs = self._whitelist_for_active_markets([s['symbol'] for s in sorted_tickers]) pairs = self._verify_blacklist(pairs) diff --git a/freqtrade/pairlist/pairlistmanager.py b/freqtrade/pairlist/pairlistmanager.py index f29f89abf..309ada094 100644 --- a/freqtrade/pairlist/pairlistmanager.py +++ b/freqtrade/pairlist/pairlistmanager.py @@ -23,14 +23,17 @@ class PairListManager(): self._blacklist = self._config['exchange'].get('pair_blacklist', []) self._pairlists: 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}") continue pairl = PairListResolver(pl.get('method'), - exchange, self, config, - pl.get('config')).pairlist + exchange=exchange, + pairlistmanager=self, + config=config, + pairlistconfig=pl.get('config'), + pairlist_pos=len(self._pairlists) + ).pairlist self._tickers_needed = pairl.needstickers or self._tickers_needed self._pairlists.append(pairl) @@ -67,7 +70,7 @@ class PairListManager(): def refresh_pairlist(self) -> None: """ - Run pairlist through all pairlists. + Run pairlist through all configured pairlists. """ pairlist = self._whitelist.copy() diff --git a/freqtrade/resolvers/pairlist_resolver.py b/freqtrade/resolvers/pairlist_resolver.py index 9e051fa8f..d849f4ffb 100644 --- a/freqtrade/resolvers/pairlist_resolver.py +++ b/freqtrade/resolvers/pairlist_resolver.py @@ -21,7 +21,7 @@ class PairListResolver(IResolver): __slots__ = ['pairlist'] def __init__(self, pairlist_name: str, exchange, pairlistmanager, - config: dict, pairlistconfig) -> None: + config: dict, pairlistconfig: dict, pairlist_pos: int) -> None: """ Load the custom class from config parameter :param config: configuration dictionary or None @@ -30,7 +30,8 @@ class PairListResolver(IResolver): kwargs={'exchange': exchange, 'pairlistmanager': pairlistmanager, 'config': config, - 'pairlistconfig': pairlistconfig}) + 'pairlistconfig': pairlistconfig, + 'pairlist_pos': pairlist_pos}) def _load_pairlist( self, pairlist_name: str, config: dict, kwargs: dict) -> IPairList: diff --git a/tests/pairlist/test_pairlist.py b/tests/pairlist/test_pairlist.py index 017f78561..c322dd8c4 100644 --- a/tests/pairlist/test_pairlist.py +++ b/tests/pairlist/test_pairlist.py @@ -55,7 +55,7 @@ def test_load_pairlist_noexist(mocker, markets, default_conf): with pytest.raises(OperationalException, match=r"Impossible to load Pairlist 'NonexistingPairList'. " r"This class does not exist or contains Python code errors."): - PairListResolver('NonexistingPairList', bot.exchange, plm, default_conf, {}) + PairListResolver('NonexistingPairList', bot.exchange, plm, default_conf, {}, 1) def test_refresh_market_pair_not_in_whitelist(mocker, markets, static_pl_conf):