From 4940fa7be3520e6096ccbd6f7231d0eb6b9b128b Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 18 Sep 2022 15:29:57 +0200 Subject: [PATCH] Add Producer Pairlist --- freqtrade/constants.py | 2 +- .../plugins/pairlist/ProducerPairList.py | 87 +++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 freqtrade/plugins/pairlist/ProducerPairList.py diff --git a/freqtrade/constants.py b/freqtrade/constants.py index 4c2bd6e18..e0e42c821 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -31,7 +31,7 @@ HYPEROPT_LOSS_BUILTIN = ['ShortTradeDurHyperOptLoss', 'OnlyProfitHyperOptLoss', 'CalmarHyperOptLoss', 'MaxDrawDownHyperOptLoss', 'MaxDrawDownRelativeHyperOptLoss', 'ProfitDrawDownHyperOptLoss'] -AVAILABLE_PAIRLISTS = ['StaticPairList', 'VolumePairList', +AVAILABLE_PAIRLISTS = ['StaticPairList', 'VolumePairList', 'ProducerPairList', 'AgeFilter', 'OffsetFilter', 'PerformanceFilter', 'PrecisionFilter', 'PriceFilter', 'RangeStabilityFilter', 'ShuffleFilter', 'SpreadFilter', 'VolatilityFilter'] diff --git a/freqtrade/plugins/pairlist/ProducerPairList.py b/freqtrade/plugins/pairlist/ProducerPairList.py new file mode 100644 index 000000000..81320f713 --- /dev/null +++ b/freqtrade/plugins/pairlist/ProducerPairList.py @@ -0,0 +1,87 @@ +""" +External Pair List provider + +Provides pair list from Leader data +""" +import logging +from typing import Any, Dict, List, Optional + +from freqtrade.plugins.pairlist.IPairList import IPairList + + +logger = logging.getLogger(__name__) + + +class ProducerPairList(IPairList): + """ + PairList plugin for use with external_message_consumer. + Will use pairs given from leader data. + + Usage: + "pairlists": [ + { + "method": "ProducerPairList", + "number_assets": 5, + "producer_name": "default", + } + ], + """ + + def __init__(self, exchange, pairlistmanager, + config: Dict[str, Any], pairlistconfig: Dict[str, Any], + pairlist_pos: int) -> None: + super().__init__(exchange, pairlistmanager, config, pairlistconfig, pairlist_pos) + + self._num_assets = self._pairlistconfig.get('number_assets') + self._producer_name = self._pairlistconfig.get('producer_name', 'default') + if config.get('external_message_consumer').get('enabled') is False: + raise ValueError("ProducerPairList requires external_message_consumer to be enabled.") + + @property + def needstickers(self) -> bool: + """ + Boolean property defining if tickers are necessary. + If no Pairlist requires tickers, an empty Dict is passed + as tickers argument to filter_pairlist + """ + return False + + def short_desc(self) -> str: + """ + Short whitelist method description - used for startup-messages + -> Please overwrite in subclasses + """ + return f"{self.name} - {self._producer_name}" + + def _filter_pairlist(self, pairlist: Optional[List[str]]): + upstream_pairlist = self._pairlistmanager._dataprovider.get_producer_pairs( + self._producer_name) + + if pairlist is None: + pairlist = self._pairlistmanager._dataprovider.get_producer_pairs(self._producer_name) + + pairs = list(dict.fromkeys(upstream_pairlist + pairlist))[:self._num_assets] + + return pairs + + def gen_pairlist(self, tickers: Dict) -> List[str]: + """ + Generate the pairlist + :param tickers: Tickers (from exchange.get_tickers()). May be cached. + :return: List of pairs + """ + pairs = self._filter_pairlist(None) + self.log_once(f"Received pairs: {pairs}", logger.debug) + pairs = self._whitelist_for_active_markets(self.verify_whitelist(pairs, logger.info)) + self.log_once(f"New Pairlist: {pairs}", logger.info) + return pairs + + def filter_pairlist(self, pairlist: List[str], tickers: Dict) -> List[str]: + """ + Filters and sorts pairlist and returns the whitelist again. + Called on each bot iteration - please use internal caching if necessary + :param pairlist: pairlist to filter or sort + :param tickers: Tickers (from exchange.get_tickers()). May be cached. + :return: new whitelist + """ + return self._filter_pairlist(pairlist)