mirror of
https://github.com/freqtrade/freqtrade.git
synced 2026-01-20 05:50:36 +00:00
remove mode, add max_rank, modify test
This commit is contained in:
@@ -18,9 +18,6 @@ from freqtrade.plugins.pairlist.IPairList import IPairList, PairlistParameter
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
MODE_VALUES = ['top_rank', 'total_assets']
|
|
||||||
|
|
||||||
|
|
||||||
class MarketCapPairList(IPairList):
|
class MarketCapPairList(IPairList):
|
||||||
|
|
||||||
is_pairlist_generator = True
|
is_pairlist_generator = True
|
||||||
@@ -36,22 +33,18 @@ class MarketCapPairList(IPairList):
|
|||||||
'for "pairlist.config.number_assets"')
|
'for "pairlist.config.number_assets"')
|
||||||
|
|
||||||
self._stake_currency = config['stake_currency']
|
self._stake_currency = config['stake_currency']
|
||||||
self._mode = self._pairlistconfig.get('mode', 'top_rank')
|
|
||||||
self._number_assets = self._pairlistconfig['number_assets']
|
self._number_assets = self._pairlistconfig['number_assets']
|
||||||
|
self._max_rank = self._pairlistconfig.get('max_rank', 30)
|
||||||
self._refresh_period = self._pairlistconfig.get('refresh_period', 86400)
|
self._refresh_period = self._pairlistconfig.get('refresh_period', 86400)
|
||||||
self._marketcap_cache: TTLCache = TTLCache(maxsize=1, ttl=self._refresh_period)
|
self._marketcap_cache: TTLCache = TTLCache(maxsize=1, ttl=self._refresh_period)
|
||||||
self._def_candletype = self._config['candle_type_def']
|
self._def_candletype = self._config['candle_type_def']
|
||||||
self._coingekko: CoinGeckoAPI = CoinGeckoAPI()
|
self._coingekko: CoinGeckoAPI = CoinGeckoAPI()
|
||||||
|
|
||||||
if self._number_assets > 250:
|
if self._max_rank > 250:
|
||||||
raise OperationalException(
|
raise OperationalException(
|
||||||
"This filter only support number_assets value up to 250."
|
"This filter only support marketcap rank up to 250."
|
||||||
)
|
)
|
||||||
|
|
||||||
if not self._validate_keys(self._mode):
|
|
||||||
raise OperationalException(
|
|
||||||
f'key {self._mode} not in {MODE_VALUES}')
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def needstickers(self) -> bool:
|
def needstickers(self) -> bool:
|
||||||
"""
|
"""
|
||||||
@@ -61,17 +54,13 @@ class MarketCapPairList(IPairList):
|
|||||||
"""
|
"""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _validate_keys(self, key):
|
|
||||||
return key in MODE_VALUES
|
|
||||||
|
|
||||||
def short_desc(self) -> str:
|
def short_desc(self) -> str:
|
||||||
"""
|
"""
|
||||||
Short whitelist method description - used for startup-messages
|
Short whitelist method description - used for startup-messages
|
||||||
"""
|
"""
|
||||||
num = self._pairlistconfig['number_assets']
|
num = self._number_assets
|
||||||
msg = f"{self.name} - Only include pairs ranked within top {num} market cap."
|
rank = self._max_rank
|
||||||
if self._mode == "total_assets":
|
msg = f"{self.name} - {num} pairs placed within top {rank} market cap."
|
||||||
msg = f"{self.name} - top {num} pairs sorted by market cap."
|
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -84,15 +73,14 @@ class MarketCapPairList(IPairList):
|
|||||||
"number_assets": {
|
"number_assets": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"default": 30,
|
"default": 30,
|
||||||
"description": "Max market cap rank",
|
"description": "Number of assets",
|
||||||
"help": "Only use assets with high market cap rank",
|
"help": "Number of assets to use from the pairlist",
|
||||||
},
|
},
|
||||||
"mode": {
|
"max_rank": {
|
||||||
"type": "option",
|
"type": "number",
|
||||||
"default": "top_rank",
|
"default": 30,
|
||||||
"options": MODE_VALUES,
|
"description": "Max rank of assets",
|
||||||
"description": "Mode of number",
|
"help": "Maximum rank of assets to use from the pairlist",
|
||||||
"help": "How to interpret the number",
|
|
||||||
},
|
},
|
||||||
"refresh_period": {
|
"refresh_period": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
@@ -149,28 +137,19 @@ class MarketCapPairList(IPairList):
|
|||||||
if marketcap_list:
|
if marketcap_list:
|
||||||
filtered_pairlist = []
|
filtered_pairlist = []
|
||||||
|
|
||||||
if self._mode == 'top_rank':
|
market = self._config['trading_mode']
|
||||||
top_marketcap = marketcap_list[:self._number_assets:]
|
pair_format = f"{self._stake_currency.upper()}"
|
||||||
|
if (market == 'futures'):
|
||||||
|
pair_format += f":{self._stake_currency.upper()}"
|
||||||
|
|
||||||
for pair in pairlist:
|
top_marketcap = marketcap_list[:self._max_rank:]
|
||||||
base = self._exchange.get_pair_base_currency(pair)
|
|
||||||
if base.lower() in top_marketcap:
|
|
||||||
filtered_pairlist.append(pair)
|
|
||||||
else:
|
|
||||||
self.log_once(f"Remove {pair} from whitelist because it's not ranked "
|
|
||||||
f"within top {self._number_assets} market cap", logger.info)
|
|
||||||
|
|
||||||
else:
|
for mc_pair in top_marketcap:
|
||||||
market = self._config['trading_mode']
|
test_pair = f"{mc_pair.upper()}/{pair_format}"
|
||||||
pair_format = f"{self._stake_currency.upper()}"
|
if test_pair in pairlist:
|
||||||
if (market == 'futures'):
|
filtered_pairlist.append(test_pair)
|
||||||
pair_format += f":{self._stake_currency.upper()}"
|
if len(filtered_pairlist) == self._number_assets:
|
||||||
for mc_pair in marketcap_list:
|
break
|
||||||
test_pair = f"{mc_pair.upper()}/{pair_format}"
|
|
||||||
if test_pair in pairlist:
|
|
||||||
filtered_pairlist.append(test_pair)
|
|
||||||
if len(filtered_pairlist) == self._number_assets:
|
|
||||||
break
|
|
||||||
|
|
||||||
if len(filtered_pairlist) > 0:
|
if len(filtered_pairlist) > 0:
|
||||||
return filtered_pairlist
|
return filtered_pairlist
|
||||||
|
|||||||
@@ -1517,29 +1517,29 @@ def test_FullTradesFilter(mocker, default_conf_usdt, fee, caplog) -> None:
|
|||||||
|
|
||||||
@pytest.mark.parametrize('pairlists,result', [
|
@pytest.mark.parametrize('pairlists,result', [
|
||||||
([
|
([
|
||||||
# Test top 2 mc
|
# Get 2 pairs
|
||||||
{"method": "StaticPairList", "allow_inactive": True},
|
{"method": "StaticPairList", "allow_inactive": True},
|
||||||
{"method": "MarketCapPairList", "mode": "top_rank", "number_assets": 2}
|
{"method": "MarketCapPairList", "number_assets": 2}
|
||||||
], ['ETH/USDT', 'BTC/USDT']),
|
|
||||||
([
|
|
||||||
# Test top 6 mc
|
|
||||||
{"method": "StaticPairList", "allow_inactive": True},
|
|
||||||
{"method": "MarketCapPairList", "mode": "top_rank", "number_assets": 6}
|
|
||||||
], ['ETH/USDT', 'XRP/USDT', 'BTC/USDT']),
|
|
||||||
([
|
|
||||||
# Test total assets mode, 2 assets
|
|
||||||
{"method": "StaticPairList", "allow_inactive": True},
|
|
||||||
{"method": "MarketCapPairList", "mode": "total_assets", "number_assets": 2}
|
|
||||||
], ['BTC/USDT', 'ETH/USDT']),
|
], ['BTC/USDT', 'ETH/USDT']),
|
||||||
|
([
|
||||||
|
# Get 6 pairs
|
||||||
|
{"method": "StaticPairList", "allow_inactive": True},
|
||||||
|
{"method": "MarketCapPairList", "number_assets": 6}
|
||||||
|
], ['BTC/USDT', 'ETH/USDT', 'XRP/USDT', 'ADA/USDT']),
|
||||||
|
([
|
||||||
|
# Get 3 pairs within top 6 ranks
|
||||||
|
{"method": "StaticPairList", "allow_inactive": True},
|
||||||
|
{"method": "MarketCapPairList", "max_rank": 6, "number_assets": 3}
|
||||||
|
], ['BTC/USDT', 'ETH/USDT', 'XRP/USDT']),
|
||||||
|
|
||||||
([
|
([
|
||||||
# Test total assets mode, 5 assets
|
# Get 4 pairs within top 8 ranks
|
||||||
{"method": "StaticPairList", "allow_inactive": True},
|
{"method": "StaticPairList", "allow_inactive": True},
|
||||||
{"method": "MarketCapPairList", "mode": "total_assets", "number_assets": 5}
|
{"method": "MarketCapPairList", "max_rank": 8, "number_assets": 4}
|
||||||
], ['BTC/USDT', 'ETH/USDT', 'XRP/USDT']),
|
], ['BTC/USDT', 'ETH/USDT', 'XRP/USDT']),
|
||||||
([
|
([
|
||||||
# MarketCapPairList as generator
|
# MarketCapPairList as generator
|
||||||
{"method": "MarketCapPairList", "mode": "total_assets", "number_assets": 5}
|
{"method": "MarketCapPairList", "number_assets": 5}
|
||||||
], ['BTC/USDT', 'ETH/USDT', 'XRP/USDT'])
|
], ['BTC/USDT', 'ETH/USDT', 'XRP/USDT'])
|
||||||
])
|
])
|
||||||
def test_MarketCapPairList_filter(mocker, default_conf_usdt, markets, pairlists, result):
|
def test_MarketCapPairList_filter(mocker, default_conf_usdt, markets, pairlists, result):
|
||||||
@@ -1576,7 +1576,7 @@ def test_MarketCapPairList_filter(mocker, default_conf_usdt, markets, pairlists,
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
default_conf_usdt['exchange']['pair_whitelist'].extend(['BTC/USDT', 'ETC/USDT'])
|
default_conf_usdt['exchange']['pair_whitelist'].extend(['BTC/USDT', 'ETC/USDT', 'ADA/USDT'])
|
||||||
default_conf_usdt['trading_mode'] = 'spot'
|
default_conf_usdt['trading_mode'] = 'spot'
|
||||||
default_conf_usdt['pairlists'] = pairlists
|
default_conf_usdt['pairlists'] = pairlists
|
||||||
mocker.patch.multiple(EXMS,
|
mocker.patch.multiple(EXMS,
|
||||||
|
|||||||
Reference in New Issue
Block a user