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 = [ 'hyperopt', '--config', 'config.json', '--hyperopt', 'DefaultHyperOpt', '--datadir', '/foo/bar', '--ticker-interval', '1m', '--timerange', ':100', '--enable-position-stacking', '--disable-max-market-positions', '--epochs', '1000', '--spaces', 'default', '--print-all' ] config = setup_optimize_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 '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_backtest_start_multi_strat(default_conf, mocker, caplog, testdatadir): default_conf['exchange']['pair_whitelist'] = ['UNITTEST/BTC'] patch_exchange(mocker) backtestmock = MagicMock() mocker.patch('freqtrade.optimize.backtesting.Backtesting.backtest', backtestmock) gen_table_mock = MagicMock() mocker.patch('freqtrade.optimize.optimize_reports.generate_text_table', gen_table_mock) gen_strattable_mock = MagicMock() mocker.patch('freqtrade.optimize.optimize_reports.generate_text_table_strategy', gen_strattable_mock) patched_configuration_load_config_file(mocker, default_conf) args = [ 'backtesting', '--config', 'config.json', '--datadir', str(testdatadir), '--strategy-path', str(Path(__file__).parents[1] / 'strategy/strats'), '--ticker-interval', '1m', '--timerange', '1510694220-1510700340', '--enable-position-stacking', '--disable-max-market-positions', '--strategy-list', 'DefaultStrategy', 'TestStrategyLegacy', ] args = get_args(args) start_backtesting(args) # 2 backtests, 4 tables assert backtestmock.call_count == 2 assert gen_table_mock.call_count == 4 assert gen_strattable_mock.call_count == 1 # check the logs, that will contain the backtest result exists = [ 'Parameter -i/--ticker-interval detected ... Using ticker_interval: 1m ...', 'Ignoring max_open_trades (--disable-max-market-positions was used) ...', 'Parameter --timerange detected: 1510694220-1510700340 ...', f'Using data directory: {testdatadir} ...', 'Using stake_currency: BTC ...', 'Using stake_amount: 0.001 ...', 'Loading data from 2017-11-14T20:57:00+00:00 ' 'up to 2017-11-14T22:58:00+00:00 (0 days)..', 'Backtesting with data from 2017-11-14T21:17:00+00:00 ' 'up to 2017-11-14T22:58:00+00:00 (0 days)..', 'Parameter --enable-position-stacking detected ...', 'Running backtesting for Strategy DefaultStrategy', 'Running backtesting for Strategy TestStrategyLegacy', ] for line in exists: assert log_has(line, caplog)
def test_process_deprecated_setting(mocker, default_conf, caplog): patched_configuration_load_config_file(mocker, default_conf) # Create sections for new and deprecated settings # (they may not exist in the config) default_conf['sectionA'] = {} default_conf['sectionB'] = {} # Assign deprecated setting default_conf['sectionB']['deprecated_setting'] = 'valB' # Both new and deprecated settings exists process_deprecated_setting(default_conf, 'sectionB', 'deprecated_setting', 'sectionA', 'new_setting') assert log_has_re('DEPRECATED', caplog) # The value of the new setting shall have been set to the # value of the deprecated one assert default_conf['sectionA']['new_setting'] == 'valB' caplog.clear() # Delete new setting (deprecated exists) del default_conf['sectionA']['new_setting'] process_deprecated_setting(default_conf, 'sectionB', 'deprecated_setting', 'sectionA', 'new_setting') assert log_has_re('DEPRECATED', caplog) # The value of the new setting shall have been set to the # value of the deprecated one assert default_conf['sectionA']['new_setting'] == 'valB' caplog.clear() # Assign new setting default_conf['sectionA']['new_setting'] = 'valA' # Delete deprecated setting del default_conf['sectionB']['deprecated_setting'] process_deprecated_setting(default_conf, 'sectionB', 'deprecated_setting', 'sectionA', 'new_setting') assert not log_has_re('DEPRECATED', caplog) assert default_conf['sectionA']['new_setting'] == 'valA' caplog.clear() # Test moving to root default_conf['sectionB']['deprecated_setting2'] = "DeadBeef" process_deprecated_setting(default_conf, 'sectionB', 'deprecated_setting2', None, 'new_setting') assert log_has_re('DEPRECATED', caplog) assert default_conf['new_setting']
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' ] 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)
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_setup_optimize_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 = [ 'backtesting', '--config', 'config.json', '--strategy', 'DefaultStrategy', ] with pytest.raises(DependencyException, match=r'.`stake_amount`.*'): setup_optimize_configuration(get_args(args), RunMode.BACKTEST)
def test_setup_hyperopt_configuration_unlimited_stake_amount(mocker, default_conf) -> None: default_conf['stake_amount'] = constants.UNLIMITED_STAKE_AMOUNT patched_configuration_load_config_file(mocker, default_conf) args = [ 'hyperopt', '--config', 'config.json', '--hyperopt', 'DefaultHyperOpt', ] with pytest.raises(DependencyException, match=r'.`stake_amount`.*'): setup_optimize_configuration(get_args(args), RunMode.HYPEROPT)
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_process_removed_settings(mocker, default_conf, setting): patched_configuration_load_config_file(mocker, default_conf) # Create sections for new and deprecated settings # (they may not exist in the config) default_conf[setting[0]] = {} # Assign removed setting default_conf[setting[0]][setting[1]] = setting[2] # New and deprecated settings are conflicting ones with pytest.raises(OperationalException, match=r'Setting .* has been moved'): process_temporary_deprecated_settings(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_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 = [ 'backtesting', '--config', 'config.json', '--strategy', 'StrategyTestV2', '--datadir', '/foo/bar', '--timeframe', '1m', '--enable-position-stacking', '--disable-max-market-positions', '--timerange', ':100', '--export-filename', 'foo_bar.json', '--fee', '0', ] config = setup_optimize_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 '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 'exportfilename' in config assert isinstance(config['exportfilename'], Path) assert log_has('Storing backtest results to {} ...'.format(config['exportfilename']), caplog) assert 'fee' in config assert log_has('Parameter --fee detected, setting fee to: {} ...'.format(config['fee']), caplog)
def test_start_not_installed(mocker, default_conf, caplog, import_fails) -> 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) with pytest.raises(OperationalException, match=r"Please ensure that the hyperopt dependencies"): start_hyperopt(args)
def test_set_logfile(default_conf, mocker): patched_configuration_load_config_file(mocker, default_conf) arglist = [ 'trade', '--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_test_pairlist(mocker, caplog, tickers, default_conf, capsys): patch_exchange(mocker, mock_markets=True) mocker.patch.multiple('freqtrade.exchange.Exchange', exchange_has=MagicMock(return_value=True), get_tickers=tickers, ) default_conf['pairlists'] = [ { "method": "VolumePairList", "number_assets": 5, "sort_key": "quoteVolume", }, {"method": "PrecisionFilter"}, {"method": "PriceFilter", "low_price_ratio": 0.02}, ] patched_configuration_load_config_file(mocker, default_conf) args = [ 'test-pairlist', '-c', 'config_bittrex.json.example' ] start_test_pairlist(get_args(args)) assert log_has_re(r"^Using resolved pairlist VolumePairList.*", caplog) assert log_has_re(r"^Using resolved pairlist PrecisionFilter.*", caplog) assert log_has_re(r"^Using resolved pairlist PriceFilter.*", caplog) captured = capsys.readouterr() assert re.match(r"Pairs for .*", captured.out) assert re.match("['ETH/BTC', 'TKN/BTC', 'BLK/BTC', 'LTC/BTC', 'XRP/BTC']", captured.out) args = [ 'test-pairlist', '-c', 'config_bittrex.json.example', '--one-column', ] start_test_pairlist(get_args(args)) captured = capsys.readouterr() assert re.match(r"ETH/BTC\nTKN/BTC\nBLK/BTC\nLTC/BTC\nXRP/BTC\n", captured.out) args = [ 'test-pairlist', '-c', 'config_bittrex.json.example', '--print-json', ] start_test_pairlist(get_args(args)) captured = capsys.readouterr() assert re.match(r'Pairs for BTC: \n\["ETH/BTC","TKN/BTC","BLK/BTC","LTC/BTC","XRP/BTC"\]\n', captured.out)
def test_pairlist_resolving_with_config_pl_not_exists(mocker, default_conf): patched_configuration_load_config_file(mocker, default_conf) arglist = [ 'download-data', '--config', 'config.json', '--pairs-file', 'tests/testdata/pairs_doesnotexist.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_start_filelock(mocker, hyperopt_conf, caplog) -> None: start_mock = MagicMock( side_effect=Timeout(Hyperopt.get_lock_filename(hyperopt_conf))) patched_configuration_load_config_file(mocker, hyperopt_conf) mocker.patch('freqtrade.optimize.hyperopt.Hyperopt.start', start_mock) patch_exchange(mocker) args = [ 'hyperopt', '--config', 'config.json', '--hyperopt', 'DefaultHyperOpt', '--hyperopt-loss', 'SharpeHyperOptLossDaily', '--epochs', '5' ] pargs = get_args(args) start_hyperopt(pargs) assert log_has("Another running instance of freqtrade Hyperopt detected.", caplog)
def test_main_fatal_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=Exception)) patched_configuration_load_config_file(mocker, default_conf) mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock()) mocker.patch('freqtrade.freqtradebot.init_db', MagicMock()) args = ['trade', '-c', 'config_examples/config_bittrex.example.json'] # Test Main + the KeyboardInterrupt exception with pytest.raises(SystemExit): main(args) assert log_has('Using config: config_examples/config_bittrex.example.json ...', caplog) assert log_has('Fatal exception!', caplog)
def test_show_info(default_conf, mocker, caplog) -> None: patched_configuration_load_config_file(mocker, default_conf) arglist = [ 'trade', '--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) assert log_has('Dry run is enabled', caplog)
def test_start_no_hyperopt_allowed(mocker, hyperopt_conf, caplog) -> None: start_mock = MagicMock() patched_configuration_load_config_file(mocker, hyperopt_conf) mocker.patch('freqtrade.optimize.hyperopt.Hyperopt.start', start_mock) patch_exchange(mocker) args = [ 'hyperopt', '--config', 'config.json', '--hyperopt', 'HyperoptTestSepFile', '--hyperopt-loss', 'SharpeHyperOptLossDaily', '--epochs', '5' ] pargs = get_args(args) with pytest.raises(OperationalException, match=r"Using separate Hyperopt files has been.*"): start_hyperopt(pargs)
def test_main_keyboard_interrupt(mocker, default_conf, caplog) -> None: patch_exchange(mocker) mocker.patch('freqtrade.freqtradebot.FreqtradeBot.cleanup', MagicMock()) mocker.patch('freqtrade.worker.Worker._worker', MagicMock(side_effect=KeyboardInterrupt)) patched_configuration_load_config_file(mocker, default_conf) mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock()) mocker.patch('freqtrade.freqtradebot.persistence.init', MagicMock()) args = ['trade', '-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('SIGINT received, aborting ...', caplog)
def test_process_deprecated_setting_pairlists(mocker, default_conf, caplog): patched_configuration_load_config_file(mocker, default_conf) default_conf.update({ 'pairlist': { 'method': 'VolumePairList', 'config': { 'precision_filter': True } } }) process_temporary_deprecated_settings(default_conf) assert log_has_re(r'DEPRECATED.*precision_filter.*', caplog) assert log_has_re( r'DEPRECATED.*in pairlist is deprecated and must be moved*', caplog)
def test_start(mocker, hyperopt_conf, caplog) -> None: start_mock = MagicMock() patched_configuration_load_config_file(mocker, hyperopt_conf) mocker.patch('freqtrade.optimize.hyperopt.Hyperopt.start', start_mock) patch_exchange(mocker) args = [ 'hyperopt', '--config', 'config.json', '--hyperopt', 'DefaultHyperOpt', '--hyperopt-loss', 'SharpeHyperOptLossDaily', '--epochs', '5' ] pargs = get_args(args) start_hyperopt(pargs) 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 = [ 'backtesting', '--config', 'config.json', '--strategy', 'DefaultStrategy', ] pargs = get_args(args) start_backtesting(pargs) assert log_has('Starting freqtrade in Backtesting mode', caplog) assert start_mock.call_count == 1
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) assert start_mock.call_count == 1
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) assert log_has('No data found. Terminating.', caplog)
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=FreqtradeException('Oh snap!'))) patched_configuration_load_config_file(mocker, default_conf) mocker.patch('freqtrade.wallets.Wallets.update', MagicMock()) mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock()) mocker.patch('freqtrade.freqtradebot.persistence.init', MagicMock()) args = ['trade', '-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_pairlist_resolving_with_config_pl(mocker, default_conf): patched_configuration_load_config_file(mocker, default_conf) arglist = [ 'download-data', '--config', 'config.json', '--pairs-file', 'tests/testdata/pairs.json', ] args = Arguments(arglist).get_parsed_arg() configuration = Configuration(args) config = configuration.get_config() assert len(config['pairs']) == 23 assert 'ETH/BTC' in config['pairs'] assert 'XRP/BTC' in config['pairs'] assert config['exchange']['name'] == default_conf['exchange']['name']
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 = [ 'download-data', '--config', 'config.json', '--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_set_logfile(default_conf, mocker, tmpdir): patched_configuration_load_config_file(mocker, default_conf) f = Path(tmpdir / "test_file.log") assert not f.is_file() arglist = [ 'trade', '--logfile', str(f), ] args = Arguments(arglist).get_parsed_arg() configuration = Configuration(args) validated_conf = configuration.load_config() assert validated_conf['logfile'] == str(f) assert f.is_file() try: f.unlink() except Exception: pass
def test_start_no_data(mocker, hyperopt_conf) -> None: patched_configuration_load_config_file(mocker, hyperopt_conf) mocker.patch('freqtrade.data.history.load_pair_history', MagicMock(return_value=pd.DataFrame)) mocker.patch( 'freqtrade.optimize.hyperopt.get_timerange', MagicMock(return_value=(datetime(2017, 12, 10), datetime(2017, 12, 13)))) patch_exchange(mocker) args = [ 'hyperopt', '--config', 'config.json', '--hyperopt', 'DefaultHyperOpt', '--hyperopt-loss', 'SharpeHyperOptLossDaily', '--epochs', '5' ] pargs = get_args(args) with pytest.raises(OperationalException, match='No data found. Terminating.'): start_hyperopt(pargs)