diff --git a/freqtrade/configuration/config_validation.py b/freqtrade/configuration/config_validation.py index 43eead46a..6f56790f4 100644 --- a/freqtrade/configuration/config_validation.py +++ b/freqtrade/configuration/config_validation.py @@ -1,4 +1,5 @@ import logging +from copy import deepcopy from typing import Any, Dict from jsonschema import Draft4Validator, validators @@ -42,15 +43,25 @@ def validate_config_schema(conf: Dict[str, Any]) -> Dict[str, Any]: :param conf: Config in JSON format :return: Returns the config if valid, otherwise throw an exception """ + conf_schema = deepcopy(constants.CONF_SCHEMA) + if conf.get('runmode', RunMode.OTHER) in (RunMode.DRY_RUN, RunMode.LIVE): + conf_schema['required'] = constants.SCHEMA_TRADE_REQUIRED + else: + conf_schema['required'] = constants.SCHEMA_MINIMAL_REQUIRED + # Dynamically allow empty stake-currency + # Since the minimal config specifies this too. + # It's not allowed for Dry-run or live modes + conf_schema['properties']['stake_currency']['enum'] += [''] # type: ignore + try: - FreqtradeValidator(constants.CONF_SCHEMA).validate(conf) + FreqtradeValidator(conf_schema).validate(conf) return conf except ValidationError as e: logger.critical( f"Invalid configuration. See config.json.example. Reason: {e}" ) raise ValidationError( - best_match(Draft4Validator(constants.CONF_SCHEMA).iter_errors(conf)).message + best_match(Draft4Validator(conf_schema).iter_errors(conf)).message ) diff --git a/freqtrade/constants.py b/freqtrade/constants.py index d7c6249d5..b21279bb4 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -269,16 +269,22 @@ CONF_SCHEMA = { 'required': ['process_throttle_secs', 'allowed_risk', 'capital_available_percentage'] } }, - 'required': [ - 'exchange', - 'max_open_trades', - 'stake_currency', - 'stake_amount', - 'dry_run', - 'dry_run_wallet', - 'bid_strategy', - 'unfilledtimeout', - 'stoploss', - 'minimal_roi', - ] } + +SCHEMA_TRADE_REQUIRED = [ + 'exchange', + 'max_open_trades', + 'stake_currency', + 'stake_amount', + 'dry_run', + 'dry_run_wallet', + 'bid_strategy', + 'unfilledtimeout', + 'stoploss', + 'minimal_roi', +] + +SCHEMA_MINIMAL_REQUIRED = [ + 'exchange', + 'dry_run', +] diff --git a/freqtrade/utils.py b/freqtrade/utils.py index 45520ecf7..9fe15aea6 100644 --- a/freqtrade/utils.py +++ b/freqtrade/utils.py @@ -12,7 +12,8 @@ from colorama import init as colorama_init from tabulate import tabulate from freqtrade.configuration import (Configuration, TimeRange, - remove_credentials) + remove_credentials, + validate_config_consistency) from freqtrade.configuration.directory_operations import (copy_sample_files, create_userdata_dir) from freqtrade.constants import USERPATH_HYPEROPTS, USERPATH_STRATEGY @@ -40,6 +41,7 @@ def setup_utils_configuration(args: Dict[str, Any], method: RunMode) -> Dict[str # Ensure we do not use Exchange credentials remove_credentials(config) + validate_config_consistency(config) return config diff --git a/tests/test_configuration.py b/tests/test_configuration.py index ee3d23131..531a88688 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -49,6 +49,7 @@ def test_load_config_missing_attributes(default_conf) -> None: conf = deepcopy(default_conf) conf.pop('stake_currency') + conf['runmode'] = RunMode.DRY_RUN with pytest.raises(ValidationError, match=r".*'stake_currency' is a required property.*"): validate_config_schema(conf)