Merge branch 'develop' into interface_ordertimeoutcallback

This commit is contained in:
Matthias
2020-03-15 14:56:14 +01:00
101 changed files with 2205 additions and 1228 deletions

View File

@@ -69,7 +69,8 @@ ARGS_HYPEROPT_LIST = ["hyperopt_list_best", "hyperopt_list_profitable",
"hyperopt_list_min_avg_time", "hyperopt_list_max_avg_time",
"hyperopt_list_min_avg_profit", "hyperopt_list_max_avg_profit",
"hyperopt_list_min_total_profit", "hyperopt_list_max_total_profit",
"print_colorized", "print_json", "hyperopt_list_no_details"]
"print_colorized", "print_json", "hyperopt_list_no_details",
"export_csv"]
ARGS_HYPEROPT_SHOW = ["hyperopt_list_best", "hyperopt_list_profitable", "hyperopt_show_index",
"print_json", "hyperopt_show_no_header"]
@@ -296,7 +297,7 @@ class Arguments:
# Add convert-data subcommand
convert_data_cmd = subparsers.add_parser(
'convert-data',
help='Convert OHLCV data from one format to another.',
help='Convert candle (OHLCV) data from one format to another.',
parents=[_common_parser],
)
convert_data_cmd.set_defaults(func=partial(start_convert_data, ohlcv=True))
@@ -305,7 +306,7 @@ class Arguments:
# Add convert-trade-data subcommand
convert_trade_data_cmd = subparsers.add_parser(
'convert-trade-data',
help='Convert trade-data from one format to another.',
help='Convert trade data from one format to another.',
parents=[_common_parser],
)
convert_trade_data_cmd.set_defaults(func=partial(start_convert_data, ohlcv=False))

View File

@@ -76,7 +76,7 @@ def ask_user_config() -> Dict[str, Any]:
{
"type": "text",
"name": "ticker_interval",
"message": "Please insert your ticker interval:",
"message": "Please insert your timeframe (ticker interval):",
"default": "5m",
},
{

View File

@@ -221,6 +221,13 @@ AVAILABLE_CLI_OPTIONS = {
action='store_true',
default=False,
),
"export_csv": Arg(
'--export-csv',
help='Export to CSV-File.'
' This will disable table print.'
' Example: --export-csv hyperopt.csv',
metavar='FILE',
),
"hyperopt_jobs": Arg(
'-j', '--job-workers',
help='The number of concurrently running jobs for hyperoptimization '
@@ -257,7 +264,8 @@ AVAILABLE_CLI_OPTIONS = {
help='Specify the class name of the hyperopt loss function class (IHyperOptLoss). '
'Different functions can generate completely different results, '
'since the target for optimization is different. Built-in Hyperopt-loss-functions are: '
'DefaultHyperOptLoss, OnlyProfitHyperOptLoss, SharpeHyperOptLoss, SharpeHyperOptLossDaily.'
'DefaultHyperOptLoss, OnlyProfitHyperOptLoss, SharpeHyperOptLoss, SharpeHyperOptLossDaily, '
'SortinoHyperOptLoss, SortinoHyperOptLossDaily.'
'(default: `%(default)s`).',
metavar='NAME',
default=constants.DEFAULT_HYPEROPT_LOSS,
@@ -347,7 +355,7 @@ AVAILABLE_CLI_OPTIONS = {
),
"dataformat_ohlcv": Arg(
'--data-format-ohlcv',
help='Storage format for downloaded ohlcv data. (default: `%(default)s`).',
help='Storage format for downloaded candle (OHLCV) data. (default: `%(default)s`).',
choices=constants.AVAILABLE_DATAHANDLERS,
default='json'
),

View File

@@ -21,6 +21,7 @@ def start_hyperopt_list(args: Dict[str, Any]) -> None:
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
@@ -46,26 +47,26 @@ def start_hyperopt_list(args: Dict[str, Any]) -> None:
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:
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 filteroptions['only_best'], print_colorized)
except KeyboardInterrupt:
print('User interrupted..')
if not export_csv:
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)
if trials and export_csv:
Hyperopt.export_csv_file(
config, trials, total_epochs, not filteroptions['only_best'], export_csv
)
def start_hyperopt_show(args: Dict[str, Any]) -> None:
"""
@@ -75,6 +76,12 @@ def start_hyperopt_show(args: Dict[str, Any]) -> None:
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),
@@ -87,10 +94,6 @@ def start_hyperopt_show(args: Dict[str, Any]) -> 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)
}
no_header = config.get('hyperopt_show_no_header', False)
trials_file = (config['user_data_dir'] /
'hyperopt_results' / 'hyperopt_results.pickle')
# Previous evaluations
trials = Hyperopt.load_previous_results(trials_file)
@@ -99,20 +102,17 @@ def start_hyperopt_show(args: Dict[str, Any]) -> None:
trials = _hyperopt_filter_trials(trials, filteroptions)
trials_epochs = len(trials)
n = config.get('hyperopt_show_index', -1)
if n > trials_epochs:
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}.")
if n < -trials_epochs:
raise OperationalException(
f"The index of the epoch to show should be greater than {-trials_epochs - 1}.")
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
print_json = config.get('print_json', False)
if trials:
val = trials[n]
Hyperopt.print_epoch_details(val, total_epochs, print_json, no_header,
@@ -129,52 +129,52 @@ def _hyperopt_filter_trials(trials: List, filteroptions: dict) -> List:
trials = [x for x in trials if x['results_metrics']['profit'] > 0]
if filteroptions['filter_min_trades'] > 0:
trials = [
x for x in trials
if x['results_metrics']['trade_count'] > filteroptions['filter_min_trades']
]
x for x in trials
if x['results_metrics']['trade_count'] > filteroptions['filter_min_trades']
]
if filteroptions['filter_max_trades'] > 0:
trials = [
x for x in trials
if x['results_metrics']['trade_count'] < filteroptions['filter_max_trades']
]
x for x in trials
if x['results_metrics']['trade_count'] < filteroptions['filter_max_trades']
]
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']
]
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']
]
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']
]
x for x in trials
if x['results_metrics']['avg_profit']
> filteroptions['filter_min_avg_profit']
]
if filteroptions['filter_max_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_max_avg_profit']
]
x for x in trials
if x['results_metrics']['avg_profit']
< filteroptions['filter_max_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']
]
x for x in trials
if x['results_metrics']['profit'] > filteroptions['filter_min_total_profit']
]
if filteroptions['filter_max_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_max_total_profit']
]
x for x in trials
if x['results_metrics']['profit'] < filteroptions['filter_max_total_profit']
]
logger.info(f"{len(trials)} " +
("best " if filteroptions['only_best'] else "") +

View File

@@ -58,7 +58,7 @@ def _print_objs_tabular(objs: List, print_colorized: bool) -> None:
else yellow + "DUPLICATE NAME" + reset)
} for s in objs]
print(tabulate(objss_to_print, headers='keys', tablefmt='pipe'))
print(tabulate(objss_to_print, headers='keys', tablefmt='psql', stralign='right'))
def start_list_strategies(args: Dict[str, Any]) -> None:
@@ -192,7 +192,7 @@ def start_list_markets(args: Dict[str, Any], pairs_only: bool = False) -> None:
else:
# print data as a table, with the human-readable summary
print(f"{summary_str}:")
print(tabulate(tabular_data, headers='keys', tablefmt='pipe'))
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)):

View File

@@ -17,10 +17,15 @@ def setup_optimize_configuration(args: Dict[str, Any], method: RunMode) -> Dict[
"""
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)
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