diff --git a/freqtrade/commands/__init__.py b/freqtrade/commands/__init__.py index 2d0c7733c..4ce3eb421 100644 --- a/freqtrade/commands/__init__.py +++ b/freqtrade/commands/__init__.py @@ -9,7 +9,8 @@ Note: Be careful with file-scoped imports in these subfiles. from freqtrade.commands.arguments import Arguments from freqtrade.commands.build_config_commands import start_new_config from freqtrade.commands.data_commands import (start_convert_data, - start_download_data) + start_download_data, + start_list_data) from freqtrade.commands.deploy_commands import (start_create_userdir, start_new_hyperopt, start_new_strategy) diff --git a/freqtrade/commands/arguments.py b/freqtrade/commands/arguments.py index 72f2a02f0..a49d917a5 100644 --- a/freqtrade/commands/arguments.py +++ b/freqtrade/commands/arguments.py @@ -54,6 +54,8 @@ ARGS_BUILD_HYPEROPT = ["user_data_dir", "hyperopt", "template"] ARGS_CONVERT_DATA = ["pairs", "format_from", "format_to", "erase"] ARGS_CONVERT_DATA_OHLCV = ARGS_CONVERT_DATA + ["timeframes"] +ARGS_LIST_DATA = ["exchange", "dataformat_ohlcv"] + ARGS_DOWNLOAD_DATA = ["pairs", "pairs_file", "days", "download_trades", "exchange", "timeframes", "erase", "dataformat_ohlcv", "dataformat_trades"] @@ -78,7 +80,7 @@ ARGS_HYPEROPT_SHOW = ["hyperopt_list_best", "hyperopt_list_profitable", "hyperop "print_json", "hyperopt_show_no_header"] NO_CONF_REQURIED = ["convert-data", "convert-trade-data", "download-data", "list-timeframes", - "list-markets", "list-pairs", "list-strategies", + "list-markets", "list-pairs", "list-strategies", "list-data", "list-hyperopts", "hyperopt-list", "hyperopt-show", "plot-dataframe", "plot-profit", "show-trades"] @@ -159,7 +161,7 @@ class Arguments: self._build_args(optionlist=['version'], parser=self.parser) from freqtrade.commands import (start_create_userdir, start_convert_data, - start_download_data, + start_download_data, start_list_data, start_hyperopt_list, start_hyperopt_show, start_list_exchanges, start_list_hyperopts, start_list_markets, start_list_strategies, @@ -233,6 +235,15 @@ class Arguments: convert_trade_data_cmd.set_defaults(func=partial(start_convert_data, ohlcv=False)) self._build_args(optionlist=ARGS_CONVERT_DATA, parser=convert_trade_data_cmd) + # Add list-data subcommand + list_data_cmd = subparsers.add_parser( + 'list-data', + help='List downloaded data.', + parents=[_common_parser], + ) + list_data_cmd.set_defaults(func=start_list_data) + self._build_args(optionlist=ARGS_LIST_DATA, parser=list_data_cmd) + # Add backtesting subcommand backtesting_cmd = subparsers.add_parser('backtesting', help='Backtesting module.', parents=[_common_parser, _strategy_parser]) diff --git a/freqtrade/commands/data_commands.py b/freqtrade/commands/data_commands.py index fc3a49f1d..4a37bdc08 100644 --- a/freqtrade/commands/data_commands.py +++ b/freqtrade/commands/data_commands.py @@ -1,5 +1,6 @@ import logging import sys +from collections import defaultdict from typing import Any, Dict, List import arrow @@ -11,6 +12,7 @@ from freqtrade.data.history import (convert_trades_to_ohlcv, refresh_backtest_ohlcv_data, refresh_backtest_trades_data) from freqtrade.exceptions import OperationalException +from freqtrade.exchange import timeframe_to_minutes from freqtrade.resolvers import ExchangeResolver from freqtrade.state import RunMode @@ -88,3 +90,24 @@ def start_convert_data(args: Dict[str, Any], ohlcv: bool = True) -> None: convert_trades_format(config, convert_from=args['format_from'], convert_to=args['format_to'], erase=args['erase']) + + +def start_list_data(args: Dict[str, Any]) -> None: + """ + List available backtest data + """ + + config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) + + from freqtrade.data.history.idatahandler import get_datahandlerclass + from tabulate import tabulate + dhc = get_datahandlerclass(config['dataformat_ohlcv']) + paircombs = dhc.ohlcv_get_available_data(config['datadir']) + + print(f"Found {len(paircombs)} pair / timeframe combinations.") + groupedpair = defaultdict(list) + for pair, timeframe in sorted(paircombs, key=lambda x: (x[0], timeframe_to_minutes(x[1]))): + groupedpair[pair].append(timeframe) + + print(tabulate([(pair, ', '.join(timeframes)) for pair, timeframes in groupedpair.items()], + headers=("pairs", "timeframe")))