Merge pull request #2888 from Fredrik81/hyperopt-filters
Added filter options to "hyperopt-list" in order to easier find epochs.
This commit is contained in:
commit
2bcce33f23
@ -413,17 +413,40 @@ You can list the hyperoptimization epochs the Hyperopt module evaluated previous
|
|||||||
```
|
```
|
||||||
usage: freqtrade hyperopt-list [-h] [-v] [--logfile FILE] [-V] [-c PATH]
|
usage: freqtrade hyperopt-list [-h] [-v] [--logfile FILE] [-V] [-c PATH]
|
||||||
[-d PATH] [--userdir PATH] [--best]
|
[-d PATH] [--userdir PATH] [--best]
|
||||||
[--profitable] [--no-color] [--print-json]
|
[--profitable] [--min-avg-time FLOAT]
|
||||||
[--no-details]
|
[--max-avg-time FLOAT] [--min-avg-profit FLOAT]
|
||||||
|
[--min-total-profit FLOAT] [--no-color]
|
||||||
|
[--print-json] [--no-details]
|
||||||
|
|
||||||
optional arguments:
|
optional arguments:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
--best Select only best epochs.
|
--best Select only best epochs.
|
||||||
--profitable Select only profitable epochs.
|
--profitable Select only profitable epochs.
|
||||||
|
--min-avg-time FLOAT Select epochs on above average time.
|
||||||
|
--max-avg-time FLOAT Select epochs on under average time.
|
||||||
|
--min-avg-profit FLOAT
|
||||||
|
Select epochs on above average profit.
|
||||||
|
--min-total-profit FLOAT
|
||||||
|
Select epochs on above total profit.
|
||||||
--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.
|
||||||
--no-details Do not print best epoch details.
|
--no-details Do not print best epoch details.
|
||||||
|
|
||||||
|
Common arguments:
|
||||||
|
-v, --verbose Verbose mode (-vv for more, -vvv to get all messages).
|
||||||
|
--logfile FILE Log to the file specified. Special values are:
|
||||||
|
'syslog', 'journald'. See the documentation for more
|
||||||
|
details.
|
||||||
|
-V, --version show program's version number and exit
|
||||||
|
-c PATH, --config PATH
|
||||||
|
Specify configuration file (default: `config.json`).
|
||||||
|
Multiple --config options may be used. Can be set to
|
||||||
|
`-` to read config from stdin.
|
||||||
|
-d PATH, --datadir PATH
|
||||||
|
Path to directory with historical backtesting data.
|
||||||
|
--userdir PATH, --user-data-dir PATH
|
||||||
|
Path to userdata directory.
|
||||||
```
|
```
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
@ -61,8 +61,10 @@ ARGS_PLOT_DATAFRAME = ["pairs", "indicators1", "indicators2", "plot_limit",
|
|||||||
ARGS_PLOT_PROFIT = ["pairs", "timerange", "export", "exportfilename", "db_url",
|
ARGS_PLOT_PROFIT = ["pairs", "timerange", "export", "exportfilename", "db_url",
|
||||||
"trade_source", "ticker_interval"]
|
"trade_source", "ticker_interval"]
|
||||||
|
|
||||||
ARGS_HYPEROPT_LIST = ["hyperopt_list_best", "hyperopt_list_profitable", "print_colorized",
|
ARGS_HYPEROPT_LIST = ["hyperopt_list_best", "hyperopt_list_profitable",
|
||||||
"print_json", "hyperopt_list_no_details"]
|
"hyperopt_list_min_avg_time", "hyperopt_list_max_avg_time",
|
||||||
|
"hyperopt_list_min_avg_profit", "hyperopt_list_min_total_profit",
|
||||||
|
"print_colorized", "print_json", "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"]
|
||||||
|
@ -398,6 +398,30 @@ AVAILABLE_CLI_OPTIONS = {
|
|||||||
help='Select only best epochs.',
|
help='Select only best epochs.',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
),
|
),
|
||||||
|
"hyperopt_list_min_avg_time": Arg(
|
||||||
|
'--min-avg-time',
|
||||||
|
help='Select epochs on above average time.',
|
||||||
|
type=float,
|
||||||
|
metavar='FLOAT',
|
||||||
|
),
|
||||||
|
"hyperopt_list_max_avg_time": Arg(
|
||||||
|
'--max-avg-time',
|
||||||
|
help='Select epochs on under average time.',
|
||||||
|
type=float,
|
||||||
|
metavar='FLOAT',
|
||||||
|
),
|
||||||
|
"hyperopt_list_min_avg_profit": Arg(
|
||||||
|
'--min-avg-profit',
|
||||||
|
help='Select epochs on above average profit.',
|
||||||
|
type=float,
|
||||||
|
metavar='FLOAT',
|
||||||
|
),
|
||||||
|
"hyperopt_list_min_total_profit": Arg(
|
||||||
|
'--min-total-profit',
|
||||||
|
help='Select epochs on above total profit.',
|
||||||
|
type=float,
|
||||||
|
metavar='FLOAT',
|
||||||
|
),
|
||||||
"hyperopt_list_no_details": Arg(
|
"hyperopt_list_no_details": Arg(
|
||||||
'--no-details',
|
'--no-details',
|
||||||
help='Do not print best epoch details.',
|
help='Do not print best epoch details.',
|
||||||
|
@ -19,13 +19,20 @@ def start_hyperopt_list(args: Dict[str, Any]) -> None:
|
|||||||
|
|
||||||
config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE)
|
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_colorized = config.get('print_colorized', False)
|
||||||
print_json = config.get('print_json', False)
|
print_json = config.get('print_json', 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
|
||||||
|
|
||||||
|
filteroptions = {
|
||||||
|
'only_best': config.get('hyperopt_list_best', False),
|
||||||
|
'only_profitable': config.get('hyperopt_list_profitable', False),
|
||||||
|
'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_min_total_profit': config.get('hyperopt_list_min_total_profit', None)
|
||||||
|
}
|
||||||
|
|
||||||
trials_file = (config['user_data_dir'] /
|
trials_file = (config['user_data_dir'] /
|
||||||
'hyperopt_results' / 'hyperopt_results.pickle')
|
'hyperopt_results' / 'hyperopt_results.pickle')
|
||||||
|
|
||||||
@ -33,7 +40,7 @@ def start_hyperopt_list(args: Dict[str, Any]) -> None:
|
|||||||
trials = Hyperopt.load_previous_results(trials_file)
|
trials = Hyperopt.load_previous_results(trials_file)
|
||||||
total_epochs = len(trials)
|
total_epochs = len(trials)
|
||||||
|
|
||||||
trials = _hyperopt_filter_trials(trials, only_best, only_profitable)
|
trials = _hyperopt_filter_trials(trials, filteroptions)
|
||||||
|
|
||||||
# TODO: fetch the interval for epochs to print from the cli option
|
# TODO: fetch the interval for epochs to print from the cli option
|
||||||
epoch_start, epoch_stop = 0, None
|
epoch_start, epoch_stop = 0, None
|
||||||
@ -44,7 +51,8 @@ def start_hyperopt_list(args: Dict[str, Any]) -> None:
|
|||||||
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, not only_best, print_colorized)
|
Hyperopt.print_results_explanation(val, total_epochs,
|
||||||
|
not filteroptions['only_best'], print_colorized)
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print('User interrupted..')
|
print('User interrupted..')
|
||||||
@ -63,8 +71,14 @@ 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)
|
||||||
|
|
||||||
only_best = config.get('hyperopt_list_best', False)
|
filteroptions = {
|
||||||
only_profitable = config.get('hyperopt_list_profitable', False)
|
'only_best': config.get('hyperopt_list_best', False),
|
||||||
|
'only_profitable': config.get('hyperopt_list_profitable', False),
|
||||||
|
'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_min_total_profit': config.get('hyperopt_list_min_total_profit', None)
|
||||||
|
}
|
||||||
no_header = config.get('hyperopt_show_no_header', False)
|
no_header = config.get('hyperopt_show_no_header', False)
|
||||||
|
|
||||||
trials_file = (config['user_data_dir'] /
|
trials_file = (config['user_data_dir'] /
|
||||||
@ -74,7 +88,7 @@ def start_hyperopt_show(args: Dict[str, Any]) -> None:
|
|||||||
trials = Hyperopt.load_previous_results(trials_file)
|
trials = Hyperopt.load_previous_results(trials_file)
|
||||||
total_epochs = len(trials)
|
total_epochs = len(trials)
|
||||||
|
|
||||||
trials = _hyperopt_filter_trials(trials, only_best, only_profitable)
|
trials = _hyperopt_filter_trials(trials, filteroptions)
|
||||||
trials_epochs = len(trials)
|
trials_epochs = len(trials)
|
||||||
|
|
||||||
n = config.get('hyperopt_show_index', -1)
|
n = config.get('hyperopt_show_index', -1)
|
||||||
@ -97,18 +111,43 @@ def start_hyperopt_show(args: Dict[str, Any]) -> None:
|
|||||||
header_str="Epoch details")
|
header_str="Epoch details")
|
||||||
|
|
||||||
|
|
||||||
def _hyperopt_filter_trials(trials: List, only_best: bool, only_profitable: bool) -> List:
|
def _hyperopt_filter_trials(trials: List, filteroptions: dict) -> List:
|
||||||
"""
|
"""
|
||||||
Filter our items from the list of hyperopt results
|
Filter our items from the list of hyperopt results
|
||||||
"""
|
"""
|
||||||
if only_best:
|
if filteroptions['only_best']:
|
||||||
trials = [x for x in trials if x['is_best']]
|
trials = [x for x in trials if x['is_best']]
|
||||||
if only_profitable:
|
if filteroptions['only_profitable']:
|
||||||
trials = [x for x in trials if x['results_metrics']['profit'] > 0]
|
trials = [x for x in trials if x['results_metrics']['profit'] > 0]
|
||||||
|
if filteroptions['filter_min_avg_time'] is not None:
|
||||||
|
trials = [x for x in trials if x['results_metrics']['trade_count'] > 0]
|
||||||
|
trials = [
|
||||||
|
x for x in trials
|
||||||
|
if x['results_metrics']['duration'] > filteroptions['filter_min_avg_time']
|
||||||
|
]
|
||||||
|
if filteroptions['filter_max_avg_time'] is not None:
|
||||||
|
trials = [x for x in trials if x['results_metrics']['trade_count'] > 0]
|
||||||
|
trials = [
|
||||||
|
x for x in trials
|
||||||
|
if x['results_metrics']['duration'] < filteroptions['filter_max_avg_time']
|
||||||
|
]
|
||||||
|
if filteroptions['filter_min_avg_profit'] is not None:
|
||||||
|
trials = [x for x in trials if x['results_metrics']['trade_count'] > 0]
|
||||||
|
trials = [
|
||||||
|
x for x in trials
|
||||||
|
if x['results_metrics']['avg_profit']
|
||||||
|
> filteroptions['filter_min_avg_profit']
|
||||||
|
]
|
||||||
|
if filteroptions['filter_min_total_profit'] is not None:
|
||||||
|
trials = [x for x in trials if x['results_metrics']['trade_count'] > 0]
|
||||||
|
trials = [
|
||||||
|
x for x in trials
|
||||||
|
if x['results_metrics']['profit'] > filteroptions['filter_min_total_profit']
|
||||||
|
]
|
||||||
|
|
||||||
logger.info(f"{len(trials)} " +
|
logger.info(f"{len(trials)} " +
|
||||||
("best " if only_best else "") +
|
("best " if filteroptions['only_best'] else "") +
|
||||||
("profitable " if only_profitable else "") +
|
("profitable " if filteroptions['only_profitable'] else "") +
|
||||||
"epochs found.")
|
"epochs found.")
|
||||||
|
|
||||||
return trials
|
return trials
|
||||||
|
@ -310,6 +310,18 @@ class Configuration:
|
|||||||
self._args_to_config(config, argname='hyperopt_list_profitable',
|
self._args_to_config(config, argname='hyperopt_list_profitable',
|
||||||
logstring='Parameter --profitable detected: {}')
|
logstring='Parameter --profitable detected: {}')
|
||||||
|
|
||||||
|
self._args_to_config(config, argname='hyperopt_list_min_avg_time',
|
||||||
|
logstring='Parameter --min-avg-time detected: {}')
|
||||||
|
|
||||||
|
self._args_to_config(config, argname='hyperopt_list_max_avg_time',
|
||||||
|
logstring='Parameter --max-avg-time detected: {}')
|
||||||
|
|
||||||
|
self._args_to_config(config, argname='hyperopt_list_min_avg_profit',
|
||||||
|
logstring='Parameter --min-avg-profit detected: {}')
|
||||||
|
|
||||||
|
self._args_to_config(config, argname='hyperopt_list_min_total_profit',
|
||||||
|
logstring='Parameter --min-total-profit detected: {}')
|
||||||
|
|
||||||
self._args_to_config(config, argname='hyperopt_list_no_details',
|
self._args_to_config(config, argname='hyperopt_list_no_details',
|
||||||
logstring='Parameter --no-details detected: {}')
|
logstring='Parameter --no-details detected: {}')
|
||||||
|
|
||||||
|
@ -778,6 +778,64 @@ 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",
|
||||||
|
"--no-details",
|
||||||
|
"--min-avg-profit", "0.11"
|
||||||
|
]
|
||||||
|
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"])
|
||||||
|
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",
|
||||||
|
" 10/12", " 11/12", " 12/12"])
|
||||||
|
args = [
|
||||||
|
"hyperopt-list",
|
||||||
|
"--no-details",
|
||||||
|
"--min-total-profit", "0.4"
|
||||||
|
]
|
||||||
|
pargs = get_args(args)
|
||||||
|
pargs['config'] = None
|
||||||
|
start_hyperopt_list(pargs)
|
||||||
|
captured = capsys.readouterr()
|
||||||
|
assert all(x in captured.out
|
||||||
|
for x in [" 10/12"])
|
||||||
|
assert all(x not in captured.out
|
||||||
|
for x in [" 1/12", " 2/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12", " 8/12",
|
||||||
|
" 9/12", " 11/12", " 12/12"])
|
||||||
|
args = [
|
||||||
|
"hyperopt-list",
|
||||||
|
"--profitable",
|
||||||
|
"--no-details",
|
||||||
|
"--min-avg-time", "2000"
|
||||||
|
]
|
||||||
|
pargs = get_args(args)
|
||||||
|
pargs['config'] = None
|
||||||
|
start_hyperopt_list(pargs)
|
||||||
|
captured = capsys.readouterr()
|
||||||
|
assert all(x in captured.out
|
||||||
|
for x in [" 10/12"])
|
||||||
|
assert all(x not in captured.out
|
||||||
|
for x in [" 1/12", " 2/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12",
|
||||||
|
" 8/12", " 9/12", " 11/12", " 12/12"])
|
||||||
|
args = [
|
||||||
|
"hyperopt-list",
|
||||||
|
"--no-details",
|
||||||
|
"--max-avg-time", "1500"
|
||||||
|
]
|
||||||
|
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", " 6/12"])
|
||||||
|
assert all(x not in captured.out
|
||||||
|
for x in [" 1/12", " 3/12", " 4/12", " 5/12", " 7/12", " 8/12"
|
||||||
|
" 9/12", " 10/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
Block a user