def test_setup_edge_configuration_with_arguments(mocker, edge_conf, caplog) -> None: patched_configuration_load_config_file(mocker, edge_conf) mocker.patch('freqtrade.configuration.configuration.create_datadir', lambda c, x: x) args = [ '--config', 'config.json', '--strategy', 'DefaultStrategy', '--datadir', '/foo/bar', 'edge', '--ticker-interval', '1m', '--refresh-pairs-cached', '--timerange', ':100', '--stoplosses=-0.01,-0.10,-0.001' ] config = setup_configuration(get_args(args), RunMode.EDGE) 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 config['runmode'] == RunMode.EDGE assert log_has('Using data directory: {} ...'.format(config['datadir']), caplog.record_tuples) assert 'ticker_interval' in config 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) assert 'timerange' in config assert log_has( 'Parameter --timerange detected: {} ...'.format(config['timerange']), caplog.record_tuples)
def test_hyperopt_with_arguments(mocker, default_conf, caplog) -> None: patched_configuration_load_config_file(mocker, default_conf) arglist = [ 'hyperopt', '--epochs', '10', '--spaces', 'all', ] args = Arguments(arglist, '').get_parsed_arg() configuration = Configuration(args, RunMode.HYPEROPT) config = configuration.get_config() assert 'epochs' in config assert int(config['epochs']) == 10 assert log_has( 'Parameter --epochs detected ... Will run Hyperopt with for 10 epochs ...', caplog) assert 'spaces' in config assert config['spaces'] == ['all'] assert log_has('Parameter -s/--spaces detected: [\'all\']', caplog) assert "runmode" in config assert config['runmode'] == RunMode.HYPEROPT
def test_pairlist_resolving_with_config(mocker, default_conf): patched_configuration_load_config_file(mocker, default_conf) arglist = [ '--config', 'config.json', 'download-data', ] args = Arguments(arglist, '').get_parsed_arg() configuration = Configuration(args) config = configuration.get_config() assert config['pairs'] == default_conf['exchange']['pair_whitelist'] assert config['exchange']['name'] == default_conf['exchange']['name'] # Override pairs arglist = [ '--config', 'config.json', 'download-data', '--pairs', 'ETH/BTC', 'XRP/BTC', ] args = Arguments(arglist, '').get_parsed_arg() configuration = Configuration(args) config = configuration.get_config() assert config['pairs'] == ['ETH/BTC', 'XRP/BTC'] assert config['exchange']['name'] == default_conf['exchange']['name']
def test_setup_configuration_without_arguments(mocker, default_conf, caplog) -> None: patched_configuration_load_config_file(mocker, default_conf) args = [ '--config', 'config.json', '--strategy', 'DefaultStrategy', 'backtesting' ] config = setup_configuration(get_args(args), RunMode.BACKTEST) 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(config['datadir']), caplog) assert 'ticker_interval' in config assert not log_has_re('Parameter -i/--ticker-interval detected .*', caplog) assert 'position_stacking' not in config assert not log_has('Parameter --enable-position-stacking detected ...', caplog) assert 'refresh_pairs' not in config assert not log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog) assert 'timerange' not in config assert 'export' not in config assert 'runmode' in config assert config['runmode'] == RunMode.BACKTEST
def test_main_reload_conf(mocker, default_conf, caplog) -> None: patch_exchange(mocker) mocker.patch('freqtrade.freqtradebot.FreqtradeBot.cleanup', MagicMock()) # 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) patched_configuration_load_config_file(mocker, default_conf) reconfigure_mock = mocker.patch('freqtrade.main.Worker._reconfigure', MagicMock()) mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock()) mocker.patch('freqtrade.freqtradebot.persistence.init', MagicMock()) 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 log_has('Using config: config.json.example ...', caplog) assert worker_mock.call_count == 4 assert reconfigure_mock.call_count == 1 assert isinstance(worker.freqtrade, FreqtradeBot)
def test_reconfigure(mocker, default_conf) -> None: patch_exchange(mocker) mocker.patch('freqtrade.freqtradebot.FreqtradeBot.cleanup', MagicMock()) mocker.patch('freqtrade.worker.Worker._worker', MagicMock(side_effect=OperationalException('Oh snap!'))) patched_configuration_load_config_file(mocker, default_conf) mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock()) mocker.patch('freqtrade.freqtradebot.persistence.init', MagicMock()) args = Arguments(['-c', 'config.json.example']).get_parsed_arg() worker = Worker(args=args, config=default_conf) freqtrade = worker.freqtrade # Renew mock to return modified data conf = deepcopy(default_conf) conf['stake_amount'] += 1 patched_configuration_load_config_file(mocker, conf) worker._config = conf # reconfigure should return a new instance worker._reconfigure() freqtrade2 = worker.freqtrade # Verify we have a new instance with the new config assert freqtrade is not freqtrade2 assert freqtrade.config['stake_amount'] + 1 == freqtrade2.config[ 'stake_amount']
def test_setup_hyperopt_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) args = [ '--config', 'config.json', '--datadir', '/foo/bar', 'hyperopt', '--ticker-interval', '1m', '--timerange', ':100', '--refresh-pairs-cached', '--enable-position-stacking', '--disable-max-market-positions', '--epochs', '1000', '--spaces', 'all', '--print-all' ] config = setup_configuration(get_args(args), RunMode.HYPEROPT) 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 config['runmode'] == RunMode.HYPEROPT assert log_has('Using data directory: {} ...'.format(config['datadir']), caplog) assert 'ticker_interval' in config assert log_has( 'Parameter -i/--ticker-interval detected ... Using ticker_interval: 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 'refresh_pairs' in config assert log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog) assert 'timerange' in config assert log_has( 'Parameter --timerange detected: {} ...'.format(config['timerange']), caplog) assert 'epochs' in config assert log_has( 'Parameter --epochs detected ... Will run Hyperopt with for 1000 epochs ...', caplog) assert 'spaces' in config assert log_has( 'Parameter -s/--spaces detected: {}'.format(config['spaces']), caplog) assert 'print_all' in config assert log_has('Parameter --print-all detected ...', caplog)
def test_load_config(default_conf, mocker) -> None: patched_configuration_load_config_file(mocker, 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_warn_forcebuy(default_conf, mocker, caplog) -> None: default_conf['forcebuy_enable'] = True patched_configuration_load_config_file(mocker, 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)
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_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 = [ '--config', 'config.json', '--strategy', 'DefaultStrategy', '--datadir', '/foo/bar', '--userdir', "/tmp/freqtrade", 'backtesting', '--ticker-interval', '1m', '--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 directory: {} ...'.format("/foo/bar"), caplog) assert log_has( 'Using user-data directory: {} ...'.format("/tmp/freqtrade"), caplog) assert 'user_data_dir' in config assert 'ticker_interval' in config assert log_has( 'Parameter -i/--ticker-interval detected ... Using ticker_interval: 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 'refresh_pairs' in config assert log_has('Parameter -r/--refresh-pairs-cached detected ...', 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)
def test_start(mocker, fee, edge_conf, caplog) -> None: start_mock = MagicMock() mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) patch_exchange(mocker) mocker.patch('freqtrade.optimize.edge_cli.EdgeCli.start', start_mock) patched_configuration_load_config_file(mocker, edge_conf) args = ['--config', 'config.json', '--strategy', 'DefaultStrategy', 'edge'] args = get_args(args) start_edge(args) assert log_has('Starting freqtrade in Edge mode', caplog.record_tuples) assert start_mock.call_count == 1
def test_start_filelock(mocker, default_conf, caplog) -> None: start_mock = MagicMock( side_effect=Timeout(Hyperopt.get_lock_filename(default_conf))) patched_configuration_load_config_file(mocker, default_conf) mocker.patch('freqtrade.optimize.hyperopt.Hyperopt.start', start_mock) patch_exchange(mocker) args = ['--config', 'config.json', 'hyperopt', '--epochs', '5'] args = get_args(args) start_hyperopt(args) assert log_has("Another running instance of freqtrade Hyperopt detected.", caplog)
def test_setup_bt_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) args = [ '--config', 'config.json', '--strategy', 'DefaultStrategy', '--datadir', '/foo/bar', 'backtesting', '--ticker-interval', '1m', '--enable-position-stacking', '--disable-max-market-positions', '--refresh-pairs-cached', '--timerange', ':100', '--export', '/bar/foo', '--export-filename', 'foo_bar.json' ] config = setup_configuration(get_args(args), RunMode.BACKTEST) 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 config['runmode'] == RunMode.BACKTEST assert log_has('Using data directory: {} ...'.format(config['datadir']), caplog) assert 'ticker_interval' in config assert log_has( 'Parameter -i/--ticker-interval detected ... Using ticker_interval: 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 'refresh_pairs' in config assert log_has('Parameter -r/--refresh-pairs-cached detected ...', 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 'exportfilename' in config assert log_has( 'Storing backtest results to {} ...'.format(config['exportfilename']), 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([], '').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_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 = ['-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_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([], '').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) assert "runmode" in validated_conf assert validated_conf['runmode'] == RunMode.DRY_RUN
def test_setup_configuration_unlimited_stake_amount(mocker, default_conf, caplog) -> None: default_conf['stake_amount'] = constants.UNLIMITED_STAKE_AMOUNT patched_configuration_load_config_file(mocker, default_conf) args = [ '--config', 'config.json', '--strategy', 'DefaultStrategy', 'backtesting' ] with pytest.raises(DependencyException, match=r'.*stake amount.*'): setup_configuration(get_args(args), RunMode.BACKTEST)
def test_show_info(default_conf, mocker, caplog) -> None: patched_configuration_load_config_file(mocker, default_conf) arglist = [ '--strategy', 'TestStrategy', '--db-url', 'sqlite:///tmp/testdb', ] args = Arguments(arglist, '').get_parsed_arg() configuration = Configuration(args) configuration.get_config() assert log_has('Using DB: "sqlite:///tmp/testdb"', caplog.record_tuples) assert log_has('Dry run is enabled', caplog.record_tuples)
def test_set_logfile(default_conf, mocker): patched_configuration_load_config_file(mocker, default_conf) arglist = [ '--logfile', 'test_file.log', ] args = Arguments(arglist, '').get_parsed_arg() configuration = Configuration(args) validated_conf = configuration.load_config() assert validated_conf['logfile'] == "test_file.log" f = Path("test_file.log") assert f.is_file() f.unlink()
def test_start_failure(mocker, default_conf, caplog) -> None: start_mock = MagicMock() patched_configuration_load_config_file(mocker, default_conf) mocker.patch('freqtrade.optimize.hyperopt.Hyperopt.start', start_mock) patch_exchange(mocker) args = [ '--config', 'config.json', '--strategy', 'SampleStrategy', 'hyperopt', '--epochs', '5' ] args = get_args(args) with pytest.raises(DependencyException): start_hyperopt(args) assert log_has("Please don't use --strategy for hyperopt.", caplog)
def test_setup_configuration_with_stratlist(mocker, default_conf, caplog) -> None: """ Test setup_configuration() function """ patched_configuration_load_config_file(mocker, 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, RunMode.BACKTEST) config = configuration.get_config() assert config['runmode'] == RunMode.BACKTEST 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(config['datadir']), caplog.record_tuples ) assert 'ticker_interval' in config 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) 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_start(mocker, default_conf, caplog) -> None: start_mock = MagicMock() patched_configuration_load_config_file(mocker, default_conf) mocker.patch('freqtrade.optimize.hyperopt.Hyperopt.start', start_mock) patch_exchange(mocker) args = ['--config', 'config.json', 'hyperopt', '--epochs', '5'] args = get_args(args) start_hyperopt(args) import pprint pprint.pprint(caplog.record_tuples) assert log_has('Starting freqtrade in Hyperopt mode', caplog) assert start_mock.call_count == 1
def test_start(mocker, fee, default_conf, caplog) -> None: start_mock = MagicMock() mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) patch_exchange(mocker) mocker.patch('freqtrade.optimize.backtesting.Backtesting.start', start_mock) patched_configuration_load_config_file(mocker, default_conf) args = [ '--config', 'config.json', '--strategy', 'DefaultStrategy', 'backtesting' ] args = get_args(args) start_backtesting(args) assert log_has('Starting freqtrade in Backtesting mode', caplog) assert start_mock.call_count == 1
def test_main_operational_exception(mocker, default_conf, caplog) -> None: patch_exchange(mocker) mocker.patch('freqtrade.freqtradebot.FreqtradeBot.cleanup', MagicMock()) mocker.patch('freqtrade.worker.Worker._worker', MagicMock(side_effect=OperationalException('Oh snap!'))) patched_configuration_load_config_file(mocker, default_conf) mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock()) mocker.patch('freqtrade.freqtradebot.persistence.init', MagicMock()) args = ['-c', 'config.json.example'] # Test Main + the KeyboardInterrupt exception with pytest.raises(SystemExit): main(args) assert log_has('Using config: config.json.example ...', caplog) assert log_has('Oh snap!', caplog)
def test_hyperoptresolver(mocker, default_conf, caplog) -> None: patched_configuration_load_config_file(mocker, default_conf) hyperopts = DefaultHyperOpts delattr(hyperopts, 'populate_buy_trend') delattr(hyperopts, 'populate_sell_trend') mocker.patch( 'freqtrade.resolvers.hyperopt_resolver.HyperOptResolver._load_hyperopt', MagicMock(return_value=hyperopts) ) x = HyperOptResolver(default_conf, ).hyperopt assert not hasattr(x, 'populate_buy_trend') assert not hasattr(x, 'populate_sell_trend') assert log_has("Custom Hyperopt does not provide populate_sell_trend. " "Using populate_sell_trend from DefaultStrategy.", caplog.record_tuples) assert log_has("Custom Hyperopt does not provide populate_buy_trend. " "Using populate_buy_trend from DefaultStrategy.", caplog.record_tuples) assert hasattr(x, "ticker_interval")
def test_start_no_data(mocker, default_conf, caplog) -> None: patched_configuration_load_config_file(mocker, default_conf) mocker.patch('freqtrade.optimize.hyperopt.load_data', MagicMock(return_value={})) mocker.patch( 'freqtrade.optimize.hyperopt.get_timeframe', MagicMock(return_value=(datetime(2017, 12, 10), datetime(2017, 12, 13)))) patch_exchange(mocker) args = ['--config', 'config.json', 'hyperopt', '--epochs', '5'] args = get_args(args) start_hyperopt(args) import pprint pprint.pprint(caplog.record_tuples) assert log_has('No data found. Terminating.', caplog)
def test_pairlist_resolving_with_config_pl_not_exists(mocker, default_conf): patched_configuration_load_config_file(mocker, default_conf) mocker.patch("freqtrade.configuration.configuration.json_load", MagicMock(return_value=['XRP/BTC', 'ETH/BTC'])) mocker.patch.object(Path, "exists", MagicMock(return_value=False)) arglist = [ '--config', 'config.json', 'download-data', '--pairs-file', 'pairs.json', ] args = Arguments(arglist, '').get_parsed_arg() with pytest.raises(OperationalException, match=r"No pairs file found with path.*"): configuration = Configuration(args) configuration.get_config()
def test_backtest_start_live(default_conf, mocker, caplog): default_conf['exchange']['pair_whitelist'] = ['UNITTEST/BTC'] async def load_pairs(pair, timeframe, since): return _load_pair_as_ticks(pair, timeframe) api_mock = MagicMock() api_mock.fetch_ohlcv = load_pairs patch_exchange(mocker, api_mock) mocker.patch('freqtrade.optimize.backtesting.Backtesting.backtest', MagicMock()) mocker.patch( 'freqtrade.optimize.backtesting.Backtesting._generate_text_table', MagicMock()) patched_configuration_load_config_file(mocker, default_conf) args = [ '--config', 'config.json', '--strategy', 'DefaultStrategy', '--datadir', 'freqtrade/tests/testdata', 'backtesting', '--ticker-interval', '1m', '--live', '--timerange', '-100', '--enable-position-stacking', '--disable-max-market-positions' ] args = get_args(args) start_backtesting(args) # check the logs, that will contain the backtest result exists = [ '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 ...', 'Using data directory: freqtrade/tests/testdata ...', 'Using stake_currency: BTC ...', 'Using stake_amount: 0.001 ...', 'Live: Downloading data for all defined pairs ...', 'Backtesting with data from 2017-11-14T19:31:00+00:00 ' 'up to 2017-11-14T22:58:00+00:00 (0 days)..', 'Parameter --enable-position-stacking detected ...' ] for line in exists: assert log_has(line, caplog.record_tuples)
def test_pairlist_resolving_with_config_pl(mocker, default_conf): patched_configuration_load_config_file(mocker, default_conf) load_mock = mocker.patch("freqtrade.configuration.configuration.json_load", MagicMock(return_value=['XRP/BTC', 'ETH/BTC'])) mocker.patch.object(Path, "exists", MagicMock(return_value=True)) mocker.patch.object(Path, "open", MagicMock(return_value=MagicMock())) arglist = [ '--config', 'config.json', 'download-data', '--pairs-file', 'pairs.json', ] args = Arguments(arglist, '').get_parsed_arg() configuration = Configuration(args) config = configuration.get_config() assert load_mock.call_count == 1 assert config['pairs'] == ['ETH/BTC', 'XRP/BTC'] assert config['exchange']['name'] == default_conf['exchange']['name']