add "cfg" argument for overriding any config from command line

This commit is contained in:
yakovenko.dima 2021-04-03 15:46:27 -03:00
parent 5f6eae52a2
commit 79e70016e0
4 changed files with 82 additions and 2 deletions

View File

@ -10,7 +10,7 @@ from freqtrade.commands.cli_options import AVAILABLE_CLI_OPTIONS
from freqtrade.constants import DEFAULT_CONFIG
ARGS_COMMON = ["verbosity", "logfile", "version", "config", "datadir", "user_data_dir"]
ARGS_COMMON = ["verbosity", "logfile", "version", "config", "cfg", "datadir", "user_data_dir"]
ARGS_STRATEGY = ["strategy", "strategy_path"]

View File

@ -1,6 +1,7 @@
"""
Definition of cli arguments used in arguments.py
"""
import argparse
from argparse import ArgumentTypeError
from freqtrade import __version__, constants
@ -38,6 +39,50 @@ class Arg:
self.kwargs = kwargs
class SetDictFromArgAction(argparse.Action):
"""
argparse action to split an argument into KEY=VALUE form
on the first = and append to a dictionary.
"""
def __call__(self, parser, args, values, option_string=None):
for key_value in values:
try:
(k, v) = key_value.split("=", 2)
except ValueError as ex:
raise argparse.ArgumentError(self, f"could not parse argument \"{values[0]}\" as k=v format")
d = self.set_dict_path_value(getattr(args, self.dest) or {}, k, v)
setattr(args, self.dest, d)
@staticmethod
def set_dict_path_value(obj, key, value):
root_obj = obj
keys = key.split('.')
latest = keys.pop()
for k in keys:
obj[k] = obj.get(k, {})
obj = obj[k]
latest_key, *value_type = latest.split(':')
value_type = value_type[0] if len(value_type) > 0 else None
if value_type is None or value_type == "str":
value = value
elif value_type == "int":
value = int(value)
elif value_type == "float":
value = float(value)
elif value_type == "bool":
if value == "True" or value == "true" or value == "1":
value = True
elif value == "False" or value == "false" or value == "0":
value = False
else:
raise ArgumentTypeError(f"Argument '{key}' has unknown value '{value}'. Must be (true|false|True|False|1|0)")
else:
raise Exception(f"Unsupported arg type '{value_type}'")
obj[latest_key] = value
return root_obj
# List of available command line options
AVAILABLE_CLI_OPTIONS = {
# Common options
@ -530,4 +575,12 @@ AVAILABLE_CLI_OPTIONS = {
help='Do not print epoch details header.',
action='store_true',
),
"cfg": Arg(
'--cfg',
nargs='+',
metavar="KEY=VALUE",
action=SetDictFromArgAction,
help='Set any config value.',
# action='store_const'
),
}

View File

@ -93,6 +93,9 @@ class Configuration:
# Load all configs
config: Dict[str, Any] = self.load_from_files(self.args.get("config", []))
if 'cfg' in self.args:
config = deep_merge_dicts(self.args['cfg'] or {}, config)
# Keep a copy of the original configuration file
config['original_config'] = deepcopy(config)

View File

@ -35,6 +35,30 @@ def test_setup_utils_configuration():
assert config['exchange']['secret'] == ''
def test_cfg_argument_replaces_configuration():
args = [
'list-exchanges', '--config', 'config_bittrex.json.example',
]
# Check original config
config = setup_utils_configuration(get_args(args), RunMode.OTHER)
assert config['dry_run'] is True
assert config['exchange']['key'] == ''
assert config['stake_amount'] == 0.05
assert config['timeframe'] == '5m'
args = [
'list-exchanges', '--config', 'config_bittrex.json.example',
'--cfg', 'stake_amount:float=0.1', 'timeframe=15m', 'exchange.sandbox:bool=true',
]
# Check original config
config = setup_utils_configuration(get_args(args), RunMode.OTHER)
assert config['stake_amount'] == 0.1
assert config['timeframe'] == '15m'
assert config['exchange']['sandbox'] is True
def test_start_trading_fail(mocker, caplog):
mocker.patch("freqtrade.worker.Worker.run", MagicMock(side_effect=OperationalException))