diff --git a/freqtrade/configuration/config_validation.py b/freqtrade/configuration/config_validation.py index 6a8374e6d..93d93263f 100644 --- a/freqtrade/configuration/config_validation.py +++ b/freqtrade/configuration/config_validation.py @@ -5,7 +5,7 @@ from jsonschema import Draft4Validator, validators from jsonschema.exceptions import ValidationError, best_match from freqtrade import constants, OperationalException - +from freqtrade.state import RunMode logger = logging.getLogger(__name__) @@ -64,6 +64,7 @@ def validate_config_consistency(conf: Dict[str, Any]) -> None: # validating trailing stoploss _validate_trailing_stoploss(conf) _validate_edge(conf) + _validate_whitelist(conf) def _validate_trailing_stoploss(conf: Dict[str, Any]) -> None: @@ -111,3 +112,15 @@ def _validate_edge(conf: Dict[str, Any]) -> None: "Edge and VolumePairList are incompatible, " "Edge will override whatever pairs VolumePairlist selects." ) + + +def _validate_whitelist(conf: Dict[str, Any]) -> None: + """ + Dynamic whitelist does not require pair_whitelist to be set - however StaticWhitelist does. + """ + 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.") diff --git a/freqtrade/configuration/configuration.py b/freqtrade/configuration/configuration.py index 034f8d386..be1c7ab4e 100644 --- a/freqtrade/configuration/configuration.py +++ b/freqtrade/configuration/configuration.py @@ -179,6 +179,9 @@ class Configuration: config['exchange']['name'] = self.args["exchange"] logger.info(f"Using exchange {config['exchange']['name']}") + if 'pair_whitelist' not in config['exchange']: + config['exchange']['pair_whitelist'] = [] + if 'user_data_dir' in self.args and self.args["user_data_dir"]: config.update({'user_data_dir': self.args["user_data_dir"]}) elif 'user_data_dir' not in config: diff --git a/freqtrade/constants.py b/freqtrade/constants.py index e8f3f5783..5fdd45916 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -235,7 +235,7 @@ CONF_SCHEMA = { 'ccxt_config': {'type': 'object'}, 'ccxt_async_config': {'type': 'object'} }, - 'required': ['name', 'pair_whitelist'] + 'required': ['name'] }, 'edge': { 'type': 'object', diff --git a/tests/test_configuration.py b/tests/test_configuration.py index 2aa805fe6..cfb7f9a7f 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -729,6 +729,30 @@ def test_validate_edge(edge_conf): validate_config_consistency(edge_conf) +def test_validate_whitelist(default_conf): + default_conf['runmode'] = RunMode.DRY_RUN + # Test regular case - has whitelist and uses StaticPairlist + validate_config_consistency(default_conf) + conf = deepcopy(default_conf) + del conf['exchange']['pair_whitelist'] + # Test error case + with pytest.raises(OperationalException, + match="StaticPairList requires pair_whitelist to be set."): + + validate_config_consistency(conf) + + conf = deepcopy(default_conf) + + conf.update({"pairlist": { + "method": "VolumePairList", + }}) + # Dynamic whitelist should not care about pair_whitelist + validate_config_consistency(conf) + del conf['exchange']['pair_whitelist'] + + validate_config_consistency(conf) + + def test_load_config_test_comments() -> None: """ Load config with comments @@ -895,7 +919,7 @@ def test_pairlist_resolving_fallback(mocker): # Fix flaky tests if config.json exists args["config"] = None - configuration = Configuration(args) + configuration = Configuration(args, RunMode.OTHER) config = configuration.get_config() assert config['pairs'] == ['ETH/BTC', 'XRP/BTC']