From 349aa2f9574d04f7f20c9c04e6008767129a17e5 Mon Sep 17 00:00:00 2001 From: Fredrik81 Date: Fri, 28 Feb 2020 21:54:04 +0100 Subject: [PATCH 1/8] Added dynamic print table function to hyperopt --- freqtrade/commands/hyperopt_commands.py | 2 +- freqtrade/optimize/hyperopt.py | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/freqtrade/commands/hyperopt_commands.py b/freqtrade/commands/hyperopt_commands.py index ccaa59e54..72e5bf12f 100755 --- a/freqtrade/commands/hyperopt_commands.py +++ b/freqtrade/commands/hyperopt_commands.py @@ -51,7 +51,7 @@ def start_hyperopt_list(args: Dict[str, Any]) -> None: try: Hyperopt.print_result_table(config, trials, total_epochs, - not filteroptions['only_best'], print_colorized) + not filteroptions['only_best'], print_colorized, 0) except KeyboardInterrupt: print('User interrupted..') diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 66ea18bd1..84cd078a0 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -116,6 +116,7 @@ class Hyperopt: self.config['ask_strategy']['use_sell_signal'] = True self.print_all = self.config.get('print_all', False) + self.hyperopt_table_header = 0 self.print_colorized = self.config.get('print_colorized', False) self.print_json = self.config.get('print_json', False) @@ -272,8 +273,13 @@ class Hyperopt: if not self.print_all: # Separate the results explanation string from dots print("\n") - self.print_results_explanation(results, self.total_epochs, self.print_all, - self.print_colorized) + self.print_result_table(self.config, results, self.total_epochs, + self.print_all, self.print_colorized, + self.hyperopt_table_header) + if is_best: + self.hyperopt_table_header = 2 + else: + self.hyperopt_table_header = 3 @staticmethod def print_results_explanation(results, total_epochs, highlight_best: bool, @@ -299,7 +305,7 @@ class Hyperopt: @staticmethod def print_result_table(config: dict, results: list, total_epochs: int, highlight_best: bool, - print_colorized: bool) -> None: + print_colorized: bool, remove_header: int) -> None: """ Log result table """ @@ -328,7 +334,7 @@ class Hyperopt: 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) + lambda x: '{:,.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: @@ -343,9 +349,11 @@ class Hyperopt: 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")) + table = tabulate(trials.to_dict(orient='list'), tablefmt='psql', + headers='keys', stralign="right") + if remove_header > 0: + table = table.split("\n", remove_header)[remove_header] + print(table) def has_space(self, space: str) -> bool: """ From 23ae0653bd6a92ccdfc0a513dde1fa7f120ceb49 Mon Sep 17 00:00:00 2001 From: Fredrik81 Date: Sat, 29 Feb 2020 23:24:08 +0100 Subject: [PATCH 2/8] Changed table output to match hyperopt-list command --- freqtrade/optimize/hyperopt.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 84cd078a0..700614453 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -276,10 +276,7 @@ class Hyperopt: self.print_result_table(self.config, results, self.total_epochs, self.print_all, self.print_colorized, self.hyperopt_table_header) - if is_best: - self.hyperopt_table_header = 2 - else: - self.hyperopt_table_header = 3 + self.hyperopt_table_header = 2 @staticmethod def print_results_explanation(results, total_epochs, highlight_best: bool, @@ -349,10 +346,17 @@ class Hyperopt: str(trials.loc[i][z]), Style.RESET_ALL) trials = trials.drop(columns=['is_initial_point', 'is_best', 'is_profit']) - table = tabulate(trials.to_dict(orient='list'), tablefmt='psql', - headers='keys', stralign="right") if remove_header > 0: + table = tabulate(trials.to_dict(orient='list'), tablefmt='orgtbl', + headers='keys', stralign="right") table = table.split("\n", remove_header)[remove_header] + elif remove_header < 0: + table = tabulate(trials.to_dict(orient='list'), tablefmt='psql', + headers='keys', stralign="right") + table = "\n".join(table.split("\n")[0:remove_header]) + else: + table = tabulate(trials.to_dict(orient='list'), tablefmt='psql', + headers='keys', stralign="right") print(table) def has_space(self, space: str) -> bool: @@ -541,7 +545,7 @@ class Hyperopt: def start(self) -> None: self.random_state = self._set_random_state(self.config.get('hyperopt_random_state', None)) logger.info(f"Using optimizer random state: {self.random_state}") - + self.hyperopt_table_header = -1 data, timerange = self.backtesting.load_bt_data() preprocessed = self.backtesting.strategy.tickerdata_to_dataframe(data) From 267416ecedf34c4019cac403fe18f808c38a2b06 Mon Sep 17 00:00:00 2001 From: Fredrik81 Date: Sun, 1 Mar 2020 03:11:00 +0100 Subject: [PATCH 3/8] Changed test for new table printing --- tests/optimize/test_hyperopt.py | 129 +++++++++++++++++++++++++++----- 1 file changed, 109 insertions(+), 20 deletions(-) diff --git a/tests/optimize/test_hyperopt.py b/tests/optimize/test_hyperopt.py index e3212e0cd..0fa5b9536 100644 --- a/tests/optimize/test_hyperopt.py +++ b/tests/optimize/test_hyperopt.py @@ -390,17 +390,30 @@ def test_onlyprofit_loss_prefers_higher_profits(default_conf, hyperopt_results) def test_log_results_if_loss_improves(hyperopt, capsys) -> None: hyperopt.current_best_loss = 2 hyperopt.total_epochs = 2 + hyperopt.print_results( { - 'is_best': True, 'loss': 1, + 'results_metrics': + { + 'trade_count': 1, + 'avg_profit': 0.1, + 'total_profit': 0.001, + 'profit': 1.0, + 'duration': 20.0 + }, + 'total_profit': 0, 'current_epoch': 2, # This starts from 1 (in a human-friendly manner) - 'results_explanation': 'foo.', - 'is_initial_point': False + 'is_initial_point': False, + 'is_best': True } ) out, err = capsys.readouterr() - assert ' 2/2: foo. Objective: 1.00000' in out + result_str = ( + '| Best | 2/2 | 1 | 0.10% | 0.00100000 BTC |' + ' 1.00% | 20.0m | 1 |' + ) + assert result_str in out def test_no_log_if_loss_does_not_improve(hyperopt, caplog) -> None: @@ -467,7 +480,16 @@ def test_start_calls_optimizer(mocker, default_conf, caplog, capsys) -> None: parallel = mocker.patch( 'freqtrade.optimize.hyperopt.Hyperopt.run_optimizer_parallel', MagicMock(return_value=[{'loss': 1, 'results_explanation': 'foo result', - 'params': {'buy': {}, 'sell': {}, 'roi': {}, 'stoploss': 0.0}}]) + 'params': {'buy': {}, 'sell': {}, 'roi': {}, 'stoploss': 0.0}, + 'results_metrics': + { + 'trade_count': 1, + 'avg_profit': 0.1, + 'total_profit': 0.001, + 'profit': 1.0, + 'duration': 20.0 + }, + }]) ) patch_exchange(mocker) # Co-test loading ticker-interval from strategy @@ -761,11 +783,23 @@ def test_print_json_spaces_all(mocker, default_conf, caplog, capsys) -> None: parallel = mocker.patch( 'freqtrade.optimize.hyperopt.Hyperopt.run_optimizer_parallel', - MagicMock(return_value=[{'loss': 1, 'results_explanation': 'foo result', 'params': {}, - 'params_details': {'buy': {'mfi-value': None}, - 'sell': {'sell-mfi-value': None}, - 'roi': {}, 'stoploss': {'stoploss': None}, - 'trailing': {'trailing_stop': None}}}]) + MagicMock(return_value=[{ + 'loss': 1, 'results_explanation': 'foo result', 'params': {}, + 'params_details': { + 'buy': {'mfi-value': None}, + 'sell': {'sell-mfi-value': None}, + 'roi': {}, 'stoploss': {'stoploss': None}, + 'trailing': {'trailing_stop': None} + }, + 'results_metrics': + { + 'trade_count': 1, + 'avg_profit': 0.1, + 'total_profit': 0.001, + 'profit': 1.0, + 'duration': 20.0 + } + }]) ) patch_exchange(mocker) @@ -787,7 +821,11 @@ def test_print_json_spaces_all(mocker, default_conf, caplog, capsys) -> None: parallel.assert_called_once() out, err = capsys.readouterr() - assert '{"params":{"mfi-value":null,"sell-mfi-value":null},"minimal_roi":{},"stoploss":null,"trailing_stop":null}' in out # noqa: E501 + result_str = ( + '{"params":{"mfi-value":null,"sell-mfi-value":null},"minimal_roi"' + ':{},"stoploss":null,"trailing_stop":null}' + ) + assert result_str in out # noqa: E501 assert dumper.called # Should be called twice, once for tickerdata, once to save evaluations assert dumper.call_count == 2 @@ -804,10 +842,22 @@ def test_print_json_spaces_default(mocker, default_conf, caplog, capsys) -> None parallel = mocker.patch( 'freqtrade.optimize.hyperopt.Hyperopt.run_optimizer_parallel', - MagicMock(return_value=[{'loss': 1, 'results_explanation': 'foo result', 'params': {}, - 'params_details': {'buy': {'mfi-value': None}, - 'sell': {'sell-mfi-value': None}, - 'roi': {}, 'stoploss': {'stoploss': None}}}]) + MagicMock(return_value=[{ + 'loss': 1, 'results_explanation': 'foo result', 'params': {}, + 'params_details': { + 'buy': {'mfi-value': None}, + 'sell': {'sell-mfi-value': None}, + 'roi': {}, 'stoploss': {'stoploss': None} + }, + 'results_metrics': + { + 'trade_count': 1, + 'avg_profit': 0.1, + 'total_profit': 0.001, + 'profit': 1.0, + 'duration': 20.0 + } + }]) ) patch_exchange(mocker) @@ -846,8 +896,18 @@ def test_print_json_spaces_roi_stoploss(mocker, default_conf, caplog, capsys) -> parallel = mocker.patch( 'freqtrade.optimize.hyperopt.Hyperopt.run_optimizer_parallel', - MagicMock(return_value=[{'loss': 1, 'results_explanation': 'foo result', 'params': {}, - 'params_details': {'roi': {}, 'stoploss': {'stoploss': None}}}]) + MagicMock(return_value=[{ + 'loss': 1, 'results_explanation': 'foo result', 'params': {}, + 'params_details': {'roi': {}, 'stoploss': {'stoploss': None}}, + 'results_metrics': + { + 'trade_count': 1, + 'avg_profit': 0.1, + 'total_profit': 0.001, + 'profit': 1.0, + 'duration': 20.0 + } + }]) ) patch_exchange(mocker) @@ -887,7 +947,16 @@ def test_simplified_interface_roi_stoploss(mocker, default_conf, caplog, capsys) parallel = mocker.patch( 'freqtrade.optimize.hyperopt.Hyperopt.run_optimizer_parallel', MagicMock(return_value=[{ - 'loss': 1, 'results_explanation': 'foo result', 'params': {'stoploss': 0.0}}]) + 'loss': 1, 'results_explanation': 'foo result', 'params': {'stoploss': 0.0}, + 'results_metrics': + { + 'trade_count': 1, + 'avg_profit': 0.1, + 'total_profit': 0.001, + 'profit': 1.0, + 'duration': 20.0 + } + }]) ) patch_exchange(mocker) @@ -965,7 +1034,17 @@ def test_simplified_interface_buy(mocker, default_conf, caplog, capsys) -> None: parallel = mocker.patch( 'freqtrade.optimize.hyperopt.Hyperopt.run_optimizer_parallel', - MagicMock(return_value=[{'loss': 1, 'results_explanation': 'foo result', 'params': {}}]) + MagicMock(return_value=[{ + 'loss': 1, 'results_explanation': 'foo result', 'params': {}, + 'results_metrics': + { + 'trade_count': 1, + 'avg_profit': 0.1, + 'total_profit': 0.001, + 'profit': 1.0, + 'duration': 20.0 + } + }]) ) patch_exchange(mocker) @@ -1012,7 +1091,17 @@ def test_simplified_interface_sell(mocker, default_conf, caplog, capsys) -> None parallel = mocker.patch( 'freqtrade.optimize.hyperopt.Hyperopt.run_optimizer_parallel', - MagicMock(return_value=[{'loss': 1, 'results_explanation': 'foo result', 'params': {}}]) + MagicMock(return_value=[{ + 'loss': 1, 'results_explanation': 'foo result', 'params': {}, + 'results_metrics': + { + 'trade_count': 1, + 'avg_profit': 0.1, + 'total_profit': 0.001, + 'profit': 1.0, + 'duration': 20.0 + } + }]) ) patch_exchange(mocker) From 379275e2d6446f8f5950a61b0b233933c851f632 Mon Sep 17 00:00:00 2001 From: Fredrik81 Date: Sun, 1 Mar 2020 03:24:04 +0100 Subject: [PATCH 4/8] Updated tests --- tests/optimize/test_hyperopt.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/tests/optimize/test_hyperopt.py b/tests/optimize/test_hyperopt.py index 0fa5b9536..5bd9e542f 100644 --- a/tests/optimize/test_hyperopt.py +++ b/tests/optimize/test_hyperopt.py @@ -479,17 +479,18 @@ def test_start_calls_optimizer(mocker, default_conf, caplog, capsys) -> None: parallel = mocker.patch( 'freqtrade.optimize.hyperopt.Hyperopt.run_optimizer_parallel', - MagicMock(return_value=[{'loss': 1, 'results_explanation': 'foo result', - 'params': {'buy': {}, 'sell': {}, 'roi': {}, 'stoploss': 0.0}, - 'results_metrics': - { - 'trade_count': 1, - 'avg_profit': 0.1, - 'total_profit': 0.001, - 'profit': 1.0, - 'duration': 20.0 - }, - }]) + MagicMock(return_value=[{ + 'loss': 1, 'results_explanation': 'foo result', + 'params': {'buy': {}, 'sell': {}, 'roi': {}, 'stoploss': 0.0}, + 'results_metrics': + { + 'trade_count': 1, + 'avg_profit': 0.1, + 'total_profit': 0.001, + 'profit': 1.0, + 'duration': 20.0 + }, + }]) ) patch_exchange(mocker) # Co-test loading ticker-interval from strategy From 399c419163cd8acf867f16b9702b9936a1d05c7d Mon Sep 17 00:00:00 2001 From: Fredrik81 Date: Tue, 3 Mar 2020 01:14:56 +0100 Subject: [PATCH 5/8] Changed table formating. Adding some code to align hyperopt table generation. WIP --- freqtrade/optimize/hyperopt.py | 15 ++++++++++----- tests/optimize/test_hyperopt.py | 4 +++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 700614453..ac272128e 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -325,15 +325,20 @@ class Hyperopt: trials['Trades'] = trials['Trades'].astype(str) trials['Epoch'] = trials['Epoch'].apply( - lambda x: "{}/{}".format(x, total_epochs)) + lambda x: '{}/{}'.format(str(x).rjust(len(str(total_epochs)), ' '), total_epochs)) trials['Avg profit'] = trials['Avg profit'].apply( - lambda x: '{:,.2f}%'.format(x) if not isna(x) else x) + lambda x: ('{:,.2f}%'.format(x)).rjust(7, ' ') if not isna(x) else "--".rjust(7, ' ')) trials['Profit'] = trials['Profit'].apply( - lambda x: '{:,.2f}%'.format(x) if not isna(x) else x) + lambda x: ('{:,.2f}%'.format(x)) if not isna(x) else "--") trials['Total profit'] = trials['Total profit'].apply( - lambda x: '{:,.8f} '.format(x) + config['stake_currency'] if not isna(x) else x) + lambda x: ('{:,.8f} '.format(x)) + config['stake_currency'] if not isna(x) else "--") trials['Avg duration'] = trials['Avg duration'].apply( - lambda x: '{:,.1f}m'.format(x) if not isna(x) else x) + lambda x: ('{:,.1f}m'.format(x)).rjust(7, ' ') if not isna(x) else "--".rjust(7, ' ')) + trials['Objective'] = trials['Objective'].apply( + lambda x: str(x).rjust(10, ' ') if str(x) != str(100000) else "N/A".rjust(10, ' ')) + trials['Profit'] = trials['Total profit'] + " (" + trials['Profit'] + ")" + trials = trials.drop(columns=['Total profit']) + if print_colorized: for i in range(len(trials)): if trials.loc[i]['is_profit']: diff --git a/tests/optimize/test_hyperopt.py b/tests/optimize/test_hyperopt.py index 5bd9e542f..8de812d2d 100644 --- a/tests/optimize/test_hyperopt.py +++ b/tests/optimize/test_hyperopt.py @@ -413,7 +413,9 @@ def test_log_results_if_loss_improves(hyperopt, capsys) -> None: '| Best | 2/2 | 1 | 0.10% | 0.00100000 BTC |' ' 1.00% | 20.0m | 1 |' ) - assert result_str in out + # assert result_str in out + assert all(x in out + for x in ["Best", "2/2", " 1", "0.10%", "0.00100000 BTC", "1.00%", "20.0m"]) def test_no_log_if_loss_does_not_improve(hyperopt, caplog) -> None: From 4aca8d7fcc2e217652572325aa72a61a70d8ec98 Mon Sep 17 00:00:00 2001 From: Fredrik81 Date: Tue, 3 Mar 2020 01:35:18 +0100 Subject: [PATCH 6/8] PEP8 fix --- tests/optimize/test_hyperopt.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/optimize/test_hyperopt.py b/tests/optimize/test_hyperopt.py index 8de812d2d..6c7e1e16f 100644 --- a/tests/optimize/test_hyperopt.py +++ b/tests/optimize/test_hyperopt.py @@ -409,11 +409,6 @@ def test_log_results_if_loss_improves(hyperopt, capsys) -> None: } ) out, err = capsys.readouterr() - result_str = ( - '| Best | 2/2 | 1 | 0.10% | 0.00100000 BTC |' - ' 1.00% | 20.0m | 1 |' - ) - # assert result_str in out assert all(x in out for x in ["Best", "2/2", " 1", "0.10%", "0.00100000 BTC", "1.00%", "20.0m"]) From 7652a2bb95451ad907aec48ff4a8cc133901ae40 Mon Sep 17 00:00:00 2001 From: Fredrik81 Date: Wed, 4 Mar 2020 00:10:47 +0100 Subject: [PATCH 7/8] Updated table layout and aligning better for hyperopt --- freqtrade/optimize/hyperopt.py | 50 ++++++++++++++++++++------------- tests/optimize/test_hyperopt.py | 2 +- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index ac272128e..7937ad611 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -21,7 +21,7 @@ from colorama import init as colorama_init from joblib import (Parallel, cpu_count, delayed, dump, load, wrap_non_picklable_objects) from pandas import DataFrame, json_normalize, isna -from tabulate import tabulate +import tabulate from freqtrade.data.converter import trim_dataframe from freqtrade.data.history import get_timerange @@ -309,6 +309,8 @@ class Hyperopt: if not results: return + tabulate.PRESERVE_WHITESPACE = True + trials = json_normalize(results, max_level=1) trials['Best'] = '' trials = trials[['Best', 'current_epoch', 'results_metrics.trade_count', @@ -325,43 +327,51 @@ class Hyperopt: trials['Trades'] = trials['Trades'].astype(str) trials['Epoch'] = trials['Epoch'].apply( - lambda x: '{}/{}'.format(str(x).rjust(len(str(total_epochs)), ' '), total_epochs)) + lambda x: '{}/{}'.format(str(x).rjust(len(str(total_epochs)), ' '), total_epochs) + ) trials['Avg profit'] = trials['Avg profit'].apply( - lambda x: ('{:,.2f}%'.format(x)).rjust(7, ' ') if not isna(x) else "--".rjust(7, ' ')) - trials['Profit'] = trials['Profit'].apply( - lambda x: ('{:,.2f}%'.format(x)) if not isna(x) else "--") - trials['Total profit'] = trials['Total profit'].apply( - lambda x: ('{:,.8f} '.format(x)) + config['stake_currency'] if not isna(x) else "--") + lambda x: ('{:,.2f}%'.format(x)).rjust(7, ' ') if not isna(x) else "--".rjust(7, ' ') + ) trials['Avg duration'] = trials['Avg duration'].apply( - lambda x: ('{:,.1f}m'.format(x)).rjust(7, ' ') if not isna(x) else "--".rjust(7, ' ')) + lambda x: ('{:,.1f} m'.format(x)).rjust(7, ' ') if not isna(x) else "--".rjust(7, ' ') + ) trials['Objective'] = trials['Objective'].apply( - lambda x: str(x).rjust(10, ' ') if str(x) != str(100000) else "N/A".rjust(10, ' ')) - trials['Profit'] = trials['Total profit'] + " (" + trials['Profit'] + ")" + lambda x: str(x).rjust(10, ' ') if str(x) != str(100000) else "N/A".rjust(10, ' ') + ) + + trials['Profit'] = trials.apply( + lambda x: '{:,.8f} {} ({:,.2f}%)'.format( + x['Total profit'], config['stake_currency'], + x['Profit']).rjust(24+len(config['stake_currency'])) + if x['Total profit'] != 0.0 else '--'.rjust(24+len(config['stake_currency'])), + axis=1 + ) trials = trials.drop(columns=['Total profit']) 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) + 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.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']) if remove_header > 0: - table = tabulate(trials.to_dict(orient='list'), tablefmt='orgtbl', - headers='keys', stralign="right") + table = tabulate.tabulate( + trials.to_dict(orient='list'), tablefmt='orgtbl', headers='keys', stralign="right") + # print(table) table = table.split("\n", remove_header)[remove_header] elif remove_header < 0: - table = tabulate(trials.to_dict(orient='list'), tablefmt='psql', - headers='keys', stralign="right") + table = tabulate.tabulate( + trials.to_dict(orient='list'), tablefmt='psql', headers='keys', stralign="right") table = "\n".join(table.split("\n")[0:remove_header]) else: - table = tabulate(trials.to_dict(orient='list'), tablefmt='psql', - headers='keys', stralign="right") + table = tabulate.tabulate( + trials.to_dict(orient='list'), tablefmt='psql', headers='keys', stralign="right") print(table) def has_space(self, space: str) -> bool: diff --git a/tests/optimize/test_hyperopt.py b/tests/optimize/test_hyperopt.py index 6c7e1e16f..5820cc9f9 100644 --- a/tests/optimize/test_hyperopt.py +++ b/tests/optimize/test_hyperopt.py @@ -410,7 +410,7 @@ def test_log_results_if_loss_improves(hyperopt, capsys) -> None: ) out, err = capsys.readouterr() assert all(x in out - for x in ["Best", "2/2", " 1", "0.10%", "0.00100000 BTC", "1.00%", "20.0m"]) + for x in ["Best", "2/2", " 1", "0.10%", "0.00100000 BTC (1.00%)", "20.0 m"]) def test_no_log_if_loss_does_not_improve(hyperopt, caplog) -> None: From 090d1e8a709d9c0abcbd1cff667207f4e22d25dd Mon Sep 17 00:00:00 2001 From: Fredrik81 Date: Wed, 4 Mar 2020 20:51:09 +0100 Subject: [PATCH 8/8] Alignment and cleanups --- freqtrade/optimize/hyperopt.py | 38 +++++++++++++++++++-------------- tests/optimize/test_hyperopt.py | 4 +--- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 7937ad611..bc0a0d58f 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -154,7 +154,7 @@ class Hyperopt: """ num_trials = len(self.trials) if num_trials > self.num_trials_saved: - logger.info(f"Saving {num_trials} {plural(num_trials, 'epoch')}.") + logger.debug(f"Saving {num_trials} {plural(num_trials, 'epoch')}.") dump(self.trials, self.trials_file) self.num_trials_saved = num_trials if final: @@ -322,7 +322,6 @@ class Hyperopt: 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) @@ -336,14 +335,15 @@ class Hyperopt: lambda x: ('{:,.1f} m'.format(x)).rjust(7, ' ') if not isna(x) else "--".rjust(7, ' ') ) trials['Objective'] = trials['Objective'].apply( - lambda x: str(x).rjust(10, ' ') if str(x) != str(100000) else "N/A".rjust(10, ' ') + lambda x: '{:,.5f}'.format(x).rjust(8, ' ') if x != 100000 else "N/A".rjust(8, ' ') ) trials['Profit'] = trials.apply( - lambda x: '{:,.8f} {} ({:,.2f}%)'.format( + lambda x: '{:,.8f} {} {}'.format( x['Total profit'], config['stake_currency'], - x['Profit']).rjust(24+len(config['stake_currency'])) - if x['Total profit'] != 0.0 else '--'.rjust(24+len(config['stake_currency'])), + '({:,.2f}%)'.format(x['Profit']).rjust(10, ' ') + ).rjust(25+len(config['stake_currency'])) + if x['Total profit'] != 0.0 else '--'.rjust(25+len(config['stake_currency'])), axis=1 ) trials = trials.drop(columns=['Total profit']) @@ -351,27 +351,33 @@ class Hyperopt: 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) + for j in range(len(trials.loc[i])-3): + trials.iat[i, j] = "{}{}{}".format(Fore.GREEN, + str(trials.loc[i][j]), 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) + for j in range(len(trials.loc[i])-3): + trials.iat[i, j] = "{}{}{}".format(Style.BRIGHT, + str(trials.loc[i][j]), Style.RESET_ALL) trials = trials.drop(columns=['is_initial_point', 'is_best', 'is_profit']) if remove_header > 0: table = tabulate.tabulate( - trials.to_dict(orient='list'), tablefmt='orgtbl', headers='keys', stralign="right") - # print(table) + trials.to_dict(orient='list'), tablefmt='orgtbl', + headers='keys', stralign="right" + ) + table = table.split("\n", remove_header)[remove_header] elif remove_header < 0: table = tabulate.tabulate( - trials.to_dict(orient='list'), tablefmt='psql', headers='keys', stralign="right") + trials.to_dict(orient='list'), tablefmt='psql', + headers='keys', stralign="right" + ) table = "\n".join(table.split("\n")[0:remove_header]) else: table = tabulate.tabulate( - trials.to_dict(orient='list'), tablefmt='psql', headers='keys', stralign="right") + trials.to_dict(orient='list'), tablefmt='psql', + headers='keys', stralign="right" + ) print(table) def has_space(self, space: str) -> bool: diff --git a/tests/optimize/test_hyperopt.py b/tests/optimize/test_hyperopt.py index 5820cc9f9..0e35ff827 100644 --- a/tests/optimize/test_hyperopt.py +++ b/tests/optimize/test_hyperopt.py @@ -410,7 +410,7 @@ def test_log_results_if_loss_improves(hyperopt, capsys) -> None: ) out, err = capsys.readouterr() assert all(x in out - for x in ["Best", "2/2", " 1", "0.10%", "0.00100000 BTC (1.00%)", "20.0 m"]) + for x in ["Best", "2/2", " 1", "0.10%", "0.00100000 BTC (1.00%)", "20.0 m"]) def test_no_log_if_loss_does_not_improve(hyperopt, caplog) -> None: @@ -432,13 +432,11 @@ def test_save_trials_saves_trials(mocker, hyperopt, testdatadir, caplog) -> None hyperopt.trials = trials hyperopt.save_trials(final=True) - assert log_has("Saving 1 epoch.", caplog) assert log_has(f"1 epoch saved to '{trials_file}'.", caplog) mock_dump.assert_called_once() hyperopt.trials = trials + trials hyperopt.save_trials(final=True) - assert log_has("Saving 2 epochs.", caplog) assert log_has(f"2 epochs saved to '{trials_file}'.", caplog)