Merge pull request #2943 from Fredrik81/add-print-table
Added function to print hyperopt-list as table using tabulate
This commit is contained in:
		| @@ -46,18 +46,12 @@ def start_hyperopt_list(args: Dict[str, Any]) -> None: | |||||||
|  |  | ||||||
|     trials = _hyperopt_filter_trials(trials, filteroptions) |     trials = _hyperopt_filter_trials(trials, filteroptions) | ||||||
|  |  | ||||||
|     # TODO: fetch the interval for epochs to print from the cli option |  | ||||||
|     epoch_start, epoch_stop = 0, None |  | ||||||
|  |  | ||||||
|     if print_colorized: |     if print_colorized: | ||||||
|         colorama_init(autoreset=True) |         colorama_init(autoreset=True) | ||||||
|  |  | ||||||
|     try: |     try: | ||||||
|         # Human-friendly indexes used here (starting from 1) |         Hyperopt.print_result_table(config, trials, total_epochs, | ||||||
|         for val in trials[epoch_start:epoch_stop]: |  | ||||||
|             Hyperopt.print_results_explanation(val, total_epochs, |  | ||||||
|                                     not filteroptions['only_best'], print_colorized) |                                     not filteroptions['only_best'], print_colorized) | ||||||
|  |  | ||||||
|     except KeyboardInterrupt: |     except KeyboardInterrupt: | ||||||
|         print('User interrupted..') |         print('User interrupted..') | ||||||
|  |  | ||||||
| @@ -75,6 +69,12 @@ def start_hyperopt_show(args: Dict[str, Any]) -> None: | |||||||
|  |  | ||||||
|     config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) |     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 = { |     filteroptions = { | ||||||
|         'only_best': config.get('hyperopt_list_best', False), |         'only_best': config.get('hyperopt_list_best', False), | ||||||
|         'only_profitable': config.get('hyperopt_list_profitable', False), |         'only_profitable': config.get('hyperopt_list_profitable', False), | ||||||
| @@ -87,10 +87,6 @@ def start_hyperopt_show(args: Dict[str, Any]) -> None: | |||||||
|         'filter_min_total_profit': config.get('hyperopt_list_min_total_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_max_total_profit': config.get('hyperopt_list_max_total_profit', None) | ||||||
|     } |     } | ||||||
|     no_header = config.get('hyperopt_show_no_header', False) |  | ||||||
|  |  | ||||||
|     trials_file = (config['user_data_dir'] / |  | ||||||
|                    'hyperopt_results' / 'hyperopt_results.pickle') |  | ||||||
|  |  | ||||||
|     # Previous evaluations |     # Previous evaluations | ||||||
|     trials = Hyperopt.load_previous_results(trials_file) |     trials = Hyperopt.load_previous_results(trials_file) | ||||||
| @@ -99,7 +95,6 @@ def start_hyperopt_show(args: Dict[str, Any]) -> None: | |||||||
|     trials = _hyperopt_filter_trials(trials, filteroptions) |     trials = _hyperopt_filter_trials(trials, filteroptions) | ||||||
|     trials_epochs = len(trials) |     trials_epochs = len(trials) | ||||||
|  |  | ||||||
|     n = config.get('hyperopt_show_index', -1) |  | ||||||
|     if n > trials_epochs: |     if n > trials_epochs: | ||||||
|         raise OperationalException( |         raise OperationalException( | ||||||
|                 f"The index of the epoch to show should be less than {trials_epochs + 1}.") |                 f"The index of the epoch to show should be less than {trials_epochs + 1}.") | ||||||
| @@ -111,8 +106,6 @@ def start_hyperopt_show(args: Dict[str, Any]) -> None: | |||||||
|     if n > 0: |     if n > 0: | ||||||
|         n -= 1 |         n -= 1 | ||||||
|  |  | ||||||
|     print_json = config.get('print_json', False) |  | ||||||
|  |  | ||||||
|     if trials: |     if trials: | ||||||
|         val = trials[n] |         val = trials[n] | ||||||
|         Hyperopt.print_epoch_details(val, total_epochs, print_json, no_header, |         Hyperopt.print_epoch_details(val, total_epochs, print_json, no_header, | ||||||
|   | |||||||
| @@ -20,7 +20,8 @@ from colorama import Fore, Style | |||||||
| from colorama import init as colorama_init | from colorama import init as colorama_init | ||||||
| from joblib import (Parallel, cpu_count, delayed, dump, load, | from joblib import (Parallel, cpu_count, delayed, dump, load, | ||||||
|                     wrap_non_picklable_objects) |                     wrap_non_picklable_objects) | ||||||
| from pandas import DataFrame | from pandas import DataFrame, json_normalize, isna | ||||||
|  | from tabulate import tabulate | ||||||
|  |  | ||||||
| from freqtrade.data.converter import trim_dataframe | from freqtrade.data.converter import trim_dataframe | ||||||
| from freqtrade.data.history import get_timerange | from freqtrade.data.history import get_timerange | ||||||
| @@ -296,6 +297,56 @@ class Hyperopt: | |||||||
|                 f"{results['results_explanation']} " + |                 f"{results['results_explanation']} " + | ||||||
|                 f"Objective: {results['loss']:.5f}") |                 f"Objective: {results['loss']:.5f}") | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def print_result_table(config: dict, results: list, total_epochs: int, highlight_best: bool, | ||||||
|  |                            print_colorized: bool) -> None: | ||||||
|  |         """ | ||||||
|  |         Log result table | ||||||
|  |         """ | ||||||
|  |         if not results: | ||||||
|  |             return | ||||||
|  |  | ||||||
|  |         trials = json_normalize(results, max_level=1) | ||||||
|  |         trials['Best'] = '' | ||||||
|  |         trials = trials[['Best', 'current_epoch', 'results_metrics.trade_count', | ||||||
|  |                          'results_metrics.avg_profit', 'results_metrics.total_profit', | ||||||
|  |                          'results_metrics.profit', 'results_metrics.duration', | ||||||
|  |                          'loss', 'is_initial_point', 'is_best']] | ||||||
|  |         trials.columns = ['Best', 'Epoch', 'Trades', 'Avg profit', 'Total profit', | ||||||
|  |                           'Profit', 'Avg duration', 'Objective', 'is_initial_point', 'is_best'] | ||||||
|  |         trials['is_profit'] = False | ||||||
|  |         trials.loc[trials['is_initial_point'], 'Best'] = '*' | ||||||
|  |         trials.loc[trials['is_best'], 'Best'] = 'Best' | ||||||
|  |         trials['Objective'] = trials['Objective'].astype(str) | ||||||
|  |         trials.loc[trials['Total profit'] > 0, 'is_profit'] = True | ||||||
|  |         trials['Trades'] = trials['Trades'].astype(str) | ||||||
|  |  | ||||||
|  |         trials['Epoch'] = trials['Epoch'].apply( | ||||||
|  |             lambda x: "{}/{}".format(x, total_epochs)) | ||||||
|  |         trials['Avg profit'] = trials['Avg profit'].apply( | ||||||
|  |             lambda x: '{:,.2f}%'.format(x) if not isna(x) else x) | ||||||
|  |         trials['Profit'] = trials['Profit'].apply( | ||||||
|  |             lambda x: '{:,.2f}%'.format(x) if not isna(x) else x) | ||||||
|  |         trials['Total profit'] = trials['Total profit'].apply( | ||||||
|  |             lambda x: '{: 11.8f} '.format(x) + config['stake_currency'] if not isna(x) else x) | ||||||
|  |         trials['Avg duration'] = trials['Avg duration'].apply( | ||||||
|  |             lambda x: '{:,.1f}m'.format(x) if not isna(x) else x) | ||||||
|  |         if print_colorized: | ||||||
|  |             for i in range(len(trials)): | ||||||
|  |                 if trials.loc[i]['is_profit']: | ||||||
|  |                     for z in range(len(trials.loc[i])-3): | ||||||
|  |                         trials.iat[i, z] = "{}{}{}".format(Fore.GREEN, | ||||||
|  |                                                            str(trials.loc[i][z]), Fore.RESET) | ||||||
|  |                 if trials.loc[i]['is_best'] and highlight_best: | ||||||
|  |                     for z in range(len(trials.loc[i])-3): | ||||||
|  |                         trials.iat[i, z] = "{}{}{}".format(Style.BRIGHT, | ||||||
|  |                                                            str(trials.loc[i][z]), Style.RESET_ALL) | ||||||
|  |  | ||||||
|  |         trials = trials.drop(columns=['is_initial_point', 'is_best', 'is_profit']) | ||||||
|  |  | ||||||
|  |         print(tabulate(trials.to_dict(orient='list'), headers='keys', tablefmt='psql', | ||||||
|  |                        stralign="right")) | ||||||
|  |  | ||||||
|     def has_space(self, space: str) -> bool: |     def has_space(self, space: str) -> bool: | ||||||
|         """ |         """ | ||||||
|         Tell if the space value is contained in the configuration |         Tell if the space value is contained in the configuration | ||||||
|   | |||||||
| @@ -779,6 +779,20 @@ def test_hyperopt_list(mocker, capsys, hyperopt_results): | |||||||
|     assert all(x not in captured.out |     assert all(x not in captured.out | ||||||
|                for x in [" 1/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12", " 8/12", " 9/12", |                for x in [" 1/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12", " 8/12", " 9/12", | ||||||
|                          " 11/12", " 12/12"]) |                          " 11/12", " 12/12"]) | ||||||
|  |     args = [ | ||||||
|  |         "hyperopt-list", | ||||||
|  |         "--profitable" | ||||||
|  |     ] | ||||||
|  |     pargs = get_args(args) | ||||||
|  |     pargs['config'] = None | ||||||
|  |     start_hyperopt_list(pargs) | ||||||
|  |     captured = capsys.readouterr() | ||||||
|  |     assert all(x in captured.out | ||||||
|  |                for x in [" 2/12", " 10/12", "Best result:", "Buy hyperspace params", | ||||||
|  |                          "Sell hyperspace params", "ROI table", "Stoploss"]) | ||||||
|  |     assert all(x not in captured.out | ||||||
|  |                for x in [" 1/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12", " 8/12", " 9/12", | ||||||
|  |                          " 11/12", " 12/12"]) | ||||||
|     args = [ |     args = [ | ||||||
|         "hyperopt-list", |         "hyperopt-list", | ||||||
|         "--no-details", |         "--no-details", | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user