Added function to print hyperopt-list as table using tabulate
This commit is contained in:
parent
9a22ce69bd
commit
2058b492eb
|
@ -440,6 +440,7 @@ optional arguments:
|
||||||
--no-color Disable colorization of hyperopt results. May be
|
--no-color Disable colorization of hyperopt results. May be
|
||||||
useful if you are redirecting output to a file.
|
useful if you are redirecting output to a file.
|
||||||
--print-json Print best result detailization in JSON format.
|
--print-json Print best result detailization in JSON format.
|
||||||
|
--print-table Print results in table format.
|
||||||
--no-details Do not print best epoch details.
|
--no-details Do not print best epoch details.
|
||||||
|
|
||||||
Common arguments:
|
Common arguments:
|
||||||
|
|
|
@ -66,7 +66,8 @@ ARGS_HYPEROPT_LIST = ["hyperopt_list_best", "hyperopt_list_profitable",
|
||||||
"hyperopt_list_min_avg_time", "hyperopt_list_max_avg_time",
|
"hyperopt_list_min_avg_time", "hyperopt_list_max_avg_time",
|
||||||
"hyperopt_list_min_avg_profit", "hyperopt_list_max_avg_profit",
|
"hyperopt_list_min_avg_profit", "hyperopt_list_max_avg_profit",
|
||||||
"hyperopt_list_min_total_profit", "hyperopt_list_max_total_profit",
|
"hyperopt_list_min_total_profit", "hyperopt_list_max_total_profit",
|
||||||
"print_colorized", "print_json", "hyperopt_list_no_details"]
|
"print_colorized", "print_json", "print_table",
|
||||||
|
"hyperopt_list_no_details"]
|
||||||
|
|
||||||
ARGS_HYPEROPT_SHOW = ["hyperopt_list_best", "hyperopt_list_profitable", "hyperopt_show_index",
|
ARGS_HYPEROPT_SHOW = ["hyperopt_list_best", "hyperopt_list_profitable", "hyperopt_show_index",
|
||||||
"print_json", "hyperopt_show_no_header"]
|
"print_json", "hyperopt_show_no_header"]
|
||||||
|
|
|
@ -220,6 +220,12 @@ AVAILABLE_CLI_OPTIONS = {
|
||||||
action='store_true',
|
action='store_true',
|
||||||
default=False,
|
default=False,
|
||||||
),
|
),
|
||||||
|
"print_table": Arg(
|
||||||
|
'--print-table',
|
||||||
|
help='Print results in table format.',
|
||||||
|
action='store_true',
|
||||||
|
default=False,
|
||||||
|
),
|
||||||
"hyperopt_jobs": Arg(
|
"hyperopt_jobs": Arg(
|
||||||
'-j', '--job-workers',
|
'-j', '--job-workers',
|
||||||
help='The number of concurrently running jobs for hyperoptimization '
|
help='The number of concurrently running jobs for hyperoptimization '
|
||||||
|
|
|
@ -21,6 +21,7 @@ def start_hyperopt_list(args: Dict[str, Any]) -> None:
|
||||||
|
|
||||||
print_colorized = config.get('print_colorized', False)
|
print_colorized = config.get('print_colorized', False)
|
||||||
print_json = config.get('print_json', False)
|
print_json = config.get('print_json', False)
|
||||||
|
print_table = config.get('print_table', False)
|
||||||
no_details = config.get('hyperopt_list_no_details', False)
|
no_details = config.get('hyperopt_list_no_details', False)
|
||||||
no_header = False
|
no_header = False
|
||||||
|
|
||||||
|
@ -52,12 +53,18 @@ def start_hyperopt_list(args: Dict[str, Any]) -> None:
|
||||||
if print_colorized:
|
if print_colorized:
|
||||||
colorama_init(autoreset=True)
|
colorama_init(autoreset=True)
|
||||||
|
|
||||||
|
if print_table:
|
||||||
|
try:
|
||||||
|
Hyperopt.print_result_table(config, trials, total_epochs,
|
||||||
|
not filteroptions['only_best'], print_colorized)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print('User interrupted..')
|
||||||
|
else:
|
||||||
try:
|
try:
|
||||||
# Human-friendly indexes used here (starting from 1)
|
# Human-friendly indexes used here (starting from 1)
|
||||||
for val in trials[epoch_start:epoch_stop]:
|
for val in trials[epoch_start:epoch_stop]:
|
||||||
Hyperopt.print_results_explanation(val, total_epochs,
|
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 +82,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 +100,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 +108,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 +119,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,
|
||||||
|
|
|
@ -286,6 +286,9 @@ class Configuration:
|
||||||
self._args_to_config(config, argname='print_json',
|
self._args_to_config(config, argname='print_json',
|
||||||
logstring='Parameter --print-json detected ...')
|
logstring='Parameter --print-json detected ...')
|
||||||
|
|
||||||
|
self._args_to_config(config, argname='print_table',
|
||||||
|
logstring='Parameter --print-table detected: {}')
|
||||||
|
|
||||||
self._args_to_config(config, argname='hyperopt_jobs',
|
self._args_to_config(config, argname='hyperopt_jobs',
|
||||||
logstring='Parameter -j/--job-workers detected: {}')
|
logstring='Parameter -j/--job-workers detected: {}')
|
||||||
|
|
||||||
|
|
|
@ -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.history import get_timerange, trim_dataframe
|
from freqtrade.data.history import get_timerange, trim_dataframe
|
||||||
from freqtrade.exceptions import OperationalException
|
from freqtrade.exceptions import OperationalException
|
||||||
|
@ -295,6 +296,50 @@ 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 = trials[['is_best', 'current_epoch',
|
||||||
|
'results_metrics.trade_count', 'results_metrics.avg_profit',
|
||||||
|
'results_metrics.total_profit', 'results_metrics.profit',
|
||||||
|
'results_metrics.duration', 'loss']]
|
||||||
|
trials.columns = ['Best', 'Epoch', 'Trades', 'Avg profit', 'Total profit',
|
||||||
|
'Profit', 'Avg duration', 'Objective']
|
||||||
|
|
||||||
|
trials['Best'] = trials['Best'].apply(lambda x: '*' if x else '')
|
||||||
|
trials['Objective'] = trials['Objective'].astype(str)
|
||||||
|
|
||||||
|
if print_colorized:
|
||||||
|
for i in range(len(trials)):
|
||||||
|
if trials.loc[i]['Total profit'] > 0:
|
||||||
|
trials.at[i, 'Best'] = Fore.GREEN + trials.loc[i]['Best']
|
||||||
|
trials.at[i, 'Objective'] = "{}{}".format(trials.loc[i]['Objective'],
|
||||||
|
Fore.RESET)
|
||||||
|
if '*' in trials.loc[i]['Best'] and highlight_best:
|
||||||
|
trials.at[i, 'Best'] = Style.BRIGHT + trials.loc[i]['Best']
|
||||||
|
trials.at[i, 'Objective'] = "{}{}".format(trials.loc[i]['Objective'],
|
||||||
|
Style.RESET_ALL)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
print(tabulate(trials.to_dict(orient='list'), headers='keys', tablefmt='psql'))
|
||||||
|
|
||||||
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
|
||||||
|
|
|
@ -893,6 +893,22 @@ 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", " 7/12", " 8/12"
|
for x in [" 1/12", " 3/12", " 4/12", " 5/12", " 7/12", " 8/12"
|
||||||
" 9/12", " 10/12", " 11/12", " 12/12"])
|
" 9/12", " 10/12", " 11/12", " 12/12"])
|
||||||
|
args = [
|
||||||
|
"hyperopt-list",
|
||||||
|
"--profitable",
|
||||||
|
"--no-details",
|
||||||
|
"--print-table",
|
||||||
|
"--max-trades", "20"
|
||||||
|
]
|
||||||
|
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"])
|
||||||
|
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"])
|
||||||
|
|
||||||
|
|
||||||
def test_hyperopt_show(mocker, capsys, hyperopt_results):
|
def test_hyperopt_show(mocker, capsys, hyperopt_results):
|
||||||
|
|
Loading…
Reference in New Issue