diff --git a/freqtrade/configuration/check_exchange.py b/freqtrade/configuration/check_exchange.py index 61e862a9c..19c377732 100644 --- a/freqtrade/configuration/check_exchange.py +++ b/freqtrade/configuration/check_exchange.py @@ -27,6 +27,14 @@ def check_exchange(config: Dict[str, Any], check_for_bad: bool = True) -> bool: logger.info("Checking exchange...") exchange = config.get('exchange', {}).get('name').lower() + if not exchange: + raise OperationalException( + f'This command requires a configured exchange. You should either use ' + f'`--exchange ` or specify a configuration file via `--config`.\n' + f'The following exchanges are supported by ccxt: ' + f'{", ".join(available_exchanges())}' + ) + if not is_exchange_available(exchange): raise OperationalException( f'Exchange "{exchange}" is not supported by ccxt ' diff --git a/freqtrade/utils.py b/freqtrade/utils.py index 5b2b08357..6ce5e888c 100644 --- a/freqtrade/utils.py +++ b/freqtrade/utils.py @@ -5,6 +5,7 @@ from typing import Any, Dict, List import arrow +from freqtrade import OperationalException from freqtrade.configuration import Configuration, TimeRange from freqtrade.configuration.directory_operations import create_userdata_dir from freqtrade.data.history import refresh_backtest_ohlcv_data @@ -70,6 +71,11 @@ def start_download_data(args: Dict[str, Any]) -> None: time_since = arrow.utcnow().shift(days=-config['days']).strftime("%Y%m%d") timerange = TimeRange.parse_timerange(f'{time_since}-') + if 'pairs' not in config: + raise OperationalException( + "Downloading data requires a list of pairs. " + "Please check the documentation on how to configure this.") + dl_path = Path(config['datadir']) logger.info(f'About to download pairs: {config["pairs"]}, ' f'intervals: {config["timeframes"]} to {dl_path}') diff --git a/tests/test_configuration.py b/tests/test_configuration.py index 2cf273091..7cb30f1b3 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -546,6 +546,13 @@ def test_check_exchange(default_conf, caplog) -> None: default_conf['runmode'] = RunMode.PLOT assert check_exchange(default_conf) + # Test no exchange... + default_conf.get('exchange').update({'name': ''}) + default_conf['runmode'] = RunMode.OTHER + with pytest.raises(OperationalException, + match=r'This command requires a configured exchange.*'): + check_exchange(default_conf) + def test_cli_verbose_with_params(default_conf, mocker, caplog) -> None: patched_configuration_load_config_file(mocker, default_conf) diff --git a/tests/test_utils.py b/tests/test_utils.py index 386efb5ec..dc0badd01 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,12 +1,14 @@ import re +from pathlib import Path from unittest.mock import MagicMock, PropertyMock import pytest +from freqtrade import OperationalException from freqtrade.state import RunMode -from tests.conftest import get_args, log_has, patch_exchange from freqtrade.utils import (setup_utils_configuration, start_create_userdir, start_download_data, start_list_exchanges) +from tests.conftest import get_args, log_has, patch_exchange def test_setup_utils_configuration(): @@ -103,3 +105,37 @@ def test_download_data_no_markets(mocker, caplog): start_download_data(get_args(args)) assert dl_mock.call_args[1]['timerange'].starttype == "date" assert log_has("Pairs [ETH/BTC,XRP/BTC] not available on exchange binance.", caplog) + + +def test_download_data_no_exchange(mocker, caplog): + mocker.patch('freqtrade.utils.refresh_backtest_ohlcv_data', + MagicMock(return_value=["ETH/BTC", "XRP/BTC"])) + patch_exchange(mocker) + mocker.patch( + 'freqtrade.exchange.Exchange.markets', PropertyMock(return_value={}) + ) + args = [ + "download-data", + ] + with pytest.raises(OperationalException, + match=r"This command requires a configured exchange.*"): + start_download_data(get_args(args)) + + +def test_download_data_no_pairs(mocker, caplog): + mocker.patch.object(Path, "exists", MagicMock(return_value=False)) + + mocker.patch('freqtrade.utils.refresh_backtest_ohlcv_data', + MagicMock(return_value=["ETH/BTC", "XRP/BTC"])) + patch_exchange(mocker) + mocker.patch( + 'freqtrade.exchange.Exchange.markets', PropertyMock(return_value={}) + ) + args = [ + "download-data", + "--exchange", + "binance", + ] + with pytest.raises(OperationalException, + match=r"Downloading data requires a list of pairs\..*"): + start_download_data(get_args(args))