Example #1
0
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_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_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_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_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'
Example #6
0
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)
Example #7
0
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)
Example #8
0
def test_load_config_max_open_trades_zero(default_conf, mocker,
                                          caplog) -> None:
    default_conf['max_open_trades'] = 0
    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'] == 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', '--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 '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)
Example #10
0
def test_load_config(default_conf, mocker) -> None:
    """
    Test Configuration.load_config() without any cli params
    """
    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 'dynamic_whitelist' not in validated_conf
Example #11
0
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)
Example #12
0
def test_load_config_file(default_conf, mocker, caplog) -> None:
    """
    Test Configuration._load_config_file() method
    """
    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)
Example #13
0
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()
    print(validated_conf)

    assert validated_conf['max_open_trades'] > 999999999
    assert validated_conf['max_open_trades'] == float('inf')
    assert log_has('Validating configuration ...', caplog.record_tuples)
Example #14
0
def reconfigure(freqtrade: FreqtradeBot, args: Namespace) -> FreqtradeBot:
    """
    Cleans up current instance, reloads the configuration and returns the new instance
    """
    # Clean up current modules
    freqtrade.cleanup()

    # Create new instance
    freqtrade = FreqtradeBot(Configuration(args, None).get_config())
    freqtrade.rpc.send_msg({
        'type': RPCMessageType.STATUS_NOTIFICATION,
        'status': 'config reloaded'
    })
    return freqtrade
Example #15
0
    def _init(self, reconfig: bool) -> None:
        """
        Also called from the _reconfigure() method (with reconfig=True).
        """
        # Salvar arquivo de Configurações JSON do Banco de Dados
        try:
            connection = psycopg2.connect(user=os.getenv('DB_USER'),
                                          password=os.getenv('DB_PASSWORD'),
                                          host=os.getenv('DB_HOST'),
                                          port=os.getenv('DB_PORT'),
                                          database=os.getenv('DB_NAME'))

            cursor = connection.cursor()

            query = "SELECT config_json FROM usuarios WHERE id={};".format(
                str(os.getenv('id_usuario')))

            # Pega o resultado do Banco de Dados e salva em um arquivo JSON
            cursor.execute(query)
            record = cursor.fetchone()
            tempString = str(record)
            tempString2 = tempString.lstrip("(")
            tempString3 = tempString2.rstrip(",)")
            resultado = ast.literal_eval(tempString3)

            with open('config.json', 'w') as outfile:
                json.dump(resultado, outfile, indent=4)

            print("JSON Saved")

        except (Exception, psycopg2.Error) as error:
            print("Error while connecting to PostgreSQL", error)
        finally:
            # Closing database connection.
            if (connection):
                cursor.close()
                connection.close()

            if reconfig or self._config is None:
                # Load configuration
                self._config = Configuration(self._args, None).get_config()

            # Init the instance of the bot
            self.freqtrade = FreqtradeBot(self._config)

            self._throttle_secs = self._config.get('internals', {}).get(
                'process_throttle_secs', constants.PROCESS_THROTTLE_SECS)

            self._sd_notify = sdnotify.SystemdNotifier() if \
                self._config.get('internals', {}).get('sd_notify', False) else None
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'
Example #17
0
def setup_utils_configuration(args: Dict[str, Any],
                              method: RunMode) -> Dict[str, Any]:
    """
    Prepare the configuration for utils subcommands
    :param args: Cli args from Arguments()
    :return: Configuration
    """
    configuration = Configuration(args, method)
    config = configuration.get_config()

    # Ensure we do not use Exchange credentials
    remove_credentials(config)

    return config
Example #18
0
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()
Example #19
0
def test_pairlist_resolving_fallback(mocker):
    mocker.patch.object(Path, "exists", MagicMock(return_value=True))
    mocker.patch.object(Path, "open", MagicMock(return_value=MagicMock()))
    mocker.patch("freqtrade.configuration.configuration.json_load",
                 MagicMock(return_value=['XRP/BTC', 'ETH/BTC']))
    arglist = ['download-data', '--exchange', 'binance']

    args = Arguments(arglist, '').get_parsed_arg()

    configuration = Configuration(args)
    config = configuration.get_config()

    assert config['pairs'] == ['ETH/BTC', 'XRP/BTC']
    assert config['exchange']['name'] == 'binance'
Example #20
0
def setup_configuration(args: Namespace) -> Dict[str, Any]:
    """
    Prepare the configuration for edge backtesting
    :param args: Cli args from Arguments()
    :return: Configuration
    """
    configuration = Configuration(args, RunMode.EDGECLI)
    config = configuration.get_config()

    # Ensure we do not use Exchange credentials
    config['exchange']['key'] = ''
    config['exchange']['secret'] = ''

    return config
Example #21
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()
Example #22
0
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
    )
Example #23
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:
        # 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"
Example #24
0
def test_validate_tsl(default_conf):
    default_conf['trailing_stop'] = True
    default_conf['trailing_stop_positive'] = 0
    default_conf['trailing_stop_positive_offset'] = 0

    default_conf['trailing_only_offset_is_reached'] = True
    with pytest.raises(OperationalException,
                       match=r'The config trailing_only_offset_is_reached needs '
                       'trailing_stop_positive_offset to be more than 0 in your config.'):
        configuration = Configuration(Namespace())
        configuration._validate_config_consistency(default_conf)

    default_conf['trailing_stop_positive_offset'] = 0.01
    default_conf['trailing_stop_positive'] = 0.015
    with pytest.raises(OperationalException,
                       match=r'The config trailing_stop_positive_offset needs '
                       'to be greater than trailing_stop_positive_offset in your config.'):
        configuration = Configuration(Namespace())
        configuration._validate_config_consistency(default_conf)

    default_conf['trailing_stop_positive'] = 0.01
    default_conf['trailing_stop_positive_offset'] = 0.015
    Configuration(Namespace())
    configuration._validate_config_consistency(default_conf)
Example #25
0
def main(sysargv: List[str]) -> None:
    """
    This function will initiate the bot and start the trading loop.
    :return: None
    """
    arguments = Arguments(
        sysargv,
        'Free, open source crypto trading bot'
    )
    args = arguments.get_parsed_arg()

    # A subcommand has been issued.
    # Means if Backtesting or Hyperopt have been called we exit the bot
    if hasattr(args, 'func'):
        args.func(args)
        return

    freqtrade = None
    return_code = 1
    try:
        # Load and validate configuration
        config = Configuration(args).get_config()

        # Init the bot
        freqtrade = FreqtradeBot(config)

        state = None
        while True:
            state = freqtrade.worker(old_state=state)
            if state == State.RELOAD_CONF:
                freqtrade = reconfigure(freqtrade, args)

    except KeyboardInterrupt:
        logger.info('SIGINT received, aborting ...')
        return_code = 0
    except OperationalException as e:
        logger.error(str(e))
        return_code = 2
    except BaseException:
        logger.exception('Fatal exception!')
    finally:
        if freqtrade:
            freqtrade.rpc.send_msg({
                'type': RPCMessageType.STATUS_NOTIFICATION,
                'status': 'process died'
            })
            freqtrade.cleanup()
        sys.exit(return_code)
Example #26
0
    def _init(self, reconfig: bool) -> None:
        """
        Also called from the _reconfigure() method (with reconfig=True).
        """
        if reconfig or self._config is None:
            # Load configuration
            self._config = Configuration(self._args, None).get_config()

        # Init the instance of the bot
        self.freqtrade = FreqtradeBot(self._config)

        self._throttle_secs = self._config.get('internals', {}).get(
            'process_throttle_secs', constants.PROCESS_THROTTLE_SECS)

        self._sd_notify = sdnotify.SystemdNotifier() if \
            self._config.get('internals', {}).get('sd_notify', False) else None
def setup_utils_configuration(args: Namespace,
                              method: RunMode) -> Dict[str, Any]:
    """
    Prepare the configuration for utils subcommands
    :param args: Cli args from Arguments()
    :return: Configuration
    """
    configuration = Configuration(args, method)
    config = configuration.get_config()

    config['exchange']['dry_run'] = True
    # Ensure we do not use Exchange credentials
    config['exchange']['key'] = ''
    config['exchange']['secret'] = ''

    return config
def test_set_logfile(default_conf, mocker):
    mocker.patch('freqtrade.configuration.open',
                 mocker.mock_open(read_data=json.dumps(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_pairlist_resolving_fallback(mocker):
    mocker.patch.object(Path, "exists", MagicMock(return_value=True))
    mocker.patch.object(Path, "open", MagicMock(return_value=MagicMock()))
    mocker.patch("freqtrade.configuration.configuration.json_load",
                 MagicMock(return_value=['XRP/BTC', 'ETH/BTC']))
    arglist = ['download-data', '--exchange', 'binance']

    args = Arguments(arglist).get_parsed_arg()
    # Fix flaky tests if config.json exists
    args["config"] = None

    configuration = Configuration(args, RunMode.OTHER)
    config = configuration.get_config()

    assert config['pairs'] == ['ETH/BTC', 'XRP/BTC']
    assert config['exchange']['name'] == 'binance'
    assert config['datadir'] == str(Path.cwd() / "user_data/data/binance")
Example #30
0
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