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'
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_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_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)
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
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_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)
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)
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
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'
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
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_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'
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
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_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__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_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)
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)
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")
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