def test_load_dry_run(default_conf, mocker, config_value, expected, arglist) -> None: default_conf['dry_run'] = config_value patched_configuration_load_config_file(mocker, default_conf) configuration = Configuration(Arguments(arglist).get_parsed_arg()) validated_conf = configuration.load_config() assert validated_conf.get('dry_run') is expected
def test_load_config_max_open_trades_zero(default_conf, mocker, caplog) -> None: default_conf['max_open_trades'] = 0 patched_configuration_load_config_file(mocker, default_conf) args = Arguments(['trade']).get_parsed_arg() configuration = Configuration(args) validated_conf = configuration.load_config() assert validated_conf['max_open_trades'] == 0 assert 'internals' in validated_conf
def test_load_dry_run(default_conf, mocker, config_value, expected, arglist) -> None: default_conf['dry_run'] = config_value patched_configuration_load_config_file(mocker, default_conf) configuration = Configuration(Arguments(arglist).get_parsed_arg()) validated_conf = configuration.load_config() assert validated_conf['dry_run'] is expected assert validated_conf['runmode'] == (RunMode.DRY_RUN if expected else RunMode.LIVE)
def test_load_config(default_conf, mocker) -> None: del default_conf['strategy_path'] patched_configuration_load_config_file(mocker, default_conf) args = Arguments(['trade']).get_parsed_arg() configuration = Configuration(args) validated_conf = configuration.load_config() assert validated_conf.get('strategy_path') is None assert 'edge' not in validated_conf
def test_load_config_invalid_pair(default_conf) -> None: """ Test the configuration validator with an invalid PAIR format """ conf = deepcopy(default_conf) conf['exchange']['pair_whitelist'].append('ETH-BTC') with pytest.raises(ValidationError, match=r'.*does not match.*'): configuration = Configuration(Namespace()) configuration._validate_config(conf)
def test_load_config_warn_forcebuy(default_conf, mocker, caplog) -> None: default_conf['forcebuy_enable'] = True patched_configuration_load_config_file(mocker, default_conf) args = Arguments(['trade']).get_parsed_arg() configuration = Configuration(args) validated_conf = configuration.load_config() assert validated_conf.get('forcebuy_enable') assert log_has('`forcebuy` RPC message enabled.', caplog)
def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> None: patched_configuration_load_config_file(mocker, default_conf) mocker.patch('freqtrade.configuration.configuration.create_datadir', lambda c, x: x) mocker.patch('freqtrade.configuration.configuration.create_userdata_dir', lambda x, *args, **kwargs: Path(x)) arglist = [ 'backtesting', '--config', 'config.json', '--strategy', 'DefaultStrategy', '--datadir', '/foo/bar', '--userdir', "/tmp/freqtrade", '--ticker-interval', '1m', '--enable-position-stacking', '--disable-max-market-positions', '--timerange', ':100', '--export', '/bar/foo', '--stake-amount', 'unlimited' ] args = Arguments(arglist).get_parsed_arg() configuration = Configuration(args) config = configuration.get_config() assert 'max_open_trades' in config assert 'stake_currency' in config assert 'stake_amount' in config assert 'exchange' in config assert 'pair_whitelist' in config['exchange'] assert 'datadir' in config assert log_has('Using data directory: {} ...'.format("/foo/bar"), caplog) assert log_has( 'Using user-data directory: {} ...'.format(Path("/tmp/freqtrade")), caplog) assert 'user_data_dir' in config assert 'timeframe' in config assert log_has( 'Parameter -i/--timeframe detected ... Using timeframe: 1m ...', caplog) assert 'position_stacking' in config assert log_has('Parameter --enable-position-stacking detected ...', caplog) assert 'use_max_market_positions' in config assert log_has('Parameter --disable-max-market-positions detected ...', caplog) assert log_has('max_open_trades set to unlimited ...', caplog) assert 'timerange' in config assert log_has( 'Parameter --timerange detected: {} ...'.format(config['timerange']), caplog) assert 'export' in config assert log_has( 'Parameter --export detected: {} ...'.format(config['export']), caplog) assert 'stake_amount' in config assert config['stake_amount'] == 'unlimited'
def test_check_exchange(default_conf, caplog) -> None: configuration = Configuration(Namespace()) # Test a valid exchange default_conf.get('exchange').update({'name': 'BITTREX'}) assert configuration.check_exchange(default_conf) # Test a valid exchange default_conf.get('exchange').update({'name': 'binance'}) assert configuration.check_exchange(default_conf) # Test a invalid exchange default_conf.get('exchange').update({'name': 'unknown_exchange'}) configuration.config = default_conf with pytest.raises(OperationalException, match=r'.*Exchange "unknown_exchange" not supported.*'): configuration.check_exchange(default_conf) # Test ccxt_rate_limit depreciation default_conf.get('exchange').update({'name': 'binance'}) default_conf['exchange']['ccxt_rate_limit'] = True configuration.check_exchange(default_conf) assert log_has( "`ccxt_rate_limit` has been deprecated in favor of " "`ccxt_config` and `ccxt_async_config` and will be removed " "in a future version.", caplog.record_tuples)
def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> None: mocker.patch('freqtrade.configuration.open', mocker.mock_open(read_data=json.dumps(default_conf))) arglist = [ '--config', 'config.json', '--strategy', 'DefaultStrategy', '--datadir', '/foo/bar', 'backtesting', '--ticker-interval', '1m', '--live', '--enable-position-stacking', '--disable-max-market-positions', '--refresh-pairs-cached', '--timerange', ':100', '--export', '/bar/foo' ] args = Arguments(arglist, '').get_parsed_arg() configuration = Configuration(args) config = configuration.get_config() assert 'max_open_trades' in config assert 'stake_currency' in config assert 'stake_amount' in config assert 'exchange' in config assert 'pair_whitelist' in config['exchange'] assert 'datadir' in config assert log_has('Using data folder: {} ...'.format(config['datadir']), 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 'live' in config assert log_has('Parameter -l/--live detected ...', caplog.record_tuples) assert 'position_stacking' in config assert log_has('Parameter --enable-position-stacking detected ...', caplog.record_tuples) assert 'use_max_market_positions' in config assert log_has('Parameter --disable-max-market-positions detected ...', caplog.record_tuples) assert log_has('max_open_trades set to unlimited ...', caplog.record_tuples) assert 'refresh_pairs' in config assert log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples) assert 'timerange' in config assert log_has( 'Parameter --timerange detected: {} ...'.format(config['timerange']), caplog.record_tuples) assert 'export' in config assert log_has( 'Parameter --export detected: {} ...'.format(config['export']), caplog.record_tuples)
def test_load_config_missing_attributes(default_conf) -> None: """ Test the configuration validator with a missing attribute """ conf = deepcopy(default_conf) conf.pop('exchange') with pytest.raises(ValidationError, match=r'.*\'exchange\' is a required property.*'): configuration = Configuration(Namespace()) configuration._validate_config(conf)
def test_load_config_warn_forcebuy(default_conf, mocker, caplog) -> None: default_conf['forcebuy_enable'] = True mocker.patch('freqtrade.configuration.open', mocker.mock_open(read_data=json.dumps(default_conf))) args = Arguments([], '').get_parsed_arg() configuration = Configuration(args) validated_conf = configuration.load_config() assert validated_conf.get('forcebuy_enable') assert log_has('`forcebuy` RPC message enabled.', caplog.record_tuples)
def test_load_config_max_open_trades_zero(default_conf, mocker, caplog) -> None: default_conf['max_open_trades'] = 0 patched_configuration_load_config_file(mocker, default_conf) args = Arguments([], '').get_parsed_arg() configuration = Configuration(args) validated_conf = configuration.load_config() assert validated_conf['max_open_trades'] == 0 assert 'internals' in validated_conf assert log_has('Validating configuration ...', caplog.record_tuples)
def test_load_config(default_conf, mocker) -> None: mocker.patch('freqtrade.configuration.open', mocker.mock_open(read_data=json.dumps(default_conf))) args = Arguments([], '').get_parsed_arg() configuration = Configuration(args) validated_conf = configuration.load_config() assert validated_conf.get('strategy') == 'DefaultStrategy' assert validated_conf.get('strategy_path') is None assert 'edge' not in validated_conf
def test_load_config_file_exception(mocker) -> None: """ Test Configuration._load_config_file() method """ mocker.patch('freqtrade.configuration.open', MagicMock(side_effect=FileNotFoundError('File not found'))) configuration = Configuration(Namespace()) with pytest.raises(OperationalException, match=r'.*Config file "somefile" not found!*'): configuration._load_config_file('somefile')
def test_load_config_incorrect_stake_amount(default_conf) -> None: """ Test the configuration validator with a missing attribute """ conf = deepcopy(default_conf) conf['stake_amount'] = 'fake' with pytest.raises(ValidationError, match=r'.*\'fake\' does not match \'unlimited\'.*'): configuration = Configuration(Namespace()) configuration._validate_config(conf)
def test_load_config_file(default_conf, mocker, caplog) -> None: file_mock = mocker.patch( 'freqtrade.configuration.open', mocker.mock_open(read_data=json.dumps(default_conf))) configuration = Configuration(Namespace()) validated_conf = configuration._load_config_file('somefile') assert file_mock.call_count == 1 assert validated_conf.items() >= default_conf.items() assert 'internals' in validated_conf assert log_has('Validating configuration ...', caplog.record_tuples)
def test_load_config_with_params(default_conf, mocker) -> None: """ Test Configuration.load_config() with cli params used """ mocker.patch('freqtrade.configuration.open', mocker.mock_open(read_data=json.dumps(default_conf))) arglist = [ '--dynamic-whitelist', '10', '--strategy', 'TestStrategy', '--strategy-path', '/some/path', '--db-url', 'sqlite:///someurl', ] args = Arguments(arglist, '').get_parsed_arg() configuration = Configuration(args) validated_conf = configuration.load_config() assert validated_conf.get('dynamic_whitelist') == 10 assert validated_conf.get('strategy') == 'TestStrategy' assert validated_conf.get('strategy_path') == '/some/path' assert validated_conf.get('db_url') == 'sqlite:///someurl' conf = default_conf.copy() conf["dry_run"] = False del conf["db_url"] mocker.patch('freqtrade.configuration.open', mocker.mock_open(read_data=json.dumps(conf))) arglist = [ '--dynamic-whitelist', '10', '--strategy', 'TestStrategy', '--strategy-path', '/some/path' ] args = Arguments(arglist, '').get_parsed_arg() configuration = Configuration(args) validated_conf = configuration.load_config() assert validated_conf.get('db_url') == DEFAULT_DB_PROD_URL # Test dry=run with ProdURL conf = default_conf.copy() conf["dry_run"] = True conf["db_url"] = DEFAULT_DB_PROD_URL mocker.patch('freqtrade.configuration.open', mocker.mock_open(read_data=json.dumps(conf))) arglist = [ '--dynamic-whitelist', '10', '--strategy', 'TestStrategy', '--strategy-path', '/some/path' ] args = Arguments(arglist, '').get_parsed_arg() configuration = Configuration(args) validated_conf = configuration.load_config() assert validated_conf.get('db_url') == DEFAULT_DB_DRYRUN_URL
def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> None: """ Test setup_configuration() function """ mocker.patch('freqtrade.configuration.open', mocker.mock_open(read_data=json.dumps(default_conf))) args = [ '--config', 'config.json', '--strategy', 'DefaultStrategy', '--datadir', '/foo/bar', 'backtesting', '--ticker-interval', '1', '--live', '--realistic-simulation', '--refresh-pairs-cached', '--timerange', ':100', '--export', '/bar/foo' ] args = Arguments(args, '').get_parsed_arg() configuration = Configuration(args) config = configuration.get_config() assert 'max_open_trades' in config assert 'stake_currency' in config assert 'stake_amount' in config assert 'exchange' in config assert 'pair_whitelist' in config['exchange'] assert 'datadir' in config assert log_has( 'Parameter --datadir detected: {} ...'.format(config['datadir']), 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: 1 ...', caplog.record_tuples) assert 'live' in config assert log_has('Parameter -l/--live detected ...', caplog.record_tuples) assert 'realistic_simulation' in config assert log_has('Parameter --realistic-simulation detected ...', caplog.record_tuples) assert log_has('Using max_open_trades: 1 ...', caplog.record_tuples) assert 'refresh_pairs' in config assert log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples) assert 'timerange' in config assert log_has( 'Parameter --timerange detected: {} ...'.format(config['timerange']), caplog.record_tuples) assert 'export' in config assert log_has( 'Parameter --export detected: {} ...'.format(config['export']), caplog.record_tuples)
def test_setup_configuration_with_stratlist(mocker, default_conf, caplog) -> None: """ Test setup_configuration() function """ mocker.patch('freqtrade.configuration.open', mocker.mock_open( read_data=json.dumps(default_conf) )) arglist = [ '--config', 'config.json', 'backtesting', '--ticker-interval', '1m', '--export', '/bar/foo', '--strategy-list', 'DefaultStrategy', 'TestStrategy' ] args = Arguments(arglist, '').get_parsed_arg() configuration = Configuration(args) config = configuration.get_config() assert 'max_open_trades' in config assert 'stake_currency' in config assert 'stake_amount' in config assert 'exchange' in config assert 'pair_whitelist' in config['exchange'] assert 'datadir' in config assert log_has( 'Using data folder: {} ...'.format(config['datadir']), 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 'strategy_list' in config assert log_has('Using strategy list of 2 Strategies', caplog.record_tuples) assert 'position_stacking' not in config assert 'use_max_market_positions' not in config assert 'timerange' not in config assert 'export' in config assert log_has( 'Parameter --export detected: {} ...'.format(config['export']), caplog.record_tuples )
def test_check_exchange(default_conf, caplog) -> None: configuration = Configuration(Namespace()) # Test an officially supported by Freqtrade team exchange default_conf.get('exchange').update({'name': 'BITTREX'}) assert configuration.check_exchange(default_conf) assert log_has_re( r"Exchange .* is officially supported by the Freqtrade development team\.", caplog.record_tuples) caplog.clear() # Test an officially supported by Freqtrade team exchange default_conf.get('exchange').update({'name': 'binance'}) assert configuration.check_exchange(default_conf) assert log_has_re( r"Exchange .* is officially supported by the Freqtrade development team\.", caplog.record_tuples) caplog.clear() # Test an available exchange, supported by ccxt default_conf.get('exchange').update({'name': 'kraken'}) assert configuration.check_exchange(default_conf) assert log_has_re( r"Exchange .* is supported by ccxt and .* not officially supported " r"by the Freqtrade development team\. .*", caplog.record_tuples) caplog.clear() # Test a 'bad' exchange, which known to have serious problems default_conf.get('exchange').update({'name': 'bitmex'}) assert not configuration.check_exchange(default_conf) assert log_has_re( r"Exchange .* is known to not work with the bot yet\. " r"Use it only for development and testing purposes\.", caplog.record_tuples) caplog.clear() # Test a 'bad' exchange with check_for_bad=False default_conf.get('exchange').update({'name': 'bitmex'}) assert configuration.check_exchange(default_conf, False) assert log_has_re( r"Exchange .* is supported by ccxt and .* not officially supported " r"by the Freqtrade development team\. .*", caplog.record_tuples) caplog.clear() # Test an invalid exchange default_conf.get('exchange').update({'name': 'unknown_exchange'}) configuration.config = default_conf with pytest.raises( OperationalException, match=r'.*Exchange "unknown_exchange" is not supported by ccxt ' r'and therefore not available for the bot.*'): configuration.check_exchange(default_conf)
def test_load_config_max_open_trades_minus_one(default_conf, mocker, caplog) -> None: default_conf['max_open_trades'] = -1 patched_configuration_load_config_file(mocker, default_conf) args = Arguments(['trade']).get_parsed_arg() configuration = Configuration(args) validated_conf = configuration.load_config() assert validated_conf['max_open_trades'] > 999999999 assert validated_conf['max_open_trades'] == float('inf') assert "runmode" in validated_conf assert validated_conf['runmode'] == RunMode.DRY_RUN
def test_pairlist_resolving(): arglist = [ 'download-data', '--pairs', 'ETH/BTC', 'XRP/BTC', '--exchange', 'binance' ] args = Arguments(arglist).get_parsed_arg() configuration = Configuration(args, RunMode.OTHER) config = configuration.get_config() assert config['pairs'] == ['ETH/BTC', 'XRP/BTC'] assert config['exchange']['name'] == 'binance'
def test_cli_verbose_with_params(default_conf, mocker, caplog) -> None: patched_configuration_load_config_file(mocker, default_conf) # Prevent setting loggers mocker.patch('freqtrade.loggers._set_loggers', MagicMock) arglist = ['trade', '-vvv'] args = Arguments(arglist).get_parsed_arg() configuration = Configuration(args) validated_conf = configuration.load_config() assert validated_conf.get('verbosity') == 3 assert log_has('Verbosity set to 3', caplog)
def test_load_custom_strategy(default_conf, mocker) -> None: default_conf.update({ 'strategy': 'CustomStrategy', 'strategy_path': '/tmp/strategies', }) patched_configuration_load_config_file(mocker, default_conf) args = Arguments(['trade']).get_parsed_arg() configuration = Configuration(args) validated_conf = configuration.load_config() assert validated_conf.get('strategy') == 'CustomStrategy' assert validated_conf.get('strategy_path') == '/tmp/strategies'
def test_load_config_file_exception(mocker, caplog) -> None: """ Test Configuration._load_config_file() method """ mocker.patch('freqtrade.configuration.open', MagicMock(side_effect=FileNotFoundError('File not found'))) configuration = Configuration([]) with pytest.raises(SystemExit): configuration._load_config_file('somefile') assert log_has( 'Config file "somefile" not found. Please create your config file', caplog.record_tuples)
def test_load_config_default_exchange_name(all_conf) -> None: """ config['exchange']['name'] option is required so it cannot be omitted in the config """ del all_conf['exchange']['name'] assert 'name' not in all_conf['exchange'] with pytest.raises(ValidationError, match=r'\'name\' is a required property'): configuration = Configuration(Namespace()) configuration._validate_config_schema(all_conf)
def test_load_config_max_open_trades_minus_one(default_conf, mocker, caplog) -> None: default_conf['max_open_trades'] = -1 mocker.patch('freqtrade.configuration.open', mocker.mock_open(read_data=json.dumps(default_conf))) args = Arguments([], '').get_parsed_arg() configuration = Configuration(args) validated_conf = configuration.load_config() assert validated_conf['max_open_trades'] > 999999999 assert validated_conf['max_open_trades'] == float('inf') assert log_has('Validating configuration ...', caplog.record_tuples)
def test_cli_verbose_with_params(default_conf, mocker, caplog) -> None: mocker.patch('freqtrade.configuration.open', mocker.mock_open(read_data=json.dumps(default_conf))) # Prevent setting loggers mocker.patch('freqtrade.configuration.set_loggers', MagicMock) arglist = ['-vvv'] args = Arguments(arglist, '').get_parsed_arg() configuration = Configuration(args) validated_conf = configuration.load_config() assert validated_conf.get('verbosity') == 3 assert log_has('Verbosity set to 3', caplog.record_tuples)
def test__args_to_config(caplog): arg_list = ['trade', '--strategy-path', 'TestTest'] args = Arguments(arg_list).get_parsed_arg() configuration = Configuration(args) config = {} with warnings.catch_warnings(record=True) as w: # No warnings ... configuration._args_to_config(config, argname="strategy_path", logstring="DeadBeef") assert len(w) == 0 assert log_has("DeadBeef", caplog) assert config['strategy_path'] == "TestTest" configuration = Configuration(args) config = {} with warnings.catch_warnings(record=True) as w: # Deprecation warnings! configuration._args_to_config(config, argname="strategy_path", logstring="DeadBeef", deprecated_msg="Going away soon!") assert len(w) == 1 assert issubclass(w[-1].category, DeprecationWarning) assert "DEPRECATED: Going away soon!" in str(w[-1].message) assert log_has("DeadBeef", caplog) assert config['strategy_path'] == "TestTest"
def test_load_custom_strategy(default_conf, mocker) -> None: default_conf.update({ 'strategy': 'CustomStrategy', 'strategy_path': '/tmp/strategies', }) mocker.patch('freqtrade.configuration.open', mocker.mock_open(read_data=json.dumps(default_conf))) args = Arguments([], '').get_parsed_arg() configuration = Configuration(args) validated_conf = configuration.load_config() assert validated_conf.get('strategy') == 'CustomStrategy' assert validated_conf.get('strategy_path') == '/tmp/strategies'