minor: configuration cleanup
This commit is contained in:
parent
5144e98a82
commit
8096a1fb04
@ -40,49 +40,20 @@ class Configuration(object):
|
|||||||
|
|
||||||
return self.config
|
return self.config
|
||||||
|
|
||||||
def load_config(self) -> Dict[str, Any]:
|
def _load_config_files(self) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Extract information for sys.argv and load the bot configuration
|
Iterate through the config files passed in the args,
|
||||||
:return: Configuration dictionary
|
loading all of them and merging their contents.
|
||||||
"""
|
"""
|
||||||
config: Dict[str, Any] = {}
|
config: Dict[str, Any] = {}
|
||||||
# Now expecting a list of config filenames here, not a string
|
|
||||||
|
# We expect here a list of config filenames
|
||||||
for path in self.args.config:
|
for path in self.args.config:
|
||||||
logger.info('Using config: %s ...', path)
|
logger.info('Using config: %s ...', path)
|
||||||
|
|
||||||
# Merge config options, overwriting old values
|
# Merge config options, overwriting old values
|
||||||
config = deep_merge_dicts(self._load_config_file(path), config)
|
config = deep_merge_dicts(self._load_config_file(path), config)
|
||||||
|
|
||||||
if 'internals' not in config:
|
|
||||||
config['internals'] = {}
|
|
||||||
|
|
||||||
logger.info('Validating configuration ...')
|
|
||||||
validate_config_schema(config)
|
|
||||||
self._validate_config_consistency(config)
|
|
||||||
|
|
||||||
# Set strategy if not specified in config and or if it's non default
|
|
||||||
if self.args.strategy != constants.DEFAULT_STRATEGY or not config.get('strategy'):
|
|
||||||
config.update({'strategy': self.args.strategy})
|
|
||||||
|
|
||||||
if self.args.strategy_path:
|
|
||||||
config.update({'strategy_path': self.args.strategy_path})
|
|
||||||
|
|
||||||
# Load Common configuration
|
|
||||||
config = self._load_common_config(config)
|
|
||||||
|
|
||||||
# Load Optimize configurations
|
|
||||||
config = self._load_optimize_config(config)
|
|
||||||
|
|
||||||
# Add plotting options if available
|
|
||||||
config = self._load_plot_config(config)
|
|
||||||
|
|
||||||
# Set runmode
|
|
||||||
if not self.runmode:
|
|
||||||
# Handle real mode, infer dry/live from config
|
|
||||||
self.runmode = RunMode.DRY_RUN if config.get('dry_run', True) else RunMode.LIVE
|
|
||||||
|
|
||||||
config.update({'runmode': self.runmode})
|
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
|
||||||
def _load_config_file(self, path: str) -> Dict[str, Any]:
|
def _load_config_file(self, path: str) -> Dict[str, Any]:
|
||||||
@ -94,13 +65,50 @@ class Configuration(object):
|
|||||||
try:
|
try:
|
||||||
# Read config from stdin if requested in the options
|
# Read config from stdin if requested in the options
|
||||||
with open(path) if path != '-' else sys.stdin as file:
|
with open(path) if path != '-' else sys.stdin as file:
|
||||||
conf = json.load(file)
|
config = json.load(file)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
raise OperationalException(
|
raise OperationalException(
|
||||||
f'Config file "{path}" not found!'
|
f'Config file "{path}" not found!'
|
||||||
' Please create a config file or check whether it exists.')
|
' Please create a config file or check whether it exists.')
|
||||||
|
|
||||||
return conf
|
return config
|
||||||
|
|
||||||
|
def _normalize_config(self, config: Dict[str, Any]) -> None:
|
||||||
|
"""
|
||||||
|
Make config more canonical -- i.e. for example add missing parts that we expect
|
||||||
|
to be normally in it...
|
||||||
|
"""
|
||||||
|
if 'internals' not in config:
|
||||||
|
config['internals'] = {}
|
||||||
|
|
||||||
|
def load_config(self) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
Extract information for sys.argv and load the bot configuration
|
||||||
|
:return: Configuration dictionary
|
||||||
|
"""
|
||||||
|
# Load all configs
|
||||||
|
config: Dict[str, Any] = self._load_config_files()
|
||||||
|
|
||||||
|
# Make resulting config more canonical
|
||||||
|
self._normalize_config(config)
|
||||||
|
|
||||||
|
logger.info('Validating configuration ...')
|
||||||
|
validate_config_schema(config)
|
||||||
|
self._validate_config_consistency(config)
|
||||||
|
|
||||||
|
# Load Common configuration
|
||||||
|
self._load_common_config(config)
|
||||||
|
|
||||||
|
# Load Optimize configurations
|
||||||
|
self._load_optimize_config(config)
|
||||||
|
|
||||||
|
# Add plotting options if available
|
||||||
|
self._load_plot_config(config)
|
||||||
|
|
||||||
|
# Set runmode
|
||||||
|
self._load_runmode_config(config)
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
def _load_logging_config(self, config: Dict[str, Any]) -> None:
|
def _load_logging_config(self, config: Dict[str, Any]) -> None:
|
||||||
"""
|
"""
|
||||||
@ -118,16 +126,22 @@ class Configuration(object):
|
|||||||
|
|
||||||
setup_logging(config)
|
setup_logging(config)
|
||||||
|
|
||||||
def _load_common_config(self, config: Dict[str, Any]) -> Dict[str, Any]:
|
def _load_strategy_config(self, config: Dict[str, Any]) -> None:
|
||||||
|
|
||||||
|
# Set strategy if not specified in config and or if it's non default
|
||||||
|
if self.args.strategy != constants.DEFAULT_STRATEGY or not config.get('strategy'):
|
||||||
|
config.update({'strategy': self.args.strategy})
|
||||||
|
|
||||||
|
if self.args.strategy_path:
|
||||||
|
config.update({'strategy_path': self.args.strategy_path})
|
||||||
|
|
||||||
|
def _load_common_config(self, config: Dict[str, Any]) -> None:
|
||||||
"""
|
"""
|
||||||
Extract information for sys.argv and load common configuration
|
Extract information for sys.argv and load common configuration
|
||||||
:return: configuration as dictionary
|
:return: configuration as dictionary
|
||||||
"""
|
"""
|
||||||
self._load_logging_config(config)
|
self._load_logging_config(config)
|
||||||
|
self._load_strategy_config(config)
|
||||||
# Support for sd_notify
|
|
||||||
if 'sd_notify' in self.args and self.args.sd_notify:
|
|
||||||
config['internals'].update({'sd_notify': True})
|
|
||||||
|
|
||||||
# Add dynamic_whitelist if found
|
# Add dynamic_whitelist if found
|
||||||
if 'dynamic_whitelist' in self.args and self.args.dynamic_whitelist:
|
if 'dynamic_whitelist' in self.args and self.args.dynamic_whitelist:
|
||||||
@ -157,6 +171,8 @@ class Configuration(object):
|
|||||||
config['db_url'] = constants.DEFAULT_DB_PROD_URL
|
config['db_url'] = constants.DEFAULT_DB_PROD_URL
|
||||||
logger.info('Dry run is disabled')
|
logger.info('Dry run is disabled')
|
||||||
|
|
||||||
|
logger.info(f'Using DB: "{config["db_url"]}"')
|
||||||
|
|
||||||
if config.get('forcebuy_enable', False):
|
if config.get('forcebuy_enable', False):
|
||||||
logger.warning('`forcebuy` RPC message enabled.')
|
logger.warning('`forcebuy` RPC message enabled.')
|
||||||
|
|
||||||
@ -164,32 +180,13 @@ class Configuration(object):
|
|||||||
if config.get('max_open_trades') == -1:
|
if config.get('max_open_trades') == -1:
|
||||||
config['max_open_trades'] = float('inf')
|
config['max_open_trades'] = float('inf')
|
||||||
|
|
||||||
logger.info(f'Using DB: "{config["db_url"]}"')
|
# Support for sd_notify
|
||||||
|
if 'sd_notify' in self.args and self.args.sd_notify:
|
||||||
|
config['internals'].update({'sd_notify': True})
|
||||||
|
|
||||||
# Check if the exchange set by the user is supported
|
# Check if the exchange set by the user is supported
|
||||||
check_exchange(config)
|
check_exchange(config)
|
||||||
|
|
||||||
return config
|
|
||||||
|
|
||||||
def _args_to_config(self, config: Dict[str, Any], argname: str,
|
|
||||||
logstring: str, logfun: Optional[Callable] = None) -> None:
|
|
||||||
"""
|
|
||||||
:param config: Configuration dictionary
|
|
||||||
:param argname: Argumentname in self.args - will be copied to config dict.
|
|
||||||
:param logstring: Logging String
|
|
||||||
:param logfun: logfun is applied to the configuration entry before passing
|
|
||||||
that entry to the log string using .format().
|
|
||||||
sample: logfun=len (prints the length of the found
|
|
||||||
configuration instead of the content)
|
|
||||||
"""
|
|
||||||
if argname in self.args and getattr(self.args, argname):
|
|
||||||
|
|
||||||
config.update({argname: getattr(self.args, argname)})
|
|
||||||
if logfun:
|
|
||||||
logger.info(logstring.format(logfun(config[argname])))
|
|
||||||
else:
|
|
||||||
logger.info(logstring.format(config[argname]))
|
|
||||||
|
|
||||||
def _load_datadir_config(self, config: Dict[str, Any]) -> None:
|
def _load_datadir_config(self, config: Dict[str, Any]) -> None:
|
||||||
"""
|
"""
|
||||||
Extract information for sys.argv and load datadir configuration:
|
Extract information for sys.argv and load datadir configuration:
|
||||||
@ -201,12 +198,11 @@ class Configuration(object):
|
|||||||
config.update({'datadir': create_datadir(config, None)})
|
config.update({'datadir': create_datadir(config, None)})
|
||||||
logger.info('Using data directory: %s ...', config.get('datadir'))
|
logger.info('Using data directory: %s ...', config.get('datadir'))
|
||||||
|
|
||||||
def _load_optimize_config(self, config: Dict[str, Any]) -> Dict[str, Any]:
|
def _load_optimize_config(self, config: Dict[str, Any]) -> None:
|
||||||
"""
|
"""
|
||||||
Extract information for sys.argv and load Optimize configuration
|
Extract information for sys.argv and load Optimize configuration
|
||||||
:return: configuration as dictionary
|
:return: configuration as dictionary
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# This will override the strategy configuration
|
# This will override the strategy configuration
|
||||||
self._args_to_config(config, argname='ticker_interval',
|
self._args_to_config(config, argname='ticker_interval',
|
||||||
logstring='Parameter -i/--ticker-interval detected ... '
|
logstring='Parameter -i/--ticker-interval detected ... '
|
||||||
@ -285,14 +281,11 @@ class Configuration(object):
|
|||||||
self._args_to_config(config, argname='hyperopt_min_trades',
|
self._args_to_config(config, argname='hyperopt_min_trades',
|
||||||
logstring='Parameter --min-trades detected: {}')
|
logstring='Parameter --min-trades detected: {}')
|
||||||
|
|
||||||
return config
|
def _load_plot_config(self, config: Dict[str, Any]) -> None:
|
||||||
|
|
||||||
def _load_plot_config(self, config: Dict[str, Any]) -> Dict[str, Any]:
|
|
||||||
"""
|
"""
|
||||||
Extract information for sys.argv Plotting configuration
|
Extract information for sys.argv Plotting configuration
|
||||||
:return: configuration as dictionary
|
:return: configuration as dictionary
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._args_to_config(config, argname='pairs',
|
self._args_to_config(config, argname='pairs',
|
||||||
logstring='Using pairs {}')
|
logstring='Using pairs {}')
|
||||||
|
|
||||||
@ -306,7 +299,14 @@ class Configuration(object):
|
|||||||
logstring='Limiting plot to: {}')
|
logstring='Limiting plot to: {}')
|
||||||
self._args_to_config(config, argname='trade_source',
|
self._args_to_config(config, argname='trade_source',
|
||||||
logstring='Using trades from: {}')
|
logstring='Using trades from: {}')
|
||||||
return config
|
|
||||||
|
def _load_runmode_config(self, config: Dict[str, Any]) -> None:
|
||||||
|
if not self.runmode:
|
||||||
|
# Handle real mode, infer dry/live from config
|
||||||
|
self.runmode = RunMode.DRY_RUN if config.get('dry_run', True) else RunMode.LIVE
|
||||||
|
logger.info("Runmode set to {self.runmode}.")
|
||||||
|
|
||||||
|
config.update({'runmode': self.runmode})
|
||||||
|
|
||||||
def _validate_config_consistency(self, conf: Dict[str, Any]) -> None:
|
def _validate_config_consistency(self, conf: Dict[str, Any]) -> None:
|
||||||
"""
|
"""
|
||||||
@ -336,3 +336,22 @@ class Configuration(object):
|
|||||||
raise OperationalException(
|
raise OperationalException(
|
||||||
f'The config trailing_stop_positive_offset needs '
|
f'The config trailing_stop_positive_offset needs '
|
||||||
'to be greater than trailing_stop_positive_offset in your config.')
|
'to be greater than trailing_stop_positive_offset in your config.')
|
||||||
|
|
||||||
|
def _args_to_config(self, config: Dict[str, Any], argname: str,
|
||||||
|
logstring: str, logfun: Optional[Callable] = None) -> None:
|
||||||
|
"""
|
||||||
|
:param config: Configuration dictionary
|
||||||
|
:param argname: Argumentname in self.args - will be copied to config dict.
|
||||||
|
:param logstring: Logging String
|
||||||
|
:param logfun: logfun is applied to the configuration entry before passing
|
||||||
|
that entry to the log string using .format().
|
||||||
|
sample: logfun=len (prints the length of the found
|
||||||
|
configuration instead of the content)
|
||||||
|
"""
|
||||||
|
if argname in self.args and getattr(self.args, argname):
|
||||||
|
|
||||||
|
config.update({argname: getattr(self.args, argname)})
|
||||||
|
if logfun:
|
||||||
|
logger.info(logstring.format(logfun(config[argname])))
|
||||||
|
else:
|
||||||
|
logger.info(logstring.format(config[argname]))
|
||||||
|
Loading…
Reference in New Issue
Block a user