diff --git a/freqtrade/configuration/check_exchange.py b/freqtrade/configuration/check_exchange.py index 5e811fb81..5d963db47 100644 --- a/freqtrade/configuration/check_exchange.py +++ b/freqtrade/configuration/check_exchange.py @@ -21,7 +21,8 @@ def check_exchange(config: Dict[str, Any], check_for_bad: bool = True) -> bool: and thus is not known for the Freqtrade at all. """ - if config['runmode'] in [RunMode.PLOT] and not config.get('exchange', {}).get('name'): + if (config['runmode'] in [RunMode.PLOT, RunMode.UTIL_NO_EXCHANGE] + and not config.get('exchange', {}).get('name')): # Skip checking exchange in plot mode, since it requires no exchange return True logger.info("Checking exchange...") diff --git a/freqtrade/configuration/config_validation.py b/freqtrade/configuration/config_validation.py index 93d93263f..8083264e2 100644 --- a/freqtrade/configuration/config_validation.py +++ b/freqtrade/configuration/config_validation.py @@ -118,7 +118,8 @@ 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]: + if conf.get('runmode', RunMode.OTHER) in [RunMode.OTHER, RunMode.PLOT, + RunMode.UTIL_NO_EXCHANGE, RunMode.UTIL_EXCHANGE]: return if (conf.get('pairlist', {}).get('method', 'StaticPairList') == 'StaticPairList' diff --git a/freqtrade/configuration/configuration.py b/freqtrade/configuration/configuration.py index be1c7ab4e..4637e3e5d 100644 --- a/freqtrade/configuration/configuration.py +++ b/freqtrade/configuration/configuration.py @@ -17,7 +17,7 @@ from freqtrade.configuration.directory_operations import (create_datadir, from freqtrade.configuration.load_config import load_config_file from freqtrade.loggers import setup_logging from freqtrade.misc import deep_merge_dicts, json_load -from freqtrade.state import RunMode +from freqtrade.state import RunMode, TRADING_MODES, NON_UTIL_MODES logger = logging.getLogger(__name__) @@ -98,14 +98,16 @@ class Configuration: # Keep a copy of the original configuration file config['original_config'] = deepcopy(config) + self._process_runmode(config) + self._process_common_options(config) + self._process_trading_options(config) + self._process_optimize_options(config) self._process_plot_options(config) - self._process_runmode(config) - # Check if the exchange set by the user is supported check_exchange(config, config.get('experimental', {}).get('block_bad_exchanges', True)) @@ -130,6 +132,22 @@ class Configuration: setup_logging(config) + def _process_trading_options(self, config: Dict[str, Any]) -> None: + if config['runmode'] not in TRADING_MODES: + return + + if config.get('dry_run', False): + logger.info('Dry run is enabled') + if config.get('db_url') in [None, constants.DEFAULT_DB_PROD_URL]: + # Default to in-memory db for dry_run if not specified + config['db_url'] = constants.DEFAULT_DB_DRYRUN_URL + else: + if not config.get('db_url', None): + config['db_url'] = constants.DEFAULT_DB_PROD_URL + logger.info('Dry run is disabled') + + logger.info(f'Using DB: "{config["db_url"]}"') + def _process_common_options(self, config: Dict[str, Any]) -> None: self._process_logging_options(config) @@ -146,25 +164,9 @@ class Configuration: config.update({'db_url': self.args["db_url"]}) logger.info('Parameter --db-url detected ...') - if config.get('dry_run', False): - logger.info('Dry run is enabled') - if config.get('db_url') in [None, constants.DEFAULT_DB_PROD_URL]: - # Default to in-memory db for dry_run if not specified - config['db_url'] = constants.DEFAULT_DB_DRYRUN_URL - else: - if not config.get('db_url', None): - config['db_url'] = constants.DEFAULT_DB_PROD_URL - logger.info('Dry run is disabled') - - logger.info(f'Using DB: "{config["db_url"]}"') - if config.get('forcebuy_enable', False): logger.warning('`forcebuy` RPC message enabled.') - # Setting max_open_trades to infinite if -1 - if config.get('max_open_trades') == -1: - config['max_open_trades'] = float('inf') - # Support for sd_notify if 'sd_notify' in self.args and self.args["sd_notify"]: config['internals'].update({'sd_notify': True}) @@ -212,6 +214,10 @@ class Configuration: self._args_to_config(config, argname='position_stacking', logstring='Parameter --enable-position-stacking detected ...') + # Setting max_open_trades to infinite if -1 + if config.get('max_open_trades') == -1: + config['max_open_trades'] = float('inf') + if 'use_max_market_positions' in self.args and not self.args["use_max_market_positions"]: config.update({'use_max_market_positions': False}) logger.info('Parameter --disable-max-market-positions detected ...') @@ -220,7 +226,7 @@ class Configuration: config.update({'max_open_trades': self.args["max_open_trades"]}) logger.info('Parameter --max_open_trades detected, ' 'overriding max_open_trades to: %s ...', config.get('max_open_trades')) - else: + elif config['runmode'] in NON_UTIL_MODES: logger.info('Using max_open_trades: %s ...', config.get('max_open_trades')) self._args_to_config(config, argname='stake_amount', diff --git a/freqtrade/state.py b/freqtrade/state.py index d4a2adba0..415f6f5f2 100644 --- a/freqtrade/state.py +++ b/freqtrade/state.py @@ -25,5 +25,12 @@ class RunMode(Enum): BACKTEST = "backtest" EDGE = "edge" HYPEROPT = "hyperopt" + UTIL_EXCHANGE = "util_exchange" + UTIL_NO_EXCHANGE = "util_no_exchange" PLOT = "plot" - OTHER = "other" # Used for plotting scripts and test + OTHER = "other" + + +TRADING_MODES = [RunMode.LIVE, RunMode.DRY_RUN] +OPTIMIZE_MODES = [RunMode.BACKTEST, RunMode.EDGE, RunMode.HYPEROPT] +NON_UTIL_MODES = TRADING_MODES + OPTIMIZE_MODES diff --git a/freqtrade/utils.py b/freqtrade/utils.py index 25e883c76..630de0f5a 100644 --- a/freqtrade/utils.py +++ b/freqtrade/utils.py @@ -74,7 +74,7 @@ def start_download_data(args: Dict[str, Any]) -> None: """ Download data (former download_backtest_data.py script) """ - config = setup_utils_configuration(args, RunMode.OTHER) + config = setup_utils_configuration(args, RunMode.UTIL_EXCHANGE) timerange = TimeRange() if 'days' in config: @@ -123,7 +123,7 @@ def start_list_timeframes(args: Dict[str, Any]) -> None: """ Print ticker intervals (timeframes) available on Exchange """ - config = setup_utils_configuration(args, RunMode.OTHER) + config = setup_utils_configuration(args, RunMode.UTIL_EXCHANGE) # Do not use ticker_interval set in the config config['ticker_interval'] = None @@ -144,7 +144,7 @@ def start_list_markets(args: Dict[str, Any], pairs_only: bool = False) -> None: :param pairs_only: if True print only pairs, otherwise print all instruments (markets) :return: None """ - config = setup_utils_configuration(args, RunMode.OTHER) + config = setup_utils_configuration(args, RunMode.UTIL_EXCHANGE) # Init exchange exchange = ExchangeResolver(config['exchange']['name'], config, validate=False).exchange