def start_list_strategies(args: Dict[str, Any]) -> None: """ Print files with Strategy custom classes available in the directory """ config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) directory = Path( config.get('strategy_path', config['user_data_dir'] / USERPATH_STRATEGIES)) strategy_objs = StrategyResolver.search_all_objects( directory, not args['print_one_column'], config.get('recursive_strategy_search', False)) # Sort alphabetically strategy_objs = sorted(strategy_objs, key=lambda x: x['name']) for obj in strategy_objs: if obj['class']: obj['hyperoptable'] = obj['class'].detect_all_parameters() else: obj['hyperoptable'] = {'count': 0} if args['print_one_column']: print('\n'.join([s['name'] for s in strategy_objs])) else: _print_objs_tabular(strategy_objs, config.get('print_colorized', False), directory)
def start_list_data(args: Dict[str, Any]) -> None: """ List available backtest data """ config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) from tabulate import tabulate from freqtrade.data.history.idatahandler import get_datahandler dhc = get_datahandler(config['datadir'], config['dataformat_ohlcv']) paircombs = dhc.ohlcv_get_available_data(config['datadir']) if args['pairs']: paircombs = [comb for comb in paircombs if comb[0] in args['pairs']] 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) if groupedpair: print( tabulate([(pair, ', '.join(timeframes)) for pair, timeframes in groupedpair.items()], headers=("Pair", "Timeframe"), tablefmt='psql', stralign='right'))
def setup_optimize_configuration(args: Dict[str, Any], method: RunMode) -> Dict[str, Any]: """ Prepare the configuration for the Hyperopt module :param args: Cli args from Arguments() :param method: Bot running mode :return: Configuration """ config = setup_utils_configuration(args, method) no_unlimited_runmodes = { RunMode.BACKTEST: 'backtesting', RunMode.HYPEROPT: 'hyperoptimization', } if method in no_unlimited_runmodes.keys(): if (config['stake_amount'] != constants.UNLIMITED_STAKE_AMOUNT and config['stake_amount'] > config['dry_run_wallet']): wallet = round_coin_value(config['dry_run_wallet'], config['stake_currency']) stake = round_coin_value(config['stake_amount'], config['stake_currency']) raise OperationalException( f"Starting balance ({wallet}) " f"is smaller than stake_amount {stake}.") return config
def start_test_pairlist(args: Dict[str, Any]) -> None: """ Test Pairlist configuration """ from freqtrade.plugins.pairlistmanager import PairListManager config = setup_utils_configuration(args, RunMode.UTIL_EXCHANGE) exchange = ExchangeResolver.load_exchange(config['exchange']['name'], config, validate=False) quote_currencies = args.get('quote_currencies') if not quote_currencies: quote_currencies = [config.get('stake_currency')] results = {} for curr in quote_currencies: config['stake_currency'] = curr pairlists = PairListManager(exchange, config) pairlists.refresh_pairlist() results[curr] = pairlists.whitelist for curr, pairlist in results.items(): if not args.get('print_one_column', False) and not args.get( 'list_pairs_print_json', False): print(f"Pairs for {curr}: ") if args.get('print_one_column', False): print('\n'.join(pairlist)) elif args.get('list_pairs_print_json', False): print(rapidjson.dumps(list(pairlist), default=str)) else: print(pairlist)
def start_show_trades(args: Dict[str, Any]) -> None: """ Show trades """ import json from freqtrade.persistence import Trade, init_db config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) if 'db_url' not in config: raise OperationalException("--db-url is required for this command.") logger.info(f'Using DB: "{parse_db_uri_for_logging(config["db_url"])}"') init_db(config['db_url'], clean_open_orders=False) tfilter = [] if config.get('trade_ids'): tfilter.append(Trade.id.in_(config['trade_ids'])) trades = Trade.get_trades(tfilter).all() logger.info(f"Printing {len(trades)} Trades: ") if config.get('print_json', False): print(json.dumps([trade.to_json() for trade in trades], indent=4)) else: for trade in trades: print(trade)
def start_hyperopt_show(args: Dict[str, Any]) -> None: """ Show details of a hyperopt epoch previously evaluated """ from freqtrade.optimize.hyperopt_tools import HyperoptTools config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) print_json = config.get('print_json', False) no_header = config.get('hyperopt_show_no_header', False) results_file = get_latest_hyperopt_file( config['user_data_dir'] / 'hyperopt_results', config.get('hyperoptexportfilename')) n = config.get('hyperopt_show_index', -1) filteroptions = { 'only_best': config.get('hyperopt_list_best', False), 'only_profitable': config.get('hyperopt_list_profitable', False), 'filter_min_trades': config.get('hyperopt_list_min_trades', 0), 'filter_max_trades': config.get('hyperopt_list_max_trades', 0), 'filter_min_avg_time': config.get('hyperopt_list_min_avg_time', None), 'filter_max_avg_time': config.get('hyperopt_list_max_avg_time', None), 'filter_min_avg_profit': config.get('hyperopt_list_min_avg_profit', None), 'filter_max_avg_profit': config.get('hyperopt_list_max_avg_profit', None), 'filter_min_total_profit': config.get('hyperopt_list_min_total_profit', None), 'filter_max_total_profit': config.get('hyperopt_list_max_total_profit', None), 'filter_min_objective': config.get('hyperopt_list_min_objective', None), 'filter_max_objective': config.get('hyperopt_list_max_objective', None) } # Previous evaluations epochs = HyperoptTools.load_previous_results(results_file) total_epochs = len(epochs) epochs = hyperopt_filter_epochs(epochs, filteroptions) filtered_epochs = len(epochs) if n > filtered_epochs: raise OperationalException( f"The index of the epoch to show should be less than {filtered_epochs + 1}.") if n < -filtered_epochs: raise OperationalException( f"The index of the epoch to show should be greater than {-filtered_epochs - 1}.") # Translate epoch index from human-readable format to pythonic if n > 0: n -= 1 if epochs: val = epochs[n] metrics = val['results_metrics'] if 'strategy_name' in metrics: show_backtest_result(metrics['strategy_name'], metrics, metrics['stake_currency']) HyperoptTools.show_epoch_details(val, total_epochs, print_json, no_header, header_str="Epoch details")
def start_hyperopt_list(args: Dict[str, Any]) -> None: """ List hyperopt epochs previously evaluated """ from freqtrade.optimize.hyperopt_tools import HyperoptTools config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) print_colorized = config.get('print_colorized', False) print_json = config.get('print_json', False) export_csv = config.get('export_csv', None) no_details = config.get('hyperopt_list_no_details', False) no_header = False filteroptions = { 'only_best': config.get('hyperopt_list_best', False), 'only_profitable': config.get('hyperopt_list_profitable', False), 'filter_min_trades': config.get('hyperopt_list_min_trades', 0), 'filter_max_trades': config.get('hyperopt_list_max_trades', 0), 'filter_min_avg_time': config.get('hyperopt_list_min_avg_time', None), 'filter_max_avg_time': config.get('hyperopt_list_max_avg_time', None), 'filter_min_avg_profit': config.get('hyperopt_list_min_avg_profit', None), 'filter_max_avg_profit': config.get('hyperopt_list_max_avg_profit', None), 'filter_min_total_profit': config.get('hyperopt_list_min_total_profit', None), 'filter_max_total_profit': config.get('hyperopt_list_max_total_profit', None), 'filter_min_objective': config.get('hyperopt_list_min_objective', None), 'filter_max_objective': config.get('hyperopt_list_max_objective', None), } results_file = get_latest_hyperopt_file( config['user_data_dir'] / 'hyperopt_results', config.get('hyperoptexportfilename')) # Previous evaluations epochs = HyperoptTools.load_previous_results(results_file) total_epochs = len(epochs) epochs = hyperopt_filter_epochs(epochs, filteroptions) if print_colorized: colorama_init(autoreset=True) if not export_csv: try: print(HyperoptTools.get_result_table(config, epochs, total_epochs, not filteroptions['only_best'], print_colorized, 0)) except KeyboardInterrupt: print('User interrupted..') if epochs and not no_details: sorted_epochs = sorted(epochs, key=itemgetter('loss')) results = sorted_epochs[0] HyperoptTools.show_epoch_details(results, total_epochs, print_json, no_header) if epochs and export_csv: HyperoptTools.export_csv_file( config, epochs, total_epochs, not filteroptions['only_best'], export_csv )
def test_setup_utils_configuration(): args = [ 'list-exchanges', '--config', 'config_examples/config_bittrex.example.json', ] config = setup_utils_configuration(get_args(args), RunMode.OTHER) assert "exchange" in config assert config['dry_run'] is True
def start_plot_dataframe(args: Dict[str, Any]) -> None: """ Entrypoint for dataframe plotting """ # Import here to avoid errors if plot-dependencies are not installed. from freqtrade.plot.plotting import load_and_plot_trades validate_plot_args(args) config = setup_utils_configuration(args, RunMode.PLOT) load_and_plot_trades(config)
def test_setup_utils_configuration(): args = [ 'list-exchanges', '--config', 'config_bittrex.json.example', ] config = setup_utils_configuration(get_args(args), RunMode.OTHER) assert "exchange" in config assert config['dry_run'] is True assert config['exchange']['key'] == '' assert config['exchange']['secret'] == ''
def start_plot_profit(args: Dict[str, Any]) -> None: """ Entrypoint for plot_profit """ # Import here to avoid errors if plot-dependencies are not installed. from freqtrade.plot.plotting import plot_profit validate_plot_args(args) config = setup_utils_configuration(args, RunMode.PLOT) plot_profit(config)
def start_hyperopt_show(args: Dict[str, Any]) -> None: """ Show details of a hyperopt epoch previously evaluated """ from freqtrade.optimize.hyperopt_tools import HyperoptTools config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) print_json = config.get('print_json', False) no_header = config.get('hyperopt_show_no_header', False) results_file = get_latest_hyperopt_file( config['user_data_dir'] / 'hyperopt_results', config.get('hyperoptexportfilename')) n = config.get('hyperopt_show_index', -1) # Previous evaluations epochs, total_epochs = HyperoptTools.load_filtered_results( results_file, config) filtered_epochs = len(epochs) if n > filtered_epochs: raise OperationalException( f"The index of the epoch to show should be less than {filtered_epochs + 1}." ) if n < -filtered_epochs: raise OperationalException( f"The index of the epoch to show should be greater than {-filtered_epochs - 1}." ) # Translate epoch index from human-readable format to pythonic if n > 0: n -= 1 if epochs: val = epochs[n] metrics = val['results_metrics'] if 'strategy_name' in metrics: strategy_name = metrics['strategy_name'] show_backtest_result(strategy_name, metrics, metrics['stake_currency'], config.get('backtest_breakdown', [])) HyperoptTools.try_export_params(config, strategy_name, val) HyperoptTools.show_epoch_details(val, total_epochs, print_json, no_header, header_str="Epoch details")
def start_convert_data(args: Dict[str, Any], ohlcv: bool = True) -> None: """ Convert data from one format to another """ config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) if ohlcv: convert_ohlcv_format(config, convert_from=args['format_from'], convert_to=args['format_to'], erase=args['erase']) else: convert_trades_format(config, convert_from=args['format_from'], convert_to=args['format_to'], erase=args['erase'])
def start_backtesting_show(args: Dict[str, Any]) -> None: """ Show previous backtest result """ config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) from freqtrade.data.btanalysis import load_backtest_stats from freqtrade.optimize.optimize_reports import show_backtest_results, show_sorted_pairlist results = load_backtest_stats(config['exportfilename']) show_backtest_results(config, results) show_sorted_pairlist(config, results)
def start_hyperopt_show(args: Dict[str, Any]) -> None: """ Show details of a hyperopt epoch previously evaluated """ from freqtrade.optimize.hyperopt import Hyperopt config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) print_json = config.get('print_json', False) no_header = config.get('hyperopt_show_no_header', False) trials_file = (config['user_data_dir'] / 'hyperopt_results' / 'hyperopt_results.pickle') n = config.get('hyperopt_show_index', -1) filteroptions = { 'only_best': config.get('hyperopt_list_best', False), 'only_profitable': config.get('hyperopt_list_profitable', False), 'filter_min_trades': config.get('hyperopt_list_min_trades', 0), 'filter_max_trades': config.get('hyperopt_list_max_trades', 0), 'filter_min_avg_time': config.get('hyperopt_list_min_avg_time', None), 'filter_max_avg_time': config.get('hyperopt_list_max_avg_time', None), 'filter_min_avg_profit': config.get('hyperopt_list_min_avg_profit', None), 'filter_max_avg_profit': config.get('hyperopt_list_max_avg_profit', None), 'filter_min_total_profit': config.get('hyperopt_list_min_total_profit', None), 'filter_max_total_profit': config.get('hyperopt_list_max_total_profit', None) } # Previous evaluations trials = Hyperopt.load_previous_results(trials_file) total_epochs = len(trials) trials = _hyperopt_filter_trials(trials, filteroptions) trials_epochs = len(trials) if n > trials_epochs: raise OperationalException( f"The index of the epoch to show should be less than {trials_epochs + 1}.") if n < -trials_epochs: raise OperationalException( f"The index of the epoch to show should be greater than {-trials_epochs - 1}.") # Translate epoch index from human-readable format to pythonic if n > 0: n -= 1 if trials: val = trials[n] Hyperopt.print_epoch_details(val, total_epochs, print_json, no_header, header_str="Epoch details")
def start_hyperopt_list(args: Dict[str, Any]) -> None: """ List hyperopt epochs previously evaluated """ from freqtrade.optimize.hyperopt import Hyperopt config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) print_colorized = config.get('print_colorized', False) print_json = config.get('print_json', False) no_details = config.get('hyperopt_list_no_details', False) no_header = False filteroptions = { 'only_best': config.get('hyperopt_list_best', False), 'only_profitable': config.get('hyperopt_list_profitable', False), 'filter_min_trades': config.get('hyperopt_list_min_trades', 0), 'filter_max_trades': config.get('hyperopt_list_max_trades', 0), 'filter_min_avg_time': config.get('hyperopt_list_min_avg_time', None), 'filter_max_avg_time': config.get('hyperopt_list_max_avg_time', None), 'filter_min_avg_profit': config.get('hyperopt_list_min_avg_profit', None), 'filter_max_avg_profit': config.get('hyperopt_list_max_avg_profit', None), 'filter_min_total_profit': config.get('hyperopt_list_min_total_profit', None), 'filter_max_total_profit': config.get('hyperopt_list_max_total_profit', None) } trials_file = (config['user_data_dir'] / 'hyperopt_results' / 'hyperopt_results.pickle') # Previous evaluations trials = Hyperopt.load_previous_results(trials_file) total_epochs = len(trials) trials = _hyperopt_filter_trials(trials, filteroptions) if print_colorized: colorama_init(autoreset=True) try: Hyperopt.print_result_table(config, trials, total_epochs, not filteroptions['only_best'], print_colorized, 0) except KeyboardInterrupt: print('User interrupted..') if trials and not no_details: sorted_trials = sorted(trials, key=itemgetter('loss')) results = sorted_trials[0] Hyperopt.print_epoch_details(results, total_epochs, print_json, no_header)
def start_new_hyperopt(args: Dict[str, Any]) -> None: config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) if 'hyperopt' in args and args['hyperopt']: if args['hyperopt'] == 'DefaultHyperopt': raise OperationalException("DefaultHyperopt is not allowed as name.") new_path = config['user_data_dir'] / USERPATH_HYPEROPTS / (args['hyperopt'] + '.py') if new_path.exists(): raise OperationalException(f"`{new_path}` already exists. " "Please choose another Hyperopt Name.") deploy_new_hyperopt(args['hyperopt'], new_path, args['template']) else: raise OperationalException("`new-hyperopt` requires --hyperopt to be set.")
def start_list_strategies(args: Dict[str, Any]) -> None: """ Print Strategies available in a directory """ config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) directory = Path(config.get('strategy_path', config['user_data_dir'] / USERPATH_STRATEGY)) strategies = StrategyResolver.search_all_objects(directory) # Sort alphabetically strategies = sorted(strategies, key=lambda x: x['name']) strats_to_print = [{'name': s['name'], 'location': s['location'].name} for s in strategies] if args['print_one_column']: print('\n'.join([s['name'] for s in strategies])) else: print(tabulate(strats_to_print, headers='keys', tablefmt='pipe'))
def start_list_timeframes(args: Dict[str, Any]) -> None: """ Print ticker intervals (timeframes) available on Exchange """ config = setup_utils_configuration(args, RunMode.UTIL_EXCHANGE) # Do not use ticker_interval set in the config config['ticker_interval'] = None # Init exchange exchange = ExchangeResolver.load_exchange(config['exchange']['name'], config, validate=False) if args['print_one_column']: print('\n'.join(exchange.timeframes)) else: print(f"Timeframes available for the exchange `{exchange.name}`: " f"{', '.join(exchange.timeframes)}")
def setup_optimize_configuration(args: Dict[str, Any], method: RunMode) -> Dict[str, Any]: """ Prepare the configuration for the Hyperopt module :param args: Cli args from Arguments() :return: Configuration """ config = setup_utils_configuration(args, method) if method == RunMode.BACKTEST: if config['stake_amount'] == constants.UNLIMITED_STAKE_AMOUNT: raise DependencyException( 'stake amount could not be "%s" for backtesting' % constants.UNLIMITED_STAKE_AMOUNT) return config
def start_new_strategy(args: Dict[str, Any]) -> None: config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) if "strategy" in args and args["strategy"]: new_path = config['user_data_dir'] / USERPATH_STRATEGIES / (args['strategy'] + '.py') if new_path.exists(): raise OperationalException(f"`{new_path}` already exists. " "Please choose another Strategy Name.") deploy_new_strategy(args['strategy'], new_path, args['template']) else: raise OperationalException("`new-strategy` requires --strategy to be set.")
def start_list_hyperopts(args: Dict[str, Any]) -> None: """ Print files with HyperOpt custom classes available in the directory """ from freqtrade.resolvers.hyperopt_resolver import HyperOptResolver config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) directory = Path(config.get('hyperopt_path', config['user_data_dir'] / USERPATH_HYPEROPTS)) hyperopt_objs = HyperOptResolver.search_all_objects(directory, not args['print_one_column']) # Sort alphabetically hyperopt_objs = sorted(hyperopt_objs, key=lambda x: x['name']) if args['print_one_column']: print('\n'.join([s['name'] for s in hyperopt_objs])) else: _print_objs_tabular(hyperopt_objs, config.get('print_colorized', False))
def start_download_data(args: Dict[str, Any]) -> None: """ Download data (former download_backtest_data.py script) """ config = setup_utils_configuration(args, RunMode.UTIL_EXCHANGE) timerange = TimeRange() if 'days' in config: 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.") logger.info(f'About to download pairs: {config["pairs"]}, ' f'intervals: {config["timeframes"]} to {config["datadir"]}') pairs_not_available: List[str] = [] # Init exchange exchange = ExchangeResolver.load_exchange(config['exchange']['name'], config) try: if config.get('download_trades'): pairs_not_available = refresh_backtest_trades_data( exchange, pairs=config["pairs"], datadir=config['datadir'], timerange=timerange, erase=config.get("erase")) # Convert downloaded trade data to different timeframes convert_trades_to_ohlcv( pairs=config["pairs"], timeframes=config["timeframes"], datadir=config['datadir'], timerange=timerange, erase=config.get("erase")) else: pairs_not_available = refresh_backtest_ohlcv_data( exchange, pairs=config["pairs"], timeframes=config["timeframes"], datadir=config['datadir'], timerange=timerange, erase=config.get("erase")) except KeyboardInterrupt: sys.exit("SIGINT received, aborting ...") finally: if pairs_not_available: logger.info(f"Pairs [{','.join(pairs_not_available)}] not available " f"on exchange {exchange.name}.")
def get_pickle_data(args: Dict[str, Any]) -> List[Union[List, int]]: """ Fetches the pickle file and returns its raw data. Returns: List[List[], int]: pickle data, total epochs """ config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) trials_file = (config['user_data_dir'] / 'hyperopt_results' / 'hyperopt_results.pickle') # Previous evaluations trials = Hyperopt.load_previous_results(trials_file) total_epochs = len(trials) return [trials, total_epochs]
def start_hyperopt_list(args: Dict[str, Any]) -> None: """ List hyperopt epochs previously evaluated """ from freqtrade.optimize.hyperopt import Hyperopt config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) only_best = config.get('hyperopt_list_best', False) only_profitable = config.get('hyperopt_list_profitable', False) print_colorized = config.get('print_colorized', False) print_json = config.get('print_json', False) no_details = config.get('hyperopt_list_no_details', False) no_header = False trials_file = (config['user_data_dir'] / 'hyperopt_results' / 'hyperopt_results.pickle') # Previous evaluations trials = Hyperopt.load_previous_results(trials_file) total_epochs = len(trials) trials = _hyperopt_filter_trials(trials, only_best, only_profitable) # TODO: fetch the interval for epochs to print from the cli option epoch_start, epoch_stop = 0, None if print_colorized: colorama_init(autoreset=True) try: # Human-friendly indexes used here (starting from 1) for val in trials[epoch_start:epoch_stop]: Hyperopt.print_results_explanation(val, total_epochs, not only_best, print_colorized) except KeyboardInterrupt: print('User interrupted..') if trials and not no_details: sorted_trials = sorted(trials, key=itemgetter('loss')) results = sorted_trials[0] Hyperopt.print_epoch_details(results, total_epochs, print_json, no_header)
def setup_optimize_configuration(args: Dict[str, Any], method: RunMode) -> Dict[str, Any]: """ Prepare the configuration for the Hyperopt module :param args: Cli args from Arguments() :return: Configuration """ config = setup_utils_configuration(args, method) no_unlimited_runmodes = { RunMode.BACKTEST: 'backtesting', RunMode.HYPEROPT: 'hyperoptimization', } if (method in no_unlimited_runmodes.keys() and config['stake_amount'] == constants.UNLIMITED_STAKE_AMOUNT): raise DependencyException( f'The value of `stake_amount` cannot be set as "{constants.UNLIMITED_STAKE_AMOUNT}" ' f'for {no_unlimited_runmodes[method]}') return config
def start_convert_data(args: Dict[str, Any], ohlcv: bool = True) -> None: """ Convert data from one format to another """ config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) if ohlcv: candle_types = [ CandleType.from_string(ct) for ct in config.get('candle_types', ['spot']) ] for candle_type in candle_types: convert_ohlcv_format(config, convert_from=args['format_from'], convert_to=args['format_to'], erase=args['erase'], candle_type=candle_type) else: convert_trades_format(config, convert_from=args['format_from'], convert_to=args['format_to'], erase=args['erase'])
def start_convert_trades(args: Dict[str, Any]) -> None: config = setup_utils_configuration(args, RunMode.UTIL_EXCHANGE) timerange = TimeRange() # Remove stake-currency to skip checks which are not relevant for datadownload config['stake_currency'] = '' if 'pairs' not in config: raise OperationalException( "Downloading data requires a list of pairs. " "Please check the documentation on how to configure this.") # Init exchange exchange = ExchangeResolver.load_exchange(config['exchange']['name'], config, validate=False) # Manual validations of relevant settings if not config['exchange'].get('skip_pair_validation', False): exchange.validate_pairs(config['pairs']) expanded_pairs = expand_pairlist(config['pairs'], list(exchange.markets)) logger.info(f"About to Convert pairs: {expanded_pairs}, " f"intervals: {config['timeframes']} to {config['datadir']}") for timeframe in config['timeframes']: exchange.validate_timeframes(timeframe) # Convert downloaded trade data to different timeframes convert_trades_to_ohlcv( pairs=expanded_pairs, timeframes=config['timeframes'], datadir=config['datadir'], timerange=timerange, erase=bool(config.get('erase')), data_format_ohlcv=config['dataformat_ohlcv'], data_format_trades=config['dataformat_trades'], )
def start_download_data(args: Dict[str, Any]) -> None: """ Download data (former download_backtest_data.py script) """ config = setup_utils_configuration(args, RunMode.UTIL_EXCHANGE) if 'days' in config and 'timerange' in config: raise OperationalException( "--days and --timerange are mutually exclusive. " "You can only specify one or the other.") timerange = TimeRange() if 'days' in config: time_since = (datetime.now() - timedelta(days=config['days'])).strftime("%Y%m%d") timerange = TimeRange.parse_timerange(f'{time_since}-') if 'timerange' in config: timerange = timerange.parse_timerange(config['timerange']) # Remove stake-currency to skip checks which are not relevant for datadownload config['stake_currency'] = '' if 'pairs' not in config: raise OperationalException( "Downloading data requires a list of pairs. " "Please check the documentation on how to configure this.") pairs_not_available: List[str] = [] # Init exchange exchange = ExchangeResolver.load_exchange(config['exchange']['name'], config, validate=False) markets = [ p for p, m in exchange.markets.items() if market_is_active(m) or config.get('include_inactive') ] expanded_pairs = expand_pairlist(config['pairs'], markets) # Manual validations of relevant settings if not config['exchange'].get('skip_pair_validation', False): exchange.validate_pairs(expanded_pairs) logger.info(f"About to download pairs: {expanded_pairs}, " f"intervals: {config['timeframes']} to {config['datadir']}") for timeframe in config['timeframes']: exchange.validate_timeframes(timeframe) try: if config.get('download_trades'): pairs_not_available = refresh_backtest_trades_data( exchange, pairs=expanded_pairs, datadir=config['datadir'], timerange=timerange, new_pairs_days=config['new_pairs_days'], erase=bool(config.get('erase')), data_format=config['dataformat_trades']) # Convert downloaded trade data to different timeframes convert_trades_to_ohlcv( pairs=expanded_pairs, timeframes=config['timeframes'], datadir=config['datadir'], timerange=timerange, erase=bool(config.get('erase')), data_format_ohlcv=config['dataformat_ohlcv'], data_format_trades=config['dataformat_trades'], ) else: pairs_not_available = refresh_backtest_ohlcv_data( exchange, pairs=expanded_pairs, timeframes=config['timeframes'], datadir=config['datadir'], timerange=timerange, new_pairs_days=config['new_pairs_days'], erase=bool(config.get('erase')), data_format=config['dataformat_ohlcv']) except KeyboardInterrupt: sys.exit("SIGINT received, aborting ...") finally: if pairs_not_available: logger.info( f"Pairs [{','.join(pairs_not_available)}] not available " f"on exchange {exchange.name}.")
def start_list_markets(args: Dict[str, Any], pairs_only: bool = False) -> None: """ Print pairs/markets on the exchange :param args: Cli args from Arguments() :param pairs_only: if True print only pairs, otherwise print all instruments (markets) :return: None """ config = setup_utils_configuration(args, RunMode.UTIL_EXCHANGE) # Init exchange exchange = ExchangeResolver.load_exchange(config['exchange']['name'], config, validate=False) # By default only active pairs/markets are to be shown active_only = not args.get('list_pairs_all', False) base_currencies = args.get('base_currencies', []) quote_currencies = args.get('quote_currencies', []) try: pairs = exchange.get_markets(base_currencies=base_currencies, quote_currencies=quote_currencies, pairs_only=pairs_only, active_only=active_only) # Sort the pairs/markets by symbol pairs = dict(sorted(pairs.items())) except Exception as e: raise OperationalException(f"Cannot get markets. Reason: {e}") from e else: summary_str = ( (f"Exchange {exchange.name} has {len(pairs)} ") + ("active " if active_only else "") + (plural(len(pairs), "pair" if pairs_only else "market")) + (f" with {', '.join(base_currencies)} as base " f"{plural(len(base_currencies), 'currency', 'currencies')}" if base_currencies else "") + (" and" if base_currencies and quote_currencies else "") + (f" with {', '.join(quote_currencies)} as quote " f"{plural(len(quote_currencies), 'currency', 'currencies')}" if quote_currencies else "")) headers = [ "Id", "Symbol", "Base", "Quote", "Active", *(['Is pair'] if not pairs_only else []) ] tabular_data = [] for _, v in pairs.items(): tabular_data.append({ 'Id': v['id'], 'Symbol': v['symbol'], 'Base': v['base'], 'Quote': v['quote'], 'Active': market_is_active(v), **({ 'Is pair': exchange.market_is_tradable(v) } if not pairs_only else {}) }) if (args.get('print_one_column', False) or args.get('list_pairs_print_json', False) or args.get('print_csv', False)): # Print summary string in the log in case of machine-readable # regular formats. logger.info(f"{summary_str}.") else: # Print empty string separating leading logs and output in case of # human-readable formats. print() if pairs: if args.get('print_list', False): # print data as a list, with human-readable summary print(f"{summary_str}: {', '.join(pairs.keys())}.") elif args.get('print_one_column', False): print('\n'.join(pairs.keys())) elif args.get('list_pairs_print_json', False): print(rapidjson.dumps(list(pairs.keys()), default=str)) elif args.get('print_csv', False): writer = csv.DictWriter(sys.stdout, fieldnames=headers) writer.writeheader() writer.writerows(tabular_data) else: # print data as a table, with the human-readable summary print(f"{summary_str}:") print( tabulate(tabular_data, headers='keys', tablefmt='psql', stralign='right')) elif not (args.get('print_one_column', False) or args.get('list_pairs_print_json', False) or args.get('print_csv', False)): print(f"{summary_str}.")