We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
download-data fails with difficult to interpret messages in certain cases
1)
```
(.env) user@nuc:~/freqtrade-wrk/github-hroff-1902/freqtrade$ freqtrade download-data
2019-09-06 01:00:01,335 - freqtrade.loggers - INFO - Verbosity set to 0
2019-09-06 01:00:01,336 - freqtrade.configuration.configuration - INFO - Dry run is enabled
2019-09-06 01:00:01,336 - freqtrade.configuration.configuration - INFO - Using DB: "sqlite://"
2019-09-06 01:00:01,336 - freqtrade.configuration.configuration - INFO - Using max_open_trades: None ...
2019-09-06 01:00:01,336 - freqtrade.configuration.configuration - INFO - Using user-data directory: /home/user/freqtrade-wrk/github-hroff-1902/freqtrade/user_data ...
2019-09-06 01:00:01,337 - freqtrade.configuration.configuration - INFO - Using data directory: /home/user/freqtrade-wrk/github-hroff-1902/freqtrade/user_data/data ...
2019-09-06 01:00:01,337 - freqtrade.configuration.configuration - INFO - timeframes --timeframes: ['1m', '5m']
2019-09-06 01:00:01,337 - freqtrade.configuration.check_exchange - INFO - Checking exchange...
2019-09-06 01:00:01,337 - freqtrade - ERROR - Exchange "" is not supported by ccxt and therefore not available for the bot.
The following exchanges are supported by ccxt: _1btcxe, acx, allcoin, anxpro, bcex, bequant, bibox, bigone, binance, binanceje, bit2c, bitbank, bitbay, bitfinex, bitfinex2, bitflyer, bitforex, bithumb, bitkk, bitlish, bitmart, bitmex, bitso, bitstamp, bitstamp1, bittrex, bitz, bl3p, bleutrade, braziliex, btcalpha, btcbox, btcchina, btcmarkets, btctradeim, btctradeua, btcturk, buda, bxinth, cex, chilebit, cobinhood, coinbase, coinbaseprime, coinbasepro, coincheck, coinegg, coinex, coinexchange, coinfalcon, coinfloor, coingi, coinmarketcap, coinmate, coinone, coinspot, cointiger, coolcoin, coss, crex24, crypton, deribit, digifinex, dsx, dx, ethfinex, exmo, exx, fcoin, fcoinjp, flowbtc, foxbit, fybse, gateio, gdax, gemini, hitbtc, hitbtc2, huobipro, huobiru, ice3x, independentreserve, indodax, itbit, kkex, kraken, kucoin, kucoin2, kuna, lakebtc, latoken, lbank, liquid, livecoin, luno, lykke, mandala, mercado, mixcoins, negociecoins, nova, oceanex, okcoincny, okcoinusd, okex, okex3, paymium, poloniex, rightbtc, southxchange, stronghold, surbitcoin, theocean, therock, tidebit, tidex, upbit, vaultoro, vbtc, virwox, xbtce, yobit, zaif, zb
```
-- Maybe it's covered by #2217  . If not, the message should not include `Exchange ""` but should be something like `Exchange is not specified.`

2) 
```
(.env) user@nuc:~/freqtrade-wrk/github-hroff-1902/freqtrade$ freqtrade download-data --exchange bittrex
2019-09-06 01:00:15,176 - freqtrade.loggers - INFO - Verbosity set to 0
2019-09-06 01:00:15,177 - freqtrade.configuration.configuration - INFO - Dry run is enabled
2019-09-06 01:00:15,177 - freqtrade.configuration.configuration - INFO - Using DB: "sqlite://"
2019-09-06 01:00:15,177 - freqtrade.configuration.configuration - INFO - Using max_open_trades: None ...
2019-09-06 01:00:15,177 - freqtrade.configuration.configuration - INFO - Using exchange bittrex
2019-09-06 01:00:15,178 - freqtrade.configuration.configuration - INFO - Using user-data directory: /home/user/freqtrade-wrk/github-hroff-1902/freqtrade/user_data ...
2019-09-06 01:00:15,178 - freqtrade.configuration.configuration - INFO - Using data directory: /home/user/freqtrade-wrk/github-hroff-1902/freqtrade/user_data/data/bittrex ...
2019-09-06 01:00:15,178 - freqtrade.configuration.configuration - INFO - timeframes --timeframes: ['1m', '5m']
2019-09-06 01:00:15,178 - freqtrade.configuration.check_exchange - INFO - Checking exchange...
2019-09-06 01:00:15,178 - freqtrade.configuration.check_exchange - INFO - Exchange "bittrex" is officially supported by the Freqtrade development team.
2019-09-06 01:00:15,179 - freqtrade - ERROR - Fatal exception!
Traceback (most recent call last):
  File "/home/user/freqtrade-wrk/github-hroff-1902/freqtrade/freqtrade/main.py", line 40, in main
    args.func(args)
  File "/home/user/freqtrade-wrk/github-hroff-1902/freqtrade/freqtrade/utils.py", line 75, in start_download_data
    logger.info(f'About to download pairs: {config["pairs"]}, '
KeyError: 'pairs'
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `freqtrade/configuration/check_exchange.py`
Content:
```
1 import logging
2 from typing import Any, Dict
3 
4 from freqtrade import OperationalException
5 from freqtrade.exchange import (available_exchanges, get_exchange_bad_reason,
6                                 is_exchange_available, is_exchange_bad,
7                                 is_exchange_officially_supported)
8 from freqtrade.state import RunMode
9 
10 logger = logging.getLogger(__name__)
11 
12 
13 def check_exchange(config: Dict[str, Any], check_for_bad: bool = True) -> bool:
14     """
15     Check if the exchange name in the config file is supported by Freqtrade
16     :param check_for_bad: if True, check the exchange against the list of known 'bad'
17                           exchanges
18     :return: False if exchange is 'bad', i.e. is known to work with the bot with
19              critical issues or does not work at all, crashes, etc. True otherwise.
20              raises an exception if the exchange if not supported by ccxt
21              and thus is not known for the Freqtrade at all.
22     """
23 
24     if config['runmode'] in [RunMode.PLOT] and not config.get('exchange', {}).get('name'):
25         # Skip checking exchange in plot mode, since it requires no exchange
26         return True
27     logger.info("Checking exchange...")
28 
29     exchange = config.get('exchange', {}).get('name').lower()
30     if not is_exchange_available(exchange):
31         raise OperationalException(
32                 f'Exchange "{exchange}" is not supported by ccxt '
33                 f'and therefore not available for the bot.\n'
34                 f'The following exchanges are supported by ccxt: '
35                 f'{", ".join(available_exchanges())}'
36         )
37 
38     if check_for_bad and is_exchange_bad(exchange):
39         raise OperationalException(f'Exchange "{exchange}" is known to not work with the bot yet. '
40                                    f'Reason: {get_exchange_bad_reason(exchange)}')
41 
42     if is_exchange_officially_supported(exchange):
43         logger.info(f'Exchange "{exchange}" is officially supported '
44                     f'by the Freqtrade development team.')
45     else:
46         logger.warning(f'Exchange "{exchange}" is supported by ccxt '
47                        f'and therefore available for the bot but not officially supported '
48                        f'by the Freqtrade development team. '
49                        f'It may work flawlessly (please report back) or have serious issues. '
50                        f'Use it at your own discretion.')
51 
52     return True
53
```

Path: `freqtrade/utils.py`
Content:
```
1 import logging
2 import sys
3 from pathlib import Path
4 from typing import Any, Dict, List
5 
6 import arrow
7 
8 from freqtrade.configuration import Configuration, TimeRange
9 from freqtrade.configuration.directory_operations import create_userdata_dir
10 from freqtrade.data.history import refresh_backtest_ohlcv_data
11 from freqtrade.exchange import available_exchanges
12 from freqtrade.resolvers import ExchangeResolver
13 from freqtrade.state import RunMode
14 
15 logger = logging.getLogger(__name__)
16 
17 
18 def setup_utils_configuration(args: Dict[str, Any], method: RunMode) -> Dict[str, Any]:
19     """
20     Prepare the configuration for utils subcommands
21     :param args: Cli args from Arguments()
22     :return: Configuration
23     """
24     configuration = Configuration(args, method)
25     config = configuration.get_config()
26 
27     config['exchange']['dry_run'] = True
28     # Ensure we do not use Exchange credentials
29     config['exchange']['key'] = ''
30     config['exchange']['secret'] = ''
31 
32     return config
33 
34 
35 def start_list_exchanges(args: Dict[str, Any]) -> None:
36     """
37     Print available exchanges
38     :param args: Cli args from Arguments()
39     :return: None
40     """
41 
42     if args['print_one_column']:
43         print('\n'.join(available_exchanges()))
44     else:
45         print(f"Exchanges supported by ccxt and available for Freqtrade: "
46               f"{', '.join(available_exchanges())}")
47 
48 
49 def start_create_userdir(args: Dict[str, Any]) -> None:
50     """
51     Create "user_data" directory to contain user data strategies, hyperopts, ...)
52     :param args: Cli args from Arguments()
53     :return: None
54     """
55     if "user_data_dir" in args and args["user_data_dir"]:
56         create_userdata_dir(args["user_data_dir"], create_dir=True)
57     else:
58         logger.warning("`create-userdir` requires --userdir to be set.")
59         sys.exit(1)
60 
61 
62 def start_download_data(args: Dict[str, Any]) -> None:
63     """
64     Download data (former download_backtest_data.py script)
65     """
66     config = setup_utils_configuration(args, RunMode.OTHER)
67 
68     timerange = TimeRange()
69     if 'days' in config:
70         time_since = arrow.utcnow().shift(days=-config['days']).strftime("%Y%m%d")
71         timerange = TimeRange.parse_timerange(f'{time_since}-')
72 
73     dl_path = Path(config['datadir'])
74     logger.info(f'About to download pairs: {config["pairs"]}, '
75                 f'intervals: {config["timeframes"]} to {dl_path}')
76 
77     pairs_not_available: List[str] = []
78 
79     try:
80         # Init exchange
81         exchange = ExchangeResolver(config['exchange']['name'], config).exchange
82 
83         pairs_not_available = refresh_backtest_ohlcv_data(
84             exchange, pairs=config["pairs"], timeframes=config["timeframes"],
85             dl_path=Path(config['datadir']), timerange=timerange, erase=config.get("erase"))
86 
87     except KeyboardInterrupt:
88         sys.exit("SIGINT received, aborting ...")
89 
90     finally:
91         if pairs_not_available:
92             logger.info(f"Pairs [{','.join(pairs_not_available)}] not available "
93                         f"on exchange {config['exchange']['name']}.")
94
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/freqtrade/configuration/check_exchange.py b/freqtrade/configuration/check_exchange.py
--- a/freqtrade/configuration/check_exchange.py
+++ b/freqtrade/configuration/check_exchange.py
@@ -27,6 +27,14 @@
     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 <exchange_name>` 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
--- a/freqtrade/utils.py
+++ b/freqtrade/utils.py
@@ -5,6 +5,7 @@
 
 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 @@
         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}')

{"golden_diff": "diff --git a/freqtrade/configuration/check_exchange.py b/freqtrade/configuration/check_exchange.py\n--- a/freqtrade/configuration/check_exchange.py\n+++ b/freqtrade/configuration/check_exchange.py\n@@ -27,6 +27,14 @@\n     logger.info(\"Checking exchange...\")\n \n     exchange = config.get('exchange', {}).get('name').lower()\n+    if not exchange:\n+        raise OperationalException(\n+            f'This command requires a configured exchange. You should either use '\n+            f'`--exchange <exchange_name>` or specify a configuration file via `--config`.\\n'\n+            f'The following exchanges are supported by ccxt: '\n+            f'{\", \".join(available_exchanges())}'\n+        )\n+\n     if not is_exchange_available(exchange):\n         raise OperationalException(\n                 f'Exchange \"{exchange}\" is not supported by ccxt '\ndiff --git a/freqtrade/utils.py b/freqtrade/utils.py\n--- a/freqtrade/utils.py\n+++ b/freqtrade/utils.py\n@@ -5,6 +5,7 @@\n \n import arrow\n \n+from freqtrade import OperationalException\n from freqtrade.configuration import Configuration, TimeRange\n from freqtrade.configuration.directory_operations import create_userdata_dir\n from freqtrade.data.history import refresh_backtest_ohlcv_data\n@@ -70,6 +71,11 @@\n         time_since = arrow.utcnow().shift(days=-config['days']).strftime(\"%Y%m%d\")\n         timerange = TimeRange.parse_timerange(f'{time_since}-')\n \n+    if 'pairs' not in config:\n+        raise OperationalException(\n+            \"Downloading data requires a list of pairs. \"\n+            \"Please check the documentation on how to configure this.\")\n+\n     dl_path = Path(config['datadir'])\n     logger.info(f'About to download pairs: {config[\"pairs\"]}, '\n                 f'intervals: {config[\"timeframes\"]} to {dl_path}')\n", "issue": "download-data fails with difficult to interpret messages in certain cases\n1)\r\n```\r\n(.env) user@nuc:~/freqtrade-wrk/github-hroff-1902/freqtrade$ freqtrade download-data\r\n2019-09-06 01:00:01,335 - freqtrade.loggers - INFO - Verbosity set to 0\r\n2019-09-06 01:00:01,336 - freqtrade.configuration.configuration - INFO - Dry run is enabled\r\n2019-09-06 01:00:01,336 - freqtrade.configuration.configuration - INFO - Using DB: \"sqlite://\"\r\n2019-09-06 01:00:01,336 - freqtrade.configuration.configuration - INFO - Using max_open_trades: None ...\r\n2019-09-06 01:00:01,336 - freqtrade.configuration.configuration - INFO - Using user-data directory: /home/user/freqtrade-wrk/github-hroff-1902/freqtrade/user_data ...\r\n2019-09-06 01:00:01,337 - freqtrade.configuration.configuration - INFO - Using data directory: /home/user/freqtrade-wrk/github-hroff-1902/freqtrade/user_data/data ...\r\n2019-09-06 01:00:01,337 - freqtrade.configuration.configuration - INFO - timeframes --timeframes: ['1m', '5m']\r\n2019-09-06 01:00:01,337 - freqtrade.configuration.check_exchange - INFO - Checking exchange...\r\n2019-09-06 01:00:01,337 - freqtrade - ERROR - Exchange \"\" is not supported by ccxt and therefore not available for the bot.\r\nThe following exchanges are supported by ccxt: _1btcxe, acx, allcoin, anxpro, bcex, bequant, bibox, bigone, binance, binanceje, bit2c, bitbank, bitbay, bitfinex, bitfinex2, bitflyer, bitforex, bithumb, bitkk, bitlish, bitmart, bitmex, bitso, bitstamp, bitstamp1, bittrex, bitz, bl3p, bleutrade, braziliex, btcalpha, btcbox, btcchina, btcmarkets, btctradeim, btctradeua, btcturk, buda, bxinth, cex, chilebit, cobinhood, coinbase, coinbaseprime, coinbasepro, coincheck, coinegg, coinex, coinexchange, coinfalcon, coinfloor, coingi, coinmarketcap, coinmate, coinone, coinspot, cointiger, coolcoin, coss, crex24, crypton, deribit, digifinex, dsx, dx, ethfinex, exmo, exx, fcoin, fcoinjp, flowbtc, foxbit, fybse, gateio, gdax, gemini, hitbtc, hitbtc2, huobipro, huobiru, ice3x, independentreserve, indodax, itbit, kkex, kraken, kucoin, kucoin2, kuna, lakebtc, latoken, lbank, liquid, livecoin, luno, lykke, mandala, mercado, mixcoins, negociecoins, nova, oceanex, okcoincny, okcoinusd, okex, okex3, paymium, poloniex, rightbtc, southxchange, stronghold, surbitcoin, theocean, therock, tidebit, tidex, upbit, vaultoro, vbtc, virwox, xbtce, yobit, zaif, zb\r\n```\r\n-- Maybe it's covered by #2217  . If not, the message should not include `Exchange \"\"` but should be something like `Exchange is not specified.`\r\n\r\n2) \r\n```\r\n(.env) user@nuc:~/freqtrade-wrk/github-hroff-1902/freqtrade$ freqtrade download-data --exchange bittrex\r\n2019-09-06 01:00:15,176 - freqtrade.loggers - INFO - Verbosity set to 0\r\n2019-09-06 01:00:15,177 - freqtrade.configuration.configuration - INFO - Dry run is enabled\r\n2019-09-06 01:00:15,177 - freqtrade.configuration.configuration - INFO - Using DB: \"sqlite://\"\r\n2019-09-06 01:00:15,177 - freqtrade.configuration.configuration - INFO - Using max_open_trades: None ...\r\n2019-09-06 01:00:15,177 - freqtrade.configuration.configuration - INFO - Using exchange bittrex\r\n2019-09-06 01:00:15,178 - freqtrade.configuration.configuration - INFO - Using user-data directory: /home/user/freqtrade-wrk/github-hroff-1902/freqtrade/user_data ...\r\n2019-09-06 01:00:15,178 - freqtrade.configuration.configuration - INFO - Using data directory: /home/user/freqtrade-wrk/github-hroff-1902/freqtrade/user_data/data/bittrex ...\r\n2019-09-06 01:00:15,178 - freqtrade.configuration.configuration - INFO - timeframes --timeframes: ['1m', '5m']\r\n2019-09-06 01:00:15,178 - freqtrade.configuration.check_exchange - INFO - Checking exchange...\r\n2019-09-06 01:00:15,178 - freqtrade.configuration.check_exchange - INFO - Exchange \"bittrex\" is officially supported by the Freqtrade development team.\r\n2019-09-06 01:00:15,179 - freqtrade - ERROR - Fatal exception!\r\nTraceback (most recent call last):\r\n  File \"/home/user/freqtrade-wrk/github-hroff-1902/freqtrade/freqtrade/main.py\", line 40, in main\r\n    args.func(args)\r\n  File \"/home/user/freqtrade-wrk/github-hroff-1902/freqtrade/freqtrade/utils.py\", line 75, in start_download_data\r\n    logger.info(f'About to download pairs: {config[\"pairs\"]}, '\r\nKeyError: 'pairs'\r\n```\r\n\n", "before_files": [{"content": "import logging\nfrom typing import Any, Dict\n\nfrom freqtrade import OperationalException\nfrom freqtrade.exchange import (available_exchanges, get_exchange_bad_reason,\n                                is_exchange_available, is_exchange_bad,\n                                is_exchange_officially_supported)\nfrom freqtrade.state import RunMode\n\nlogger = logging.getLogger(__name__)\n\n\ndef check_exchange(config: Dict[str, Any], check_for_bad: bool = True) -> bool:\n    \"\"\"\n    Check if the exchange name in the config file is supported by Freqtrade\n    :param check_for_bad: if True, check the exchange against the list of known 'bad'\n                          exchanges\n    :return: False if exchange is 'bad', i.e. is known to work with the bot with\n             critical issues or does not work at all, crashes, etc. True otherwise.\n             raises an exception if the exchange if not supported by ccxt\n             and thus is not known for the Freqtrade at all.\n    \"\"\"\n\n    if config['runmode'] in [RunMode.PLOT] and not config.get('exchange', {}).get('name'):\n        # Skip checking exchange in plot mode, since it requires no exchange\n        return True\n    logger.info(\"Checking exchange...\")\n\n    exchange = config.get('exchange', {}).get('name').lower()\n    if not is_exchange_available(exchange):\n        raise OperationalException(\n                f'Exchange \"{exchange}\" is not supported by ccxt '\n                f'and therefore not available for the bot.\\n'\n                f'The following exchanges are supported by ccxt: '\n                f'{\", \".join(available_exchanges())}'\n        )\n\n    if check_for_bad and is_exchange_bad(exchange):\n        raise OperationalException(f'Exchange \"{exchange}\" is known to not work with the bot yet. '\n                                   f'Reason: {get_exchange_bad_reason(exchange)}')\n\n    if is_exchange_officially_supported(exchange):\n        logger.info(f'Exchange \"{exchange}\" is officially supported '\n                    f'by the Freqtrade development team.')\n    else:\n        logger.warning(f'Exchange \"{exchange}\" is supported by ccxt '\n                       f'and therefore available for the bot but not officially supported '\n                       f'by the Freqtrade development team. '\n                       f'It may work flawlessly (please report back) or have serious issues. '\n                       f'Use it at your own discretion.')\n\n    return True\n", "path": "freqtrade/configuration/check_exchange.py"}, {"content": "import logging\nimport sys\nfrom pathlib import Path\nfrom typing import Any, Dict, List\n\nimport arrow\n\nfrom freqtrade.configuration import Configuration, TimeRange\nfrom freqtrade.configuration.directory_operations import create_userdata_dir\nfrom freqtrade.data.history import refresh_backtest_ohlcv_data\nfrom freqtrade.exchange import available_exchanges\nfrom freqtrade.resolvers import ExchangeResolver\nfrom freqtrade.state import RunMode\n\nlogger = logging.getLogger(__name__)\n\n\ndef setup_utils_configuration(args: Dict[str, Any], method: RunMode) -> Dict[str, Any]:\n    \"\"\"\n    Prepare the configuration for utils subcommands\n    :param args: Cli args from Arguments()\n    :return: Configuration\n    \"\"\"\n    configuration = Configuration(args, method)\n    config = configuration.get_config()\n\n    config['exchange']['dry_run'] = True\n    # Ensure we do not use Exchange credentials\n    config['exchange']['key'] = ''\n    config['exchange']['secret'] = ''\n\n    return config\n\n\ndef start_list_exchanges(args: Dict[str, Any]) -> None:\n    \"\"\"\n    Print available exchanges\n    :param args: Cli args from Arguments()\n    :return: None\n    \"\"\"\n\n    if args['print_one_column']:\n        print('\\n'.join(available_exchanges()))\n    else:\n        print(f\"Exchanges supported by ccxt and available for Freqtrade: \"\n              f\"{', '.join(available_exchanges())}\")\n\n\ndef start_create_userdir(args: Dict[str, Any]) -> None:\n    \"\"\"\n    Create \"user_data\" directory to contain user data strategies, hyperopts, ...)\n    :param args: Cli args from Arguments()\n    :return: None\n    \"\"\"\n    if \"user_data_dir\" in args and args[\"user_data_dir\"]:\n        create_userdata_dir(args[\"user_data_dir\"], create_dir=True)\n    else:\n        logger.warning(\"`create-userdir` requires --userdir to be set.\")\n        sys.exit(1)\n\n\ndef start_download_data(args: Dict[str, Any]) -> None:\n    \"\"\"\n    Download data (former download_backtest_data.py script)\n    \"\"\"\n    config = setup_utils_configuration(args, RunMode.OTHER)\n\n    timerange = TimeRange()\n    if 'days' in config:\n        time_since = arrow.utcnow().shift(days=-config['days']).strftime(\"%Y%m%d\")\n        timerange = TimeRange.parse_timerange(f'{time_since}-')\n\n    dl_path = Path(config['datadir'])\n    logger.info(f'About to download pairs: {config[\"pairs\"]}, '\n                f'intervals: {config[\"timeframes\"]} to {dl_path}')\n\n    pairs_not_available: List[str] = []\n\n    try:\n        # Init exchange\n        exchange = ExchangeResolver(config['exchange']['name'], config).exchange\n\n        pairs_not_available = refresh_backtest_ohlcv_data(\n            exchange, pairs=config[\"pairs\"], timeframes=config[\"timeframes\"],\n            dl_path=Path(config['datadir']), timerange=timerange, erase=config.get(\"erase\"))\n\n    except KeyboardInterrupt:\n        sys.exit(\"SIGINT received, aborting ...\")\n\n    finally:\n        if pairs_not_available:\n            logger.info(f\"Pairs [{','.join(pairs_not_available)}] not available \"\n                        f\"on exchange {config['exchange']['name']}.\")\n", "path": "freqtrade/utils.py"}], "after_files": [{"content": "import logging\nfrom typing import Any, Dict\n\nfrom freqtrade import OperationalException\nfrom freqtrade.exchange import (available_exchanges, get_exchange_bad_reason,\n                                is_exchange_available, is_exchange_bad,\n                                is_exchange_officially_supported)\nfrom freqtrade.state import RunMode\n\nlogger = logging.getLogger(__name__)\n\n\ndef check_exchange(config: Dict[str, Any], check_for_bad: bool = True) -> bool:\n    \"\"\"\n    Check if the exchange name in the config file is supported by Freqtrade\n    :param check_for_bad: if True, check the exchange against the list of known 'bad'\n                          exchanges\n    :return: False if exchange is 'bad', i.e. is known to work with the bot with\n             critical issues or does not work at all, crashes, etc. True otherwise.\n             raises an exception if the exchange if not supported by ccxt\n             and thus is not known for the Freqtrade at all.\n    \"\"\"\n\n    if config['runmode'] in [RunMode.PLOT] and not config.get('exchange', {}).get('name'):\n        # Skip checking exchange in plot mode, since it requires no exchange\n        return True\n    logger.info(\"Checking exchange...\")\n\n    exchange = config.get('exchange', {}).get('name').lower()\n    if not exchange:\n        raise OperationalException(\n            f'This command requires a configured exchange. You should either use '\n            f'`--exchange <exchange_name>` or specify a configuration file via `--config`.\\n'\n            f'The following exchanges are supported by ccxt: '\n            f'{\", \".join(available_exchanges())}'\n        )\n\n    if not is_exchange_available(exchange):\n        raise OperationalException(\n                f'Exchange \"{exchange}\" is not supported by ccxt '\n                f'and therefore not available for the bot.\\n'\n                f'The following exchanges are supported by ccxt: '\n                f'{\", \".join(available_exchanges())}'\n        )\n\n    if check_for_bad and is_exchange_bad(exchange):\n        raise OperationalException(f'Exchange \"{exchange}\" is known to not work with the bot yet. '\n                                   f'Reason: {get_exchange_bad_reason(exchange)}')\n\n    if is_exchange_officially_supported(exchange):\n        logger.info(f'Exchange \"{exchange}\" is officially supported '\n                    f'by the Freqtrade development team.')\n    else:\n        logger.warning(f'Exchange \"{exchange}\" is supported by ccxt '\n                       f'and therefore available for the bot but not officially supported '\n                       f'by the Freqtrade development team. '\n                       f'It may work flawlessly (please report back) or have serious issues. '\n                       f'Use it at your own discretion.')\n\n    return True\n", "path": "freqtrade/configuration/check_exchange.py"}, {"content": "import logging\nimport sys\nfrom pathlib import Path\nfrom typing import Any, Dict, List\n\nimport arrow\n\nfrom freqtrade import OperationalException\nfrom freqtrade.configuration import Configuration, TimeRange\nfrom freqtrade.configuration.directory_operations import create_userdata_dir\nfrom freqtrade.data.history import refresh_backtest_ohlcv_data\nfrom freqtrade.exchange import available_exchanges\nfrom freqtrade.resolvers import ExchangeResolver\nfrom freqtrade.state import RunMode\n\nlogger = logging.getLogger(__name__)\n\n\ndef setup_utils_configuration(args: Dict[str, Any], method: RunMode) -> Dict[str, Any]:\n    \"\"\"\n    Prepare the configuration for utils subcommands\n    :param args: Cli args from Arguments()\n    :return: Configuration\n    \"\"\"\n    configuration = Configuration(args, method)\n    config = configuration.get_config()\n\n    config['exchange']['dry_run'] = True\n    # Ensure we do not use Exchange credentials\n    config['exchange']['key'] = ''\n    config['exchange']['secret'] = ''\n\n    return config\n\n\ndef start_list_exchanges(args: Dict[str, Any]) -> None:\n    \"\"\"\n    Print available exchanges\n    :param args: Cli args from Arguments()\n    :return: None\n    \"\"\"\n\n    if args['print_one_column']:\n        print('\\n'.join(available_exchanges()))\n    else:\n        print(f\"Exchanges supported by ccxt and available for Freqtrade: \"\n              f\"{', '.join(available_exchanges())}\")\n\n\ndef start_create_userdir(args: Dict[str, Any]) -> None:\n    \"\"\"\n    Create \"user_data\" directory to contain user data strategies, hyperopts, ...)\n    :param args: Cli args from Arguments()\n    :return: None\n    \"\"\"\n    if \"user_data_dir\" in args and args[\"user_data_dir\"]:\n        create_userdata_dir(args[\"user_data_dir\"], create_dir=True)\n    else:\n        logger.warning(\"`create-userdir` requires --userdir to be set.\")\n        sys.exit(1)\n\n\ndef start_download_data(args: Dict[str, Any]) -> None:\n    \"\"\"\n    Download data (former download_backtest_data.py script)\n    \"\"\"\n    config = setup_utils_configuration(args, RunMode.OTHER)\n\n    timerange = TimeRange()\n    if 'days' in config:\n        time_since = arrow.utcnow().shift(days=-config['days']).strftime(\"%Y%m%d\")\n        timerange = TimeRange.parse_timerange(f'{time_since}-')\n\n    if 'pairs' not in config:\n        raise OperationalException(\n            \"Downloading data requires a list of pairs. \"\n            \"Please check the documentation on how to configure this.\")\n\n    dl_path = Path(config['datadir'])\n    logger.info(f'About to download pairs: {config[\"pairs\"]}, '\n                f'intervals: {config[\"timeframes\"]} to {dl_path}')\n\n    pairs_not_available: List[str] = []\n\n    try:\n        # Init exchange\n        exchange = ExchangeResolver(config['exchange']['name'], config).exchange\n\n        pairs_not_available = refresh_backtest_ohlcv_data(\n            exchange, pairs=config[\"pairs\"], timeframes=config[\"timeframes\"],\n            dl_path=Path(config['datadir']), timerange=timerange, erase=config.get(\"erase\"))\n\n    except KeyboardInterrupt:\n        sys.exit(\"SIGINT received, aborting ...\")\n\n    finally:\n        if pairs_not_available:\n            logger.info(f\"Pairs [{','.join(pairs_not_available)}] not available \"\n                        f\"on exchange {config['exchange']['name']}.\")\n", "path": "freqtrade/utils.py"}]}