Beispiel #1
0
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:
        warnings.simplefilter("always")
        # 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:
        warnings.simplefilter("always")
        # 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"
Beispiel #2
0
def test_load_config_combine_dicts(default_conf, mocker, caplog) -> None:
    conf1 = deepcopy(default_conf)
    conf2 = deepcopy(default_conf)
    del conf1['exchange']['key']
    del conf1['exchange']['secret']
    del conf2['exchange']['name']
    conf2['exchange']['pair_whitelist'] += ['NANO/BTC']

    config_files = [conf1, conf2]

    configsmock = MagicMock(side_effect=config_files)
    mocker.patch('freqtrade.configuration.configuration.load_config_file',
                 configsmock)

    arg_list = [
        'trade',
        '-c',
        'test_conf.json',
        '--config',
        'test2_conf.json',
    ]
    args = Arguments(arg_list).get_parsed_arg()
    configuration = Configuration(args)
    validated_conf = configuration.load_config()

    exchange_conf = default_conf['exchange']
    assert validated_conf['exchange']['name'] == exchange_conf['name']
    assert validated_conf['exchange']['key'] == exchange_conf['key']
    assert validated_conf['exchange']['secret'] == exchange_conf['secret']
    assert validated_conf['exchange']['pair_whitelist'] != conf1['exchange'][
        'pair_whitelist']
    assert validated_conf['exchange']['pair_whitelist'] == conf2['exchange'][
        'pair_whitelist']

    assert 'internals' in validated_conf
def test_parse_args_defaults(mocker) -> None:
    mocker.patch.object(Path, 'is_file', MagicMock(side_effect=[False, True]))
    args = Arguments(['trade']).get_parsed_arg()
    assert args['config'] == ['config.json']
    assert args['strategy_path'] is None
    assert args['datadir'] is None
    assert args['verbosity'] == 0
Beispiel #4
0
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!')))
    mocker.patch('freqtrade.wallets.Wallets.update', MagicMock())
    patched_configuration_load_config_file(mocker, default_conf)
    mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
    mocker.patch('freqtrade.freqtradebot.init_db', MagicMock())

    args = Arguments(['trade', '-c',
                      'config_bittrex.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']
Beispiel #5
0
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
Beispiel #6
0
def test_main_reload_config(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_CONFIG, State.RUNNING,
        OperationalException("Oh snap!")
    ])
    mocker.patch('freqtrade.worker.Worker._worker', worker_mock)
    patched_configuration_load_config_file(mocker, default_conf)
    mocker.patch('freqtrade.wallets.Wallets.update', MagicMock())
    reconfigure_mock = mocker.patch('freqtrade.worker.Worker._reconfigure',
                                    MagicMock())

    mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
    mocker.patch('freqtrade.freqtradebot.init_db', MagicMock())

    args = Arguments(['trade', '-c',
                      'config_bittrex.json.example']).get_parsed_arg()
    worker = Worker(args=args, config=default_conf)
    with pytest.raises(SystemExit):
        main(['trade', '-c', 'config_bittrex.json.example'])

    assert log_has('Using config: config_bittrex.json.example ...', caplog)
    assert worker_mock.call_count == 4
    assert reconfigure_mock.call_count == 1
    assert isinstance(worker.freqtrade, FreqtradeBot)
Beispiel #7
0
def test_parse_args_defaults(mocker) -> None:
    mocker.patch.object(Path, "is_file", MagicMock(side_effect=[False, True]))
    args = Arguments(['trade']).get_parsed_arg()
    assert args["config"] == ['config.json']
    assert args["strategy_path"] is None
    assert args["datadir"] is None
    assert args["verbosity"] == 0
Beispiel #8
0
def test_setup_configuration_without_arguments(mocker, default_conf,
                                               caplog) -> None:
    patched_configuration_load_config_file(mocker, default_conf)

    arglist = [
        'backtesting',
        '--config',
        'config.json',
        '--strategy',
        'DefaultStrategy',
    ]

    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 'user_data_dir' in config
    assert log_has('Using data directory: {} ...'.format(config['datadir']),
                   caplog)
    assert 'timeframe' in config
    assert not log_has('Parameter -i/--timeframe detected ...', caplog)

    assert 'position_stacking' not in config
    assert not log_has('Parameter --enable-position-stacking detected ...',
                       caplog)

    assert 'timerange' not in config
    assert 'export' not in config
def test_config_notallowed(mocker) -> None:
    mocker.patch.object(Path, 'is_file', MagicMock(return_value=False))
    args = [
        'create-userdir',
    ]
    pargs = Arguments(args).get_parsed_arg()

    assert 'config' not in pargs

    # When file exists:
    mocker.patch.object(Path, 'is_file', MagicMock(return_value=True))
    args = [
        'create-userdir',
    ]
    pargs = Arguments(args).get_parsed_arg()
    # config is not added even if it exists, since create-userdir is in the notallowed list
    assert 'config' not in pargs
def test_config_notrequired(mocker) -> None:
    mocker.patch.object(Path, 'is_file', MagicMock(return_value=False))
    args = [
        'download-data',
    ]
    pargs = Arguments(args).get_parsed_arg()

    assert pargs['config'] is None

    # When file exists:
    mocker.patch.object(Path, 'is_file', MagicMock(side_effect=[False, True]))
    args = [
        'download-data',
    ]
    pargs = Arguments(args).get_parsed_arg()
    # config is added if it exists
    assert pargs['config'] == ['config.json']
def test_parse_args_default_userdatadir(mocker) -> None:
    mocker.patch.object(Path, 'is_file', MagicMock(return_value=True))
    args = Arguments(['trade']).get_parsed_arg()
    # configuration defaults to user_data if that is available.
    assert args['config'] == [str(Path('user_data/config.json'))]
    assert args['strategy_path'] is None
    assert args['datadir'] is None
    assert args['verbosity'] == 0
Beispiel #12
0
def test_load_config(default_conf, mocker) -> None:
    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
Beispiel #13
0
def test_parse_args_userdatadir(mocker) -> None:
    mocker.patch.object(Path, "is_file", MagicMock(return_value=True))
    args = Arguments(['trade', '--user-data-dir',
                      'user_data']).get_parsed_arg()
    # configuration defaults to user_data if that is available.
    assert args["config"] == [str(Path('user_data/config.json'))]
    assert args["strategy_path"] is None
    assert args["datadir"] is None
    assert args["verbosity"] == 0
Beispiel #14
0
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', 'StrategyTestV2',
        '--datadir', '/foo/bar',
        '--userdir', "/tmp/freqtrade",
        '--ticker-interval', '1m',
        '--enable-position-stacking',
        '--disable-max-market-positions',
        '--timerange', ':100',
        '--export', 'trades',
        '--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'
Beispiel #15
0
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)
Beispiel #16
0
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)
Beispiel #17
0
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_download_data_options() -> None:
    args = [
        'download-data', '--datadir', 'datadir/directory', '--pairs-file',
        'file_with_pairs', '--days', '30', '--exchange', 'binance'
    ]
    pargs = Arguments(args).get_parsed_arg()

    assert pargs['pairs_file'] == 'file_with_pairs'
    assert pargs['datadir'] == 'datadir/directory'
    assert pargs['days'] == 30
    assert pargs['exchange'] == 'binance'
Beispiel #19
0
def test_parse_args_hyperopt_custom() -> None:
    args = [
        'hyperopt', '-c', 'test_conf.json', '--epochs', '20', '--spaces', 'buy'
    ]
    call_args = Arguments(args).get_parsed_arg()
    assert call_args["config"] == ['test_conf.json']
    assert call_args["epochs"] == 20
    assert call_args["verbosity"] == 0
    assert call_args["command"] == 'hyperopt'
    assert call_args["spaces"] == ['buy']
    assert call_args["func"] is not None
    assert callable(call_args["func"])
Beispiel #20
0
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
Beispiel #21
0
def test_plot_profit_options() -> None:
    args = [
        'plot-profit',
        '-p', 'UNITTEST/BTC',
        '--trade-source', 'DB',
        '--db-url', 'sqlite:///whatever.sqlite',
    ]
    pargs = Arguments(args).get_parsed_arg()

    assert pargs['trade_source'] == 'DB'
    assert pargs['pairs'] == ['UNITTEST/BTC']
    assert pargs['db_url'] == 'sqlite:///whatever.sqlite'
def test_parse_args_hyperopt_custom() -> None:
    args = [
        'hyperopt', '-c', 'test_conf.json', '--epochs', '20', '--spaces', 'buy'
    ]
    call_args = Arguments(args).get_parsed_arg()
    assert call_args['config'] == ['test_conf.json']
    assert call_args['epochs'] == 20
    assert call_args['verbosity'] == 0
    assert call_args['command'] == 'hyperopt'
    assert call_args['spaces'] == ['buy']
    assert call_args['func'] is not None
    assert callable(call_args['func'])
Beispiel #23
0
def test_parse_args_backtesting_custom() -> None:
    args = [
        'backtesting', '-c', 'test_conf.json', '--ticker-interval', '1m',
        '--strategy-list', 'DefaultStrategy', 'SampleStrategy'
    ]
    call_args = Arguments(args).get_parsed_arg()
    assert call_args["config"] == ['test_conf.json']
    assert call_args["verbosity"] == 0
    assert call_args["command"] == 'backtesting'
    assert call_args["func"] is not None
    assert call_args["ticker_interval"] == '1m'
    assert type(call_args["strategy_list"]) is list
    assert len(call_args["strategy_list"]) == 2
Beispiel #24
0
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'
Beispiel #25
0
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_parse_args_backtesting_custom() -> None:
    args = [
        'backtesting', '-c', 'test_conf.json', '--ticker-interval', '1m',
        '--strategy-list', 'DefaultStrategy', 'SampleStrategy'
    ]
    call_args = Arguments(args).get_parsed_arg()
    assert call_args['config'] == ['test_conf.json']
    assert call_args['verbosity'] == 0
    assert call_args['command'] == 'backtesting'
    assert call_args['func'] is not None
    assert call_args['timeframe'] == '1m'
    assert type(call_args['strategy_list']) is list
    assert len(call_args['strategy_list']) == 2
Beispiel #27
0
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)
Beispiel #28
0
def main(sysargv: List[str] = None) -> None:
    """
    This function will initiate the bot and start the trading loop.
    :return: None
    """

    return_code: Any = 1
    try:
        setup_logging_pre()
        arguments = Arguments(sysargv)
        args = arguments.get_parsed_arg()

        # Call subcommand.
        if 'func' in args:
            return_code = args['func'](args)
        else:
            # No subcommand was issued.
            raise OperationalException(
                "Usage of Freqtrade requires a subcommand to be specified.\n"
                "To have the bot executing trades in live/dry-run modes, "
                "depending on the value of the `dry_run` setting in the config, run Freqtrade "
                "as `freqtrade trade [options...]`.\n"
                "To see the full list of options available, please use "
                "`freqtrade --help` or `freqtrade <command> --help`."
                )

    except SystemExit as e:
        return_code = e
    except KeyboardInterrupt:
        logger.info('SIGINT received, aborting ...')
        return_code = 0
    except FreqtradeException as e:
        logger.error(str(e))
        return_code = 2
    except Exception:
        logger.exception('Fatal exception!')
    finally:
        sys.exit(return_code)
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()
Beispiel #30
0
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()