diff --git a/freqtrade/configuration/config_validation.py b/freqtrade/configuration/config_validation.py index 93d93263f..21086c913 100644 --- a/freqtrade/configuration/config_validation.py +++ b/freqtrade/configuration/config_validation.py @@ -121,6 +121,7 @@ def _validate_whitelist(conf: Dict[str, Any]) -> None: if conf.get('runmode', RunMode.OTHER) in [RunMode.OTHER, RunMode.PLOT]: return - if (conf.get('pairlist', {}).get('method', 'StaticPairList') == 'StaticPairList' - and not conf.get('exchange', {}).get('pair_whitelist')): - raise OperationalException("StaticPairList requires pair_whitelist to be set.") + for pl in conf.get('pairlists', [{'method': 'StaticPairList'}]): + if (pl.get('method') == 'StaticPairList' + and not conf.get('exchange', {}).get('pair_whitelist')): + raise OperationalException("StaticPairList requires pair_whitelist to be set.") diff --git a/freqtrade/configuration/configuration.py b/freqtrade/configuration/configuration.py index be1c7ab4e..b8995edf9 100644 --- a/freqtrade/configuration/configuration.py +++ b/freqtrade/configuration/configuration.py @@ -81,6 +81,9 @@ class Configuration: if 'ask_strategy' not in config: config['ask_strategy'] = {} + if 'pairlists' not in config: + config['pairlists'] = [] + # validate configuration before returning logger.info('Validating configuration ...') validate_config_schema(config) diff --git a/freqtrade/configuration/deprecated_settings.py b/freqtrade/configuration/deprecated_settings.py index 8471028aa..3aec85ae2 100644 --- a/freqtrade/configuration/deprecated_settings.py +++ b/freqtrade/configuration/deprecated_settings.py @@ -58,9 +58,18 @@ def process_temporary_deprecated_settings(config: Dict[str, Any]) -> None: process_deprecated_setting(config, 'ask_strategy', 'ignore_roi_if_buy_signal', 'experimental', 'ignore_roi_if_buy_signal') + if config.get('pairlist', {}).get("method") == 'VolumePairList': + logger.warning( + "DEPRECATED: " + f"Using VolumePairList in pairlist is deprecated and must be moved to pairlists. " + "Please refer to the docs on configuration details") + config['pairlists'].append({'method': 'VolumePairList', + 'config': config.get('pairlist', {}).get('config') + }) + if config.get('pairlist', {}).get('config', {}).get('precision_filter'): logger.warning( "DEPRECATED: " f"Using precision_filter setting is deprecated and has been replaced by" "PrecisionFilter. Please refer to the docs on configuration details") - config['pairlist'].update({'filters': {'PrecisionFilter': {}}}) + config['pairlists'].append({'method': 'PrecisionFilter'}) diff --git a/tests/conftest.py b/tests/conftest.py index d551596f0..b2c76baec 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -242,6 +242,9 @@ def default_conf(testdatadir): "HOT/BTC", ] }, + "pairlists": [ + {"method": "StaticPairList"} + ], "telegram": { "enabled": True, "token": "token", diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 766511d2d..bb9d88658 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -1050,8 +1050,8 @@ def test_whitelist_static(default_conf, update, mocker) -> None: telegram._whitelist(update=update, context=MagicMock()) assert msg_mock.call_count == 1 - assert ('Using whitelist `StaticPairList` with 4 pairs\n`ETH/BTC, LTC/BTC, XRP/BTC, NEO/BTC`' - in msg_mock.call_args_list[0][0][0]) + assert ("Using whitelist `['StaticPairList']` with 4 pairs\n" + "`ETH/BTC, LTC/BTC, XRP/BTC, NEO/BTC`" in msg_mock.call_args_list[0][0][0]) def test_whitelist_dynamic(default_conf, update, mocker) -> None: @@ -1062,17 +1062,17 @@ def test_whitelist_dynamic(default_conf, update, mocker) -> None: _send_msg=msg_mock ) mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True)) - default_conf['pairlist'] = {'method': 'VolumePairList', - 'config': {'number_assets': 4} - } + default_conf['pairlists'] = [{'method': 'VolumePairList', + 'config': {'number_assets': 4} + }] freqtradebot = get_patched_freqtradebot(mocker, default_conf) telegram = Telegram(freqtradebot) telegram._whitelist(update=update, context=MagicMock()) assert msg_mock.call_count == 1 - assert ('Using whitelist `VolumePairList` with 4 pairs\n`ETH/BTC, LTC/BTC, XRP/BTC, NEO/BTC`' - in msg_mock.call_args_list[0][0][0]) + assert ("Using whitelist `['VolumePairList']` with 4 pairs\n" + "`ETH/BTC, LTC/BTC, XRP/BTC, NEO/BTC`" in msg_mock.call_args_list[0][0][0]) def test_blacklist_static(default_conf, update, mocker) -> None: diff --git a/tests/test_configuration.py b/tests/test_configuration.py index 258088925..6cfae01c6 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -743,9 +743,9 @@ def test_validate_whitelist(default_conf): conf = deepcopy(default_conf) - conf.update({"pairlist": { + conf.update({"pairlists": [{ "method": "VolumePairList", - }}) + }]}) # Dynamic whitelist should not care about pair_whitelist validate_config_consistency(conf) del conf['exchange']['pair_whitelist'] @@ -963,14 +963,16 @@ def test_process_temporary_deprecated_settings(mocker, default_conf, setting, ca assert default_conf[setting[0]][setting[1]] == setting[5] -def test_process_deprecated_setting_precision_filter(mocker, default_conf, caplog): +def test_process_deprecated_setting_pairlists(mocker, default_conf, caplog): patched_configuration_load_config_file(mocker, default_conf) default_conf.update({'pairlist': { + 'method': 'VolumePairList', 'config': {'precision_filter': True} }}) process_temporary_deprecated_settings(default_conf) assert log_has_re(r'DEPRECATED.*precision_filter.*', caplog) + assert log_has_re(r'DEPRECATED.*in pairlist is deprecated and must be moved*', caplog) def test_check_conflicting_settings(mocker, default_conf, caplog):