From 17cf9d33cfa848a20c4b9ff4d0fdf116f4c5603f Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 24 Apr 2019 20:44:36 +0200 Subject: [PATCH 01/20] add _args_to_conig --- freqtrade/configuration.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/freqtrade/configuration.py b/freqtrade/configuration.py index 6388a97ac..172010dd8 100644 --- a/freqtrade/configuration.py +++ b/freqtrade/configuration.py @@ -216,6 +216,14 @@ class Configuration(object): logger.info(f'Created data directory: {datadir}') return datadir + def _args_to_config(self, config, argname, configname, logstring) -> bool: + + if argname in self.args and getattr(self.args, argname): + + config.update({configname: getattr(self.args, argname)}) + + logger.info(logstring.format(config[configname])) + def _load_backtesting_config(self, config: Dict[str, Any]) -> Dict[str, Any]: # noqa: C901 """ Extract information for sys.argv and load Backtesting configuration @@ -232,9 +240,8 @@ class Configuration(object): config.update({'live': True}) logger.info('Parameter -l/--live detected ...') - if 'position_stacking' in self.args and self.args.position_stacking: - config.update({'position_stacking': True}) - logger.info('Parameter --enable-position-stacking detected ...') + self._args_to_config(config, 'position_stacking', 'position_stacking', + 'Parameter --enable-position-stacking detected ...') if 'use_max_market_positions' in self.args and not self.args.use_max_market_positions: config.update({'use_max_market_positions': False}) From 39f60c474002be0827987c3c6ba74d391ecacef6 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 24 Apr 2019 21:02:05 +0200 Subject: [PATCH 02/20] Add some more arguments to args_to_config --- freqtrade/configuration.py | 60 ++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/freqtrade/configuration.py b/freqtrade/configuration.py index 172010dd8..395653213 100644 --- a/freqtrade/configuration.py +++ b/freqtrade/configuration.py @@ -216,13 +216,19 @@ class Configuration(object): logger.info(f'Created data directory: {datadir}') return datadir - def _args_to_config(self, config, argname, configname, logstring) -> bool: - + def _args_to_config(self, config, argname, configname, logstring, logfun=None) -> bool: + """ + 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({configname: getattr(self.args, argname)}) - - logger.info(logstring.format(config[configname])) + if logfun: + logger.info(logstring.format(logfun(config[configname]))) + else: + logger.info(logstring.format(config[configname])) def _load_backtesting_config(self, config: Dict[str, Any]) -> Dict[str, Any]: # noqa: C901 """ @@ -236,12 +242,11 @@ class Configuration(object): logger.info('Parameter -i/--ticker-interval detected ...') logger.info('Using ticker_interval: %s ...', config.get('ticker_interval')) - if 'live' in self.args and self.args.live: - config.update({'live': True}) - logger.info('Parameter -l/--live detected ...') + self._args_to_config(config, argname='live', configname='live', + logstring='Parameter -l/--live detected ...') - self._args_to_config(config, 'position_stacking', 'position_stacking', - 'Parameter --enable-position-stacking detected ...') + self._args_to_config(config, argname='position_stacking', configname='position_stacking', + logstring='Parameter --enable-position-stacking detected ...') if 'use_max_market_positions' in self.args and not self.args.use_max_market_positions: config.update({'use_max_market_positions': False}) @@ -254,14 +259,12 @@ class Configuration(object): else: logger.info('Using max_open_trades: %s ...', config.get('max_open_trades')) - if 'stake_amount' in self.args and self.args.stake_amount: - config.update({'stake_amount': self.args.stake_amount}) - logger.info('Parameter --stake_amount detected, overriding stake_amount to: %s ...', - config.get('stake_amount')) + self._args_to_config(config, argname='stake_amount', configname='stake_amount', + logstring='Parameter --stake_amount detected, ' + 'overriding stake_amount to: {} ...') - if 'timerange' in self.args and self.args.timerange: - config.update({'timerange': self.args.timerange}) - logger.info('Parameter --timerange detected: %s ...', self.args.timerange) + self._args_to_config(config, argname='timerange', configname='timerange', + logstring='Parameter --timerange detected: {} ...') if 'datadir' in self.args and self.args.datadir: config.update({'datadir': self._create_datadir(config, self.args.datadir)}) @@ -269,25 +272,20 @@ class Configuration(object): config.update({'datadir': self._create_datadir(config, None)}) logger.info('Using data folder: %s ...', config.get('datadir')) - if 'refresh_pairs' in self.args and self.args.refresh_pairs: - config.update({'refresh_pairs': True}) - logger.info('Parameter -r/--refresh-pairs-cached detected ...') + self._args_to_config(config, argname='refresh_pairs', configname='refresh_pairs', + logstring='Parameter -r/--refresh-pairs-cached detected ...') - if 'strategy_list' in self.args and self.args.strategy_list: - config.update({'strategy_list': self.args.strategy_list}) - logger.info('Using strategy list of %s Strategies', len(self.args.strategy_list)) + self._args_to_config(config, argname='strategy_list', configname='strategy_list', + logstring='Using strategy list of {} Strategies', logfun=len) - if 'ticker_interval' in self.args and self.args.ticker_interval: - config.update({'ticker_interval': self.args.ticker_interval}) - logger.info('Overriding ticker interval with Command line argument') + self._args_to_config(config, argname='ticker_interval', configname='ticker_interval', + logstring='Overriding ticker interval with Command line argument') - if 'export' in self.args and self.args.export: - config.update({'export': self.args.export}) - logger.info('Parameter --export detected: %s ...', self.args.export) + self._args_to_config(config, argname='export', configname='export', + logstring='Parameter --export detected: {} ...') - if 'export' in config and 'exportfilename' in self.args and self.args.exportfilename: - config.update({'exportfilename': self.args.exportfilename}) - logger.info('Storing backtest results to %s ...', self.args.exportfilename) + self._args_to_config(config, argname='exportfilename', configname='exportfilename', + logstring='Storing backtest results to {} ...') return config From d6276a15d2087d1bea30a1a796d8bd30a4b05724 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 24 Apr 2019 21:12:08 +0200 Subject: [PATCH 03/20] Convert all optimize to args_to_config --- freqtrade/configuration.py | 54 ++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/freqtrade/configuration.py b/freqtrade/configuration.py index 395653213..2b9b02630 100644 --- a/freqtrade/configuration.py +++ b/freqtrade/configuration.py @@ -216,7 +216,7 @@ class Configuration(object): logger.info(f'Created data directory: {datadir}') return datadir - def _args_to_config(self, config, argname, configname, logstring, logfun=None) -> bool: + def _args_to_config(self, config, argname, configname, logstring, logfun=None) -> None: """ logfun is applied to the configuration entry before passing that entry to the log string using .format(). @@ -230,7 +230,7 @@ class Configuration(object): else: logger.info(logstring.format(config[configname])) - def _load_backtesting_config(self, config: Dict[str, Any]) -> Dict[str, Any]: # noqa: C901 + def _load_backtesting_config(self, config: Dict[str, Any]) -> Dict[str, Any]: """ Extract information for sys.argv and load Backtesting configuration :return: configuration as dictionary @@ -295,9 +295,8 @@ class Configuration(object): :return: configuration as dictionary """ - if 'timerange' in self.args and self.args.timerange: - config.update({'timerange': self.args.timerange}) - logger.info('Parameter --timerange detected: %s ...', self.args.timerange) + self._args_to_config(config, argname='timerange', configname='timerange', + logstring='Parameter --timerange detected: {} ...') if 'stoploss_range' in self.args and self.args.stoploss_range: txt_range = eval(self.args.stoploss_range) @@ -306,9 +305,8 @@ class Configuration(object): config['edge'].update({'stoploss_range_step': txt_range[2]}) logger.info('Parameter --stoplosses detected: %s ...', self.args.stoploss_range) - if 'refresh_pairs' in self.args and self.args.refresh_pairs: - config.update({'refresh_pairs': True}) - logger.info('Parameter -r/--refresh-pairs-cached detected ...') + self._args_to_config(config, argname='refresh_pairs', configname='refresh_pairs', + logstring='Parameter -r/--refresh-pairs-cached detected ...') return config @@ -318,35 +316,29 @@ class Configuration(object): :return: configuration as dictionary """ - if "hyperopt" in self.args: - # Add the hyperopt file to use - config.update({'hyperopt': self.args.hyperopt}) + self._args_to_config(config, argname='hyperopt', configname='hyperopt', + logstring='Using Hyperopt file {}') - if 'epochs' in self.args and self.args.epochs: - config.update({'epochs': self.args.epochs}) - logger.info('Parameter --epochs detected ...') - logger.info('Will run Hyperopt with for %s epochs ...', config.get('epochs')) + self._args_to_config(config, argname='epochs', configname='epochs', + logstring='Parameter --epochs detected ... ' + 'Will run Hyperopt with for {} epochs ...' + ) - if 'spaces' in self.args and self.args.spaces: - config.update({'spaces': self.args.spaces}) - logger.info('Parameter -s/--spaces detected: %s', config.get('spaces')) + self._args_to_config(config, argname='spaces', configname='spaces', + logstring='Parameter -s/--spaces detected: {}') - if 'print_all' in self.args and self.args.print_all: - config.update({'print_all': self.args.print_all}) - logger.info('Parameter --print-all detected: %s', config.get('print_all')) + self._args_to_config(config, argname='print_all', configname='print_all', + logstring='Parameter --print-all detected ...') - if 'hyperopt_jobs' in self.args and self.args.hyperopt_jobs: - config.update({'hyperopt_jobs': self.args.hyperopt_jobs}) - logger.info('Parameter -j/--job-workers detected: %s', config.get('hyperopt_jobs')) + self._args_to_config(config, argname='hyperopt_jobs', configname='hyperopt_jobs', + logstring='Parameter -j/--job-workers detected: {}') - if 'refresh_pairs' in self.args and self.args.refresh_pairs: - config.update({'refresh_pairs': True}) - logger.info('Parameter -r/--refresh-pairs-cached detected ...') + self._args_to_config(config, argname='refresh_pairs', configname='refresh_pairs', + logstring='Parameter -r/--refresh-pairs-cached detected ...') - if 'hyperopt_random_state' in self.args and self.args.hyperopt_random_state is not None: - config.update({'hyperopt_random_state': self.args.hyperopt_random_state}) - logger.info("Parameter --random-state detected: %s", - config.get('hyperopt_random_state')) + self._args_to_config(config, argname='hyperopt_random_state', + configname='hyperopt_random_state', + logstring='Parameter --random-state detected: {}') return config From a0413b5d910e22fbb1a168cb7949c7a6a176b27d Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 24 Apr 2019 21:12:23 +0200 Subject: [PATCH 04/20] Only log one message per call --- freqtrade/tests/optimize/test_hyperopt.py | 5 +++-- freqtrade/tests/test_configuration.py | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/freqtrade/tests/optimize/test_hyperopt.py b/freqtrade/tests/optimize/test_hyperopt.py index 063d0e791..d45f806e5 100644 --- a/freqtrade/tests/optimize/test_hyperopt.py +++ b/freqtrade/tests/optimize/test_hyperopt.py @@ -137,7 +137,8 @@ def test_setup_hyperopt_configuration_with_arguments(mocker, default_conf, caplo ) assert 'epochs' in config - assert log_has('Parameter --epochs detected ...', caplog.record_tuples) + assert log_has('Parameter --epochs detected ... Will run Hyperopt with for 1000 epochs ...', + caplog.record_tuples) assert 'spaces' in config assert log_has( @@ -145,7 +146,7 @@ def test_setup_hyperopt_configuration_with_arguments(mocker, default_conf, caplo caplog.record_tuples ) assert 'print_all' in config - assert log_has('Parameter --print-all detected: True', caplog.record_tuples) + assert log_has('Parameter --print-all detected ...', caplog.record_tuples) def test_hyperoptresolver(mocker, default_conf, caplog) -> None: diff --git a/freqtrade/tests/test_configuration.py b/freqtrade/tests/test_configuration.py index 09041dd3d..663b4fbad 100644 --- a/freqtrade/tests/test_configuration.py +++ b/freqtrade/tests/test_configuration.py @@ -463,8 +463,8 @@ def test_hyperopt_with_arguments(mocker, default_conf, caplog) -> None: assert 'epochs' in config assert int(config['epochs']) == 10 - assert log_has('Parameter --epochs detected ...', caplog.record_tuples) - assert log_has('Will run Hyperopt with for 10 epochs ...', caplog.record_tuples) + assert log_has('Parameter --epochs detected ... Will run Hyperopt with for 10 epochs ...', + caplog.record_tuples) assert 'spaces' in config assert config['spaces'] == ['all'] From ca3b8ef2e7f1c9d745187bcbc59c4ae6dfc343b3 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 24 Apr 2019 21:13:57 +0200 Subject: [PATCH 05/20] Remove duplicate argument --- freqtrade/configuration.py | 43 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/freqtrade/configuration.py b/freqtrade/configuration.py index 2b9b02630..5d4b1b9af 100644 --- a/freqtrade/configuration.py +++ b/freqtrade/configuration.py @@ -216,7 +216,7 @@ class Configuration(object): logger.info(f'Created data directory: {datadir}') return datadir - def _args_to_config(self, config, argname, configname, logstring, logfun=None) -> None: + def _args_to_config(self, config, argname, logstring, logfun=None) -> None: """ logfun is applied to the configuration entry before passing that entry to the log string using .format(). @@ -224,11 +224,11 @@ class Configuration(object): """ if argname in self.args and getattr(self.args, argname): - config.update({configname: getattr(self.args, argname)}) + config.update({argname: getattr(self.args, argname)}) if logfun: - logger.info(logstring.format(logfun(config[configname]))) + logger.info(logstring.format(logfun(config[argname]))) else: - logger.info(logstring.format(config[configname])) + logger.info(logstring.format(config[argname])) def _load_backtesting_config(self, config: Dict[str, Any]) -> Dict[str, Any]: """ @@ -242,10 +242,10 @@ class Configuration(object): logger.info('Parameter -i/--ticker-interval detected ...') logger.info('Using ticker_interval: %s ...', config.get('ticker_interval')) - self._args_to_config(config, argname='live', configname='live', + self._args_to_config(config, argname='live', logstring='Parameter -l/--live detected ...') - self._args_to_config(config, argname='position_stacking', configname='position_stacking', + self._args_to_config(config, argname='position_stacking', logstring='Parameter --enable-position-stacking detected ...') if 'use_max_market_positions' in self.args and not self.args.use_max_market_positions: @@ -259,11 +259,11 @@ class Configuration(object): else: logger.info('Using max_open_trades: %s ...', config.get('max_open_trades')) - self._args_to_config(config, argname='stake_amount', configname='stake_amount', + self._args_to_config(config, argname='stake_amount', logstring='Parameter --stake_amount detected, ' 'overriding stake_amount to: {} ...') - self._args_to_config(config, argname='timerange', configname='timerange', + self._args_to_config(config, argname='timerange', logstring='Parameter --timerange detected: {} ...') if 'datadir' in self.args and self.args.datadir: @@ -272,19 +272,19 @@ class Configuration(object): config.update({'datadir': self._create_datadir(config, None)}) logger.info('Using data folder: %s ...', config.get('datadir')) - self._args_to_config(config, argname='refresh_pairs', configname='refresh_pairs', + self._args_to_config(config, argname='refresh_pairs', logstring='Parameter -r/--refresh-pairs-cached detected ...') - self._args_to_config(config, argname='strategy_list', configname='strategy_list', + self._args_to_config(config, argname='strategy_list', logstring='Using strategy list of {} Strategies', logfun=len) - self._args_to_config(config, argname='ticker_interval', configname='ticker_interval', + self._args_to_config(config, argname='ticker_interval', logstring='Overriding ticker interval with Command line argument') - self._args_to_config(config, argname='export', configname='export', + self._args_to_config(config, argname='export', logstring='Parameter --export detected: {} ...') - self._args_to_config(config, argname='exportfilename', configname='exportfilename', + self._args_to_config(config, argname='exportfilename', logstring='Storing backtest results to {} ...') return config @@ -295,7 +295,7 @@ class Configuration(object): :return: configuration as dictionary """ - self._args_to_config(config, argname='timerange', configname='timerange', + self._args_to_config(config, argname='timerange', logstring='Parameter --timerange detected: {} ...') if 'stoploss_range' in self.args and self.args.stoploss_range: @@ -305,7 +305,7 @@ class Configuration(object): config['edge'].update({'stoploss_range_step': txt_range[2]}) logger.info('Parameter --stoplosses detected: %s ...', self.args.stoploss_range) - self._args_to_config(config, argname='refresh_pairs', configname='refresh_pairs', + self._args_to_config(config, argname='refresh_pairs', logstring='Parameter -r/--refresh-pairs-cached detected ...') return config @@ -316,28 +316,27 @@ class Configuration(object): :return: configuration as dictionary """ - self._args_to_config(config, argname='hyperopt', configname='hyperopt', + self._args_to_config(config, argname='hyperopt', logstring='Using Hyperopt file {}') - self._args_to_config(config, argname='epochs', configname='epochs', + self._args_to_config(config, argname='epochs', logstring='Parameter --epochs detected ... ' 'Will run Hyperopt with for {} epochs ...' ) - self._args_to_config(config, argname='spaces', configname='spaces', + self._args_to_config(config, argname='spaces', logstring='Parameter -s/--spaces detected: {}') - self._args_to_config(config, argname='print_all', configname='print_all', + self._args_to_config(config, argname='print_all', logstring='Parameter --print-all detected ...') - self._args_to_config(config, argname='hyperopt_jobs', configname='hyperopt_jobs', + self._args_to_config(config, argname='hyperopt_jobs', logstring='Parameter -j/--job-workers detected: {}') - self._args_to_config(config, argname='refresh_pairs', configname='refresh_pairs', + self._args_to_config(config, argname='refresh_pairs', logstring='Parameter -r/--refresh-pairs-cached detected ...') self._args_to_config(config, argname='hyperopt_random_state', - configname='hyperopt_random_state', logstring='Parameter --random-state detected: {}') return config From 87329c689d3345354dd49d6676edb8503eac9998 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 24 Apr 2019 21:24:00 +0200 Subject: [PATCH 06/20] Change ticker_interval too --- freqtrade/configuration.py | 7 +++---- freqtrade/tests/optimize/test_backtesting.py | 17 ++++++----------- freqtrade/tests/optimize/test_edge_cli.py | 18 ++++++++---------- freqtrade/tests/optimize/test_hyperopt.py | 11 ++++------- freqtrade/tests/test_configuration.py | 14 ++++---------- 5 files changed, 25 insertions(+), 42 deletions(-) diff --git a/freqtrade/configuration.py b/freqtrade/configuration.py index 5d4b1b9af..eea0bf5ae 100644 --- a/freqtrade/configuration.py +++ b/freqtrade/configuration.py @@ -237,10 +237,9 @@ class Configuration(object): """ # This will override the strategy configuration - if 'ticker_interval' in self.args and self.args.ticker_interval: - config.update({'ticker_interval': self.args.ticker_interval}) - logger.info('Parameter -i/--ticker-interval detected ...') - logger.info('Using ticker_interval: %s ...', config.get('ticker_interval')) + self._args_to_config(config, argname='ticker_interval', + logstring='Parameter -i/--ticker-interval detected ... ' + 'Using ticker_interval: {} ...') self._args_to_config(config, argname='live', logstring='Parameter -l/--live detected ...') diff --git a/freqtrade/tests/optimize/test_backtesting.py b/freqtrade/tests/optimize/test_backtesting.py index af0b07d6f..281ce2bfe 100644 --- a/freqtrade/tests/optimize/test_backtesting.py +++ b/freqtrade/tests/optimize/test_backtesting.py @@ -23,7 +23,7 @@ from freqtrade.optimize.backtesting import (Backtesting, setup_configuration, from freqtrade.state import RunMode from freqtrade.strategy.default_strategy import DefaultStrategy from freqtrade.strategy.interface import SellType -from freqtrade.tests.conftest import log_has, patch_exchange +from freqtrade.tests.conftest import log_has, log_has_re, patch_exchange def get_args(args) -> List[str]: @@ -190,7 +190,7 @@ def test_setup_configuration_without_arguments(mocker, default_conf, caplog) -> caplog.record_tuples ) assert 'ticker_interval' in config - assert not log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples) + assert not log_has_re('Parameter -i/--ticker-interval detected .*', caplog.record_tuples) assert 'live' not in config assert not log_has('Parameter -l/--live detected ...', caplog.record_tuples) @@ -242,11 +242,8 @@ def test_setup_bt_configuration_with_arguments(mocker, default_conf, caplog) -> caplog.record_tuples ) assert 'ticker_interval' in config - assert log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples) - assert log_has( - 'Using ticker_interval: 1m ...', - caplog.record_tuples - ) + assert log_has('Parameter -i/--ticker-interval detected ... Using ticker_interval: 1m ...', + caplog.record_tuples) assert 'live' in config assert log_has('Parameter -l/--live detected ...', caplog.record_tuples) @@ -853,8 +850,7 @@ def test_backtest_start_live(default_conf, mocker, caplog): start(args) # check the logs, that will contain the backtest result exists = [ - 'Parameter -i/--ticker-interval detected ...', - 'Using ticker_interval: 1m ...', + 'Parameter -i/--ticker-interval detected ... Using ticker_interval: 1m ...', 'Parameter -l/--live detected ...', 'Ignoring max_open_trades (--disable-max-market-positions was used) ...', 'Parameter --timerange detected: -100 ...', @@ -912,8 +908,7 @@ def test_backtest_start_multi_strat(default_conf, mocker, caplog): # check the logs, that will contain the backtest result exists = [ - 'Parameter -i/--ticker-interval detected ...', - 'Using ticker_interval: 1m ...', + 'Parameter -i/--ticker-interval detected ... Using ticker_interval: 1m ...', 'Parameter -l/--live detected ...', 'Ignoring max_open_trades (--disable-max-market-positions was used) ...', 'Parameter --timerange detected: -100 ...', diff --git a/freqtrade/tests/optimize/test_edge_cli.py b/freqtrade/tests/optimize/test_edge_cli.py index a58620139..488d552c8 100644 --- a/freqtrade/tests/optimize/test_edge_cli.py +++ b/freqtrade/tests/optimize/test_edge_cli.py @@ -1,14 +1,15 @@ # pragma pylint: disable=missing-docstring, C0103, C0330 # pragma pylint: disable=protected-access, too-many-lines, invalid-name, too-many-arguments -from unittest.mock import MagicMock import json from typing import List -from freqtrade.edge import PairInfo +from unittest.mock import MagicMock + from freqtrade.arguments import Arguments -from freqtrade.optimize.edge_cli import (EdgeCli, setup_configuration, start) +from freqtrade.edge import PairInfo +from freqtrade.optimize.edge_cli import EdgeCli, setup_configuration, start from freqtrade.state import RunMode -from freqtrade.tests.conftest import log_has, patch_exchange +from freqtrade.tests.conftest import log_has, log_has_re, patch_exchange def get_args(args) -> List[str]: @@ -40,7 +41,7 @@ def test_setup_configuration_without_arguments(mocker, default_conf, caplog) -> caplog.record_tuples ) assert 'ticker_interval' in config - assert not log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples) + assert not log_has_re('Parameter -i/--ticker-interval detected .*', caplog.record_tuples) assert 'refresh_pairs' not in config assert not log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples) @@ -79,11 +80,8 @@ def test_setup_edge_configuration_with_arguments(mocker, edge_conf, caplog) -> N caplog.record_tuples ) assert 'ticker_interval' in config - assert log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples) - assert log_has( - 'Using ticker_interval: 1m ...', - caplog.record_tuples - ) + assert log_has('Parameter -i/--ticker-interval detected ... Using ticker_interval: 1m ...', + caplog.record_tuples) assert 'refresh_pairs' in config assert log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples) diff --git a/freqtrade/tests/optimize/test_hyperopt.py b/freqtrade/tests/optimize/test_hyperopt.py index d45f806e5..aa3381e95 100644 --- a/freqtrade/tests/optimize/test_hyperopt.py +++ b/freqtrade/tests/optimize/test_hyperopt.py @@ -14,7 +14,7 @@ from freqtrade.optimize.hyperopt import Hyperopt, start, setup_configuration from freqtrade.optimize.default_hyperopt import DefaultHyperOpts from freqtrade.resolvers import StrategyResolver, HyperOptResolver from freqtrade.state import RunMode -from freqtrade.tests.conftest import log_has, patch_exchange +from freqtrade.tests.conftest import log_has, log_has_re, patch_exchange from freqtrade.tests.optimize.test_backtesting import get_args @@ -64,7 +64,7 @@ def test_setup_hyperopt_configuration_without_arguments(mocker, default_conf, ca caplog.record_tuples ) assert 'ticker_interval' in config - assert not log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples) + assert not log_has_re('Parameter -i/--ticker-interval detected .*', caplog.record_tuples) assert 'live' not in config assert not log_has('Parameter -l/--live detected ...', caplog.record_tuples) @@ -114,11 +114,8 @@ def test_setup_hyperopt_configuration_with_arguments(mocker, default_conf, caplo caplog.record_tuples ) assert 'ticker_interval' in config - assert log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples) - assert log_has( - 'Using ticker_interval: 1m ...', - caplog.record_tuples - ) + assert log_has('Parameter -i/--ticker-interval detected ... Using ticker_interval: 1m ...', + caplog.record_tuples) assert 'position_stacking' in config assert log_has('Parameter --enable-position-stacking detected ...', caplog.record_tuples) diff --git a/freqtrade/tests/test_configuration.py b/freqtrade/tests/test_configuration.py index 663b4fbad..aee0dfadd 100644 --- a/freqtrade/tests/test_configuration.py +++ b/freqtrade/tests/test_configuration.py @@ -360,11 +360,8 @@ def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> Non caplog.record_tuples ) assert 'ticker_interval' in config - assert log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples) - assert log_has( - 'Using ticker_interval: 1m ...', - caplog.record_tuples - ) + assert log_has('Parameter -i/--ticker-interval detected ... Using ticker_interval: 1m ...', + caplog.record_tuples) assert 'live' in config assert log_has('Parameter -l/--live detected ...', caplog.record_tuples) @@ -425,11 +422,8 @@ def test_setup_configuration_with_stratlist(mocker, default_conf, caplog) -> Non caplog.record_tuples ) assert 'ticker_interval' in config - assert log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples) - assert log_has( - 'Using ticker_interval: 1m ...', - caplog.record_tuples - ) + assert log_has('Parameter -i/--ticker-interval detected ... Using ticker_interval: 1m ...', + caplog.record_tuples) assert 'strategy_list' in config assert log_has('Using strategy list of 2 Strategies', caplog.record_tuples) From 86313b337a6edb075066ea120d63a93a7219ce39 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 24 Apr 2019 21:27:32 +0200 Subject: [PATCH 07/20] Combine optimize configurations, eliminate duplicates --- freqtrade/configuration.py | 42 ++++++-------------------------------- 1 file changed, 6 insertions(+), 36 deletions(-) diff --git a/freqtrade/configuration.py b/freqtrade/configuration.py index eea0bf5ae..062c877ec 100644 --- a/freqtrade/configuration.py +++ b/freqtrade/configuration.py @@ -95,14 +95,8 @@ class Configuration(object): # Load Common configuration config = self._load_common_config(config) - # Load Backtesting - config = self._load_backtesting_config(config) - - # Load Edge - config = self._load_edge_config(config) - - # Load Hyperopt - config = self._load_hyperopt_config(config) + # Load Optimize configurations + config = self._load_optimize_config(config) # Set runmode if not self.runmode: @@ -230,9 +224,9 @@ class Configuration(object): else: logger.info(logstring.format(config[argname])) - def _load_backtesting_config(self, config: Dict[str, Any]) -> Dict[str, Any]: + def _load_optimize_config(self, config: Dict[str, Any]) -> Dict[str, Any]: """ - Extract information for sys.argv and load Backtesting configuration + Extract information for sys.argv and load Optimize configuration :return: configuration as dictionary """ @@ -286,17 +280,7 @@ class Configuration(object): self._args_to_config(config, argname='exportfilename', logstring='Storing backtest results to {} ...') - return config - - def _load_edge_config(self, config: Dict[str, Any]) -> Dict[str, Any]: - """ - Extract information for sys.argv and load Edge configuration - :return: configuration as dictionary - """ - - self._args_to_config(config, argname='timerange', - logstring='Parameter --timerange detected: {} ...') - + # Edge section: if 'stoploss_range' in self.args and self.args.stoploss_range: txt_range = eval(self.args.stoploss_range) config['edge'].update({'stoploss_range_min': txt_range[0]}) @@ -304,17 +288,7 @@ class Configuration(object): config['edge'].update({'stoploss_range_step': txt_range[2]}) logger.info('Parameter --stoplosses detected: %s ...', self.args.stoploss_range) - self._args_to_config(config, argname='refresh_pairs', - logstring='Parameter -r/--refresh-pairs-cached detected ...') - - return config - - def _load_hyperopt_config(self, config: Dict[str, Any]) -> Dict[str, Any]: - """ - Extract information for sys.argv and load Hyperopt configuration - :return: configuration as dictionary - """ - + # Hyperopt section self._args_to_config(config, argname='hyperopt', logstring='Using Hyperopt file {}') @@ -332,12 +306,8 @@ class Configuration(object): self._args_to_config(config, argname='hyperopt_jobs', logstring='Parameter -j/--job-workers detected: {}') - self._args_to_config(config, argname='refresh_pairs', - logstring='Parameter -r/--refresh-pairs-cached detected ...') - self._args_to_config(config, argname='hyperopt_random_state', logstring='Parameter --random-state detected: {}') - return config def _validate_config_schema(self, conf: Dict[str, Any]) -> Dict[str, Any]: From b4630c403d2aa88f1be79b80ec9510006a18e388 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 24 Apr 2019 21:32:33 +0200 Subject: [PATCH 08/20] Add typehints --- freqtrade/configuration.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/freqtrade/configuration.py b/freqtrade/configuration.py index 062c877ec..0eb773eb5 100644 --- a/freqtrade/configuration.py +++ b/freqtrade/configuration.py @@ -7,7 +7,7 @@ import os import sys from argparse import Namespace from logging.handlers import RotatingFileHandler -from typing import Any, Dict, List, Optional +from typing import Any, Callable, Dict, List, Optional from jsonschema import Draft4Validator, validators from jsonschema.exceptions import ValidationError, best_match @@ -17,7 +17,6 @@ from freqtrade.exchange import is_exchange_supported, supported_exchanges from freqtrade.misc import deep_merge_dicts from freqtrade.state import RunMode - logger = logging.getLogger(__name__) @@ -210,11 +209,16 @@ class Configuration(object): logger.info(f'Created data directory: {datadir}') return datadir - def _args_to_config(self, config, argname, logstring, logfun=None) -> None: + def _args_to_config(self, config: Dict[str, Any], argname: str, + logstring: str, logfun=Optional[Callable]) -> None: """ - 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) + :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): From 22eb6cb5fa181e7fd1b2d64cdd53ccfc23a41325 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 24 Apr 2019 22:08:56 +0200 Subject: [PATCH 09/20] Fix typo in args_to_config --- freqtrade/configuration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/configuration.py b/freqtrade/configuration.py index 0eb773eb5..54862ff70 100644 --- a/freqtrade/configuration.py +++ b/freqtrade/configuration.py @@ -210,7 +210,7 @@ class Configuration(object): return datadir def _args_to_config(self, config: Dict[str, Any], argname: str, - logstring: str, logfun=Optional[Callable]) -> None: + logstring: str, logfun: Optional[Callable] = None) -> None: """ :param config: Configuration dictionary :param argname: Argumentname in self.args - will be copied to config dict. From eaf5547b8802aeabde208f12ed62b2b002a1ac18 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Fri, 26 Apr 2019 12:42:07 +0000 Subject: [PATCH 10/20] Update ccxt from 1.18.489 to 1.18.491 --- requirements-pi.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-pi.txt b/requirements-pi.txt index 672ab9767..c121d8cc9 100644 --- a/requirements-pi.txt +++ b/requirements-pi.txt @@ -1,6 +1,6 @@ # requirements without requirements installable via conda # mainly used for Raspberry pi installs -ccxt==1.18.489 +ccxt==1.18.491 SQLAlchemy==1.3.3 python-telegram-bot==11.1.0 arrow==0.13.1 From bf2a39b76da9d0c0ff99e7efdc79257f79d6ffa6 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 26 Apr 2019 19:50:18 +0200 Subject: [PATCH 11/20] Fix add requirements-pi.txt in dockerfile earlier Avoids docker-build failure --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index e36766530..202989e43 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ RUN cd /tmp && /tmp/install_ta-lib.sh && rm -r /tmp/*ta-lib* ENV LD_LIBRARY_PATH /usr/local/lib # Install dependencies -COPY requirements.txt /freqtrade/ +COPY requirements.txt requirements-pi.txt /freqtrade/ RUN pip install numpy --no-cache-dir \ && pip install -r requirements.txt --no-cache-dir From 99b08fbd13efef4645045556f2e33e143cada380 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 26 Apr 2019 19:51:24 +0200 Subject: [PATCH 12/20] Remove unused Hyperopt test lines --- freqtrade/tests/optimize/test_hyperopt.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/freqtrade/tests/optimize/test_hyperopt.py b/freqtrade/tests/optimize/test_hyperopt.py index 063d0e791..a777f93a8 100644 --- a/freqtrade/tests/optimize/test_hyperopt.py +++ b/freqtrade/tests/optimize/test_hyperopt.py @@ -1,7 +1,7 @@ # pragma pylint: disable=missing-docstring,W0212,C0103 -from datetime import datetime import json import os +from datetime import datetime from unittest.mock import MagicMock import pandas as pd @@ -10,9 +10,10 @@ import pytest from freqtrade import DependencyException from freqtrade.data.converter import parse_ticker_dataframe from freqtrade.data.history import load_tickerdata_file -from freqtrade.optimize.hyperopt import Hyperopt, start, setup_configuration from freqtrade.optimize.default_hyperopt import DefaultHyperOpts -from freqtrade.resolvers import StrategyResolver, HyperOptResolver +from freqtrade.optimize.hyperopt import (HYPEROPT_LOCKFILE, Hyperopt, + setup_configuration, start) +from freqtrade.resolvers import HyperOptResolver from freqtrade.state import RunMode from freqtrade.tests.conftest import log_has, patch_exchange from freqtrade.tests.optimize.test_backtesting import get_args @@ -185,7 +186,6 @@ def test_start(mocker, default_conf, caplog) -> None: '--epochs', '5' ] args = get_args(args) - StrategyResolver({'strategy': 'DefaultStrategy'}) start(args) import pprint @@ -214,7 +214,6 @@ def test_start_failure(mocker, default_conf, caplog) -> None: '--epochs', '5' ] args = get_args(args) - StrategyResolver({'strategy': 'DefaultStrategy'}) with pytest.raises(DependencyException): start(args) assert log_has( @@ -224,7 +223,6 @@ def test_start_failure(mocker, default_conf, caplog) -> None: def test_loss_calculation_prefer_correct_trade_count(hyperopt) -> None: - StrategyResolver({'strategy': 'DefaultStrategy'}) correct = hyperopt.calculate_loss(1, hyperopt.target_trades, 20) over = hyperopt.calculate_loss(1, hyperopt.target_trades + 100, 20) From dc12cacd50114394950d195d0ab33b6785c6c507 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 26 Apr 2019 19:57:09 +0200 Subject: [PATCH 13/20] Rename requirements-pi to requirements.common --- .pyup.yml | 2 +- Dockerfile | 2 +- Dockerfile.pi | 4 ++-- docs/installation.md | 2 +- requirements-pi.txt => requirements-common.txt | 0 requirements.txt | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) rename requirements-pi.txt => requirements-common.txt (100%) diff --git a/.pyup.yml b/.pyup.yml index 462ae5783..3494a3fd3 100644 --- a/.pyup.yml +++ b/.pyup.yml @@ -22,7 +22,7 @@ requirements: - requirements.txt - requirements-dev.txt - requirements-plot.txt - - requirements-pi.txt + - requirements-common.txt # configure the branch prefix the bot is using diff --git a/Dockerfile b/Dockerfile index 202989e43..7a0298719 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ RUN cd /tmp && /tmp/install_ta-lib.sh && rm -r /tmp/*ta-lib* ENV LD_LIBRARY_PATH /usr/local/lib # Install dependencies -COPY requirements.txt requirements-pi.txt /freqtrade/ +COPY requirements.txt requirements-common.txt /freqtrade/ RUN pip install numpy --no-cache-dir \ && pip install -r requirements.txt --no-cache-dir diff --git a/Dockerfile.pi b/Dockerfile.pi index 5184e2d37..1b9c4c579 100644 --- a/Dockerfile.pi +++ b/Dockerfile.pi @@ -27,9 +27,9 @@ RUN wget https://github.com/jjhelmus/berryconda/releases/download/v2.0.0/Berryco && rm Berryconda3-2.0.0-Linux-armv7l.sh # Install dependencies -COPY requirements-pi.txt /freqtrade/ +COPY requirements-common.txt /freqtrade/ RUN ~/berryconda3/bin/conda install -y numpy pandas scipy \ - && ~/berryconda3/bin/pip install -r requirements-pi.txt --no-cache-dir + && ~/berryconda3/bin/pip install -r requirements-common.txt --no-cache-dir # Install and execute COPY . /freqtrade/ diff --git a/docs/installation.md b/docs/installation.md index 23a6cbd23..7060d7b39 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -326,7 +326,7 @@ conda activate freqtrade conda install scipy pandas numpy sudo apt install libffi-dev -python3 -m pip install -r requirements-pi.txt +python3 -m pip install -r requirements-common.txt python3 -m pip install -e . ``` diff --git a/requirements-pi.txt b/requirements-common.txt similarity index 100% rename from requirements-pi.txt rename to requirements-common.txt diff --git a/requirements.txt b/requirements.txt index 4c2376078..78585f8f5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # Load common requirements --r requirements-pi.txt +-r requirements-common.txt numpy==1.16.3 pandas==0.24.2 From 40c02073776418614e8c223bbdaf2456beccebb8 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 26 Apr 2019 19:59:05 +0200 Subject: [PATCH 14/20] revert erroneous refactor --- freqtrade/tests/optimize/test_hyperopt.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/freqtrade/tests/optimize/test_hyperopt.py b/freqtrade/tests/optimize/test_hyperopt.py index a777f93a8..21db63636 100644 --- a/freqtrade/tests/optimize/test_hyperopt.py +++ b/freqtrade/tests/optimize/test_hyperopt.py @@ -11,8 +11,7 @@ from freqtrade import DependencyException from freqtrade.data.converter import parse_ticker_dataframe from freqtrade.data.history import load_tickerdata_file from freqtrade.optimize.default_hyperopt import DefaultHyperOpts -from freqtrade.optimize.hyperopt import (HYPEROPT_LOCKFILE, Hyperopt, - setup_configuration, start) +from freqtrade.optimize.hyperopt import Hyperopt, setup_configuration, start from freqtrade.resolvers import HyperOptResolver from freqtrade.state import RunMode from freqtrade.tests.conftest import log_has, patch_exchange From 21b31f11b8d3e87eceab3f9973316711ffc81c64 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Sat, 27 Apr 2019 12:42:05 +0000 Subject: [PATCH 15/20] Update ccxt from 1.18.491 to 1.18.492 --- requirements-common.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-common.txt b/requirements-common.txt index c121d8cc9..51bc88480 100644 --- a/requirements-common.txt +++ b/requirements-common.txt @@ -1,6 +1,6 @@ # requirements without requirements installable via conda # mainly used for Raspberry pi installs -ccxt==1.18.491 +ccxt==1.18.492 SQLAlchemy==1.3.3 python-telegram-bot==11.1.0 arrow==0.13.1 From 59bd081e92cd4fdfef54e119a9a823205e1554c6 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 29 Apr 2019 12:42:12 +0000 Subject: [PATCH 16/20] Update ccxt from 1.18.492 to 1.18.493 --- requirements-common.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-common.txt b/requirements-common.txt index 51bc88480..71680cc7b 100644 --- a/requirements-common.txt +++ b/requirements-common.txt @@ -1,6 +1,6 @@ # requirements without requirements installable via conda # mainly used for Raspberry pi installs -ccxt==1.18.492 +ccxt==1.18.493 SQLAlchemy==1.3.3 python-telegram-bot==11.1.0 arrow==0.13.1 From 537c03504f62c5f59a59fd11b912470ae58a4e96 Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Tue, 30 Apr 2019 10:29:49 +0300 Subject: [PATCH 17/20] fix #1810 --- freqtrade/worker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/worker.py b/freqtrade/worker.py index c7afe5c97..60c069e11 100755 --- a/freqtrade/worker.py +++ b/freqtrade/worker.py @@ -71,7 +71,7 @@ class Worker(object): while True: state = self._worker(old_state=state) if state == State.RELOAD_CONF: - self.freqtrade = self._reconfigure() + self._reconfigure() def _worker(self, old_state: State, throttle_secs: Optional[float] = None) -> State: """ From 615067973657a459de85c00f069c647986d8a761 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Tue, 30 Apr 2019 12:42:06 +0000 Subject: [PATCH 18/20] Update ccxt from 1.18.493 to 1.18.496 --- requirements-common.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-common.txt b/requirements-common.txt index 71680cc7b..e91b47d2f 100644 --- a/requirements-common.txt +++ b/requirements-common.txt @@ -1,6 +1,6 @@ # requirements without requirements installable via conda # mainly used for Raspberry pi installs -ccxt==1.18.493 +ccxt==1.18.496 SQLAlchemy==1.3.3 python-telegram-bot==11.1.0 arrow==0.13.1 From 5665426e6ba752c29be6dd9230c91ab08c4046c5 Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Tue, 30 Apr 2019 19:47:55 +0300 Subject: [PATCH 19/20] better type hints in worker --- freqtrade/worker.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/freqtrade/worker.py b/freqtrade/worker.py index 60c069e11..19a570505 100755 --- a/freqtrade/worker.py +++ b/freqtrade/worker.py @@ -39,7 +39,7 @@ class Worker(object): logger.debug("sd_notify: READY=1") self._sd_notify.notify("READY=1") - def _init(self, reconfig: bool): + def _init(self, reconfig: bool) -> None: """ Also called from the _reconfigure() method (with reconfig=True). """ @@ -63,17 +63,17 @@ class Worker(object): return self.freqtrade.state @state.setter - def state(self, value: State): + def state(self, value: State) -> None: self.freqtrade.state = value - def run(self): + def run(self) -> None: state = None while True: state = self._worker(old_state=state) if state == State.RELOAD_CONF: self._reconfigure() - def _worker(self, old_state: State, throttle_secs: Optional[float] = None) -> State: + def _worker(self, old_state: Optional[State], throttle_secs: Optional[float] = None) -> State: """ Trading routine that must be run at each loop :param old_state: the previous service state from the previous call @@ -148,7 +148,7 @@ class Worker(object): # state_changed = True return state_changed - def _reconfigure(self): + def _reconfigure(self) -> None: """ Cleans up current freqtradebot instance, reloads the configuration and replaces it with the new instance @@ -174,7 +174,7 @@ class Worker(object): logger.debug("sd_notify: READY=1") self._sd_notify.notify("READY=1") - def exit(self): + def exit(self) -> None: # Tell systemd that we are exiting now if self._sd_notify: logger.debug("sd_notify: STOPPING=1") From b24bbb2cb107cb095dfc628106aac2d2c6cfaf8e Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 30 Apr 2019 19:32:03 +0200 Subject: [PATCH 20/20] Improve test for reload_conf with a "realistic" workflow --- freqtrade/tests/test_main.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/freqtrade/tests/test_main.py b/freqtrade/tests/test_main.py index fc5d2e378..e4ffc5fae 100644 --- a/freqtrade/tests/test_main.py +++ b/freqtrade/tests/test_main.py @@ -7,10 +7,11 @@ import pytest from freqtrade import OperationalException from freqtrade.arguments import Arguments -from freqtrade.worker import Worker +from freqtrade.freqtradebot import FreqtradeBot from freqtrade.main import main from freqtrade.state import State from freqtrade.tests.conftest import log_has, patch_exchange +from freqtrade.worker import Worker def test_parse_args_backtesting(mocker) -> None: @@ -107,24 +108,30 @@ def test_main_operational_exception(mocker, default_conf, caplog) -> None: def test_main_reload_conf(mocker, default_conf, caplog) -> None: patch_exchange(mocker) mocker.patch('freqtrade.freqtradebot.FreqtradeBot.cleanup', MagicMock()) - mocker.patch('freqtrade.worker.Worker._worker', MagicMock(return_value=State.RELOAD_CONF)) + # Simulate Running, reload, running workflow + worker_mock = MagicMock(side_effect=[State.RUNNING, + State.RELOAD_CONF, + State.RUNNING, + OperationalException("Oh snap!")]) + mocker.patch('freqtrade.worker.Worker._worker', worker_mock) mocker.patch( 'freqtrade.configuration.Configuration._load_config_file', lambda *args, **kwargs: default_conf ) + reconfigure_mock = mocker.patch('freqtrade.main.Worker._reconfigure', MagicMock()) + mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock()) mocker.patch('freqtrade.freqtradebot.persistence.init', MagicMock()) - # Raise exception as side effect to avoid endless loop - reconfigure_mock = mocker.patch( - 'freqtrade.main.Worker._reconfigure', MagicMock(side_effect=Exception) - ) - + args = Arguments(['-c', 'config.json.example'], '').get_parsed_arg() + worker = Worker(args=args, config=default_conf) with pytest.raises(SystemExit): main(['-c', 'config.json.example']) - assert reconfigure_mock.call_count == 1 assert log_has('Using config: config.json.example ...', caplog.record_tuples) + assert worker_mock.call_count == 4 + assert reconfigure_mock.call_count == 1 + assert isinstance(worker.freqtrade, FreqtradeBot) def test_reconfigure(mocker, default_conf) -> None: