switch signal handler to try catch. fix pickling and formatting output

This commit is contained in:
Janne Sinivirta 2018-06-22 13:02:26 +03:00
parent 8272120c3a
commit a525cba8e9
1 changed files with 38 additions and 64 deletions

View File

@ -8,7 +8,6 @@ import json
import logging import logging
import os import os
import pickle import pickle
import signal
import sys import sys
import multiprocessing import multiprocessing
@ -18,9 +17,7 @@ from math import exp
from operator import itemgetter from operator import itemgetter
from typing import Dict, Any, Callable, Optional, List from typing import Dict, Any, Callable, Optional, List
import numpy
import talib.abstract as ta import talib.abstract as ta
from hyperopt import STATUS_FAIL, STATUS_OK, Trials, fmin, hp, space_eval, tpe
from pandas import DataFrame from pandas import DataFrame
from skopt.space import Real, Integer, Categorical, Dimension from skopt.space import Real, Integer, Categorical, Dimension
@ -64,9 +61,9 @@ class Hyperopt(Backtesting):
# Configuration and data used by hyperopt # Configuration and data used by hyperopt
self.processed: Optional[Dict[str, Any]] = None self.processed: Optional[Dict[str, Any]] = None
# Hyperopt Trials # Previous evaluations
self.trials_file = os.path.join('user_data', 'hyperopt_trials.pickle') self.trials_file = os.path.join('user_data', 'hyperopt_trials.pickle')
self.trials = Trials() self.trials = []
def get_args(self, params): def get_args(self, params):
dimensions = self.hyperopt_space() dimensions = self.hyperopt_space()
@ -104,10 +101,11 @@ class Hyperopt(Backtesting):
""" """
Save hyperopt trials to file Save hyperopt trials to file
""" """
logger.info('Saving Trials to \'%s\'', self.trials_file) if self.trials:
pickle.dump(self.trials, open(self.trials_file, 'wb')) logger.info('Saving %d evaluations to \'%s\'', len(self.trials), self.trials_file)
pickle.dump(self.trials, open(self.trials_file, 'wb'))
def read_trials(self) -> Trials: def read_trials(self) -> List:
""" """
Read hyperopt trials file Read hyperopt trials file
""" """
@ -120,9 +118,15 @@ class Hyperopt(Backtesting):
""" """
Display Best hyperopt result Display Best hyperopt result
""" """
vals = json.dumps(self.trials.best_trial['misc']['vals'], indent=4) results = sorted(self.trials, key=itemgetter('loss'))
results = self.trials.best_trial['result']['result'] best_result = results[0]
logger.info('Best result:\n%s\nwith values:\n%s', results, vals) logger.info(
'Best result:\n%s\nwith values:\n%s',
best_result['result'],
best_result['params']
)
if 'roi_t1' in best_result['params']:
logger.info('ROI table:\n%s', self.generate_roi_table(best_result['params']))
def log_results(self, results) -> None: def log_results(self, results) -> None:
""" """
@ -202,7 +206,6 @@ class Hyperopt(Backtesting):
Categorical([True, False], name='rsi-enabled'), Categorical([True, False], name='rsi-enabled'),
] ]
def has_space(self, space: str) -> bool: def has_space(self, space: str) -> bool:
""" """
Tell if a space value is contained in the configuration Tell if a space value is contained in the configuration
@ -251,7 +254,7 @@ class Hyperopt(Backtesting):
} }
#conditions.append(triggers.get(params['trigger']['type'])) #conditions.append(triggers.get(params['trigger']['type']))
conditions.append(dataframe['close'] < dataframe['bb_lowerband']) # single trigger conditions.append(dataframe['close'] < dataframe['bb_lowerband']) # single trigger
dataframe.loc[ dataframe.loc[
reduce(lambda x, y: x & y, conditions), reduce(lambda x, y: x & y, conditions),
@ -290,7 +293,7 @@ class Hyperopt(Backtesting):
return { return {
'loss': loss, 'loss': loss,
'status': STATUS_OK, 'params': params,
'result': result_explanation, 'result': result_explanation,
} }
@ -322,22 +325,15 @@ class Hyperopt(Backtesting):
self.analyze.populate_indicators = Hyperopt.populate_indicators # type: ignore self.analyze.populate_indicators = Hyperopt.populate_indicators # type: ignore
self.processed = self.tickerdata_to_dataframe(data) self.processed = self.tickerdata_to_dataframe(data)
logger.info('Preparing Trials..') logger.info('Preparing..')
signal.signal(signal.SIGINT, self.signal_handler)
# read trials file if we have one # read trials file if we have one
if os.path.exists(self.trials_file) and os.path.getsize(self.trials_file) > 0: if os.path.exists(self.trials_file) and os.path.getsize(self.trials_file) > 0:
self.trials = self.read_trials() self.trials = self.read_trials()
self.current_tries = len(self.trials.results)
self.total_tries += self.current_tries
logger.info( logger.info(
'Continuing with trials. Current: %d, Total: %d', 'Loaded %d previous evaluations from disk.',
self.current_tries, len(self.trials)
self.total_tries
) )
# results = sorted(self.trials.results, key=itemgetter('loss'))
# best_result = results[0]['result']
cpus = multiprocessing.cpu_count() cpus = multiprocessing.cpu_count()
print(f'Found {cpus}. Let\'s make them scream!') print(f'Found {cpus}. Let\'s make them scream!')
@ -349,50 +345,28 @@ class Hyperopt(Backtesting):
acq_optimizer_kwargs={'n_jobs': -1} acq_optimizer_kwargs={'n_jobs': -1}
) )
with Parallel(n_jobs=-1) as parallel: try:
for i in range(self.total_tries//cpus): with Parallel(n_jobs=-1) as parallel:
asked = opt.ask(n_points=cpus) for i in range(self.total_tries//cpus):
f_val = parallel(delayed(self.generate_optimizer)(v) for v in asked) asked = opt.ask(n_points=cpus)
opt.tell(asked, [i['loss'] for i in f_val]) f_val = parallel(delayed(self.generate_optimizer)(v) for v in asked)
opt.tell(asked, [i['loss'] for i in f_val])
for j in range(cpus): self.trials += f_val
self.log_results( for j in range(cpus):
{ self.log_results(
'loss': f_val[j]['loss'], {
'current_tries': i * cpus + j, 'loss': f_val[j]['loss'],
'total_tries': self.total_tries, 'current_tries': i * cpus + j,
'result': f_val[j]['result'], 'total_tries': self.total_tries,
} 'result': f_val[j]['result'],
) }
)
# Improve best parameter logging display except KeyboardInterrupt:
# if best_parameters: print('User interrupted..')
# best_parameters = space_eval(
# self.hyperopt_space(),
# best_parameters
# )
# logger.info('Best parameters:\n%s', json.dumps(best_parameters, indent=4))
# if 'roi_t1' in best_parameters:
# logger.info('ROI table:\n%s', self.generate_roi_table(best_parameters))
# logger.info('Best Result:\n%s', best_result)
# # Store trials result to file to resume next time
# self.save_trials()
def signal_handler(self, sig, frame) -> None:
"""
Hyperopt SIGINT handler
"""
logger.info(
'Hyperopt received %s',
signal.Signals(sig).name
)
self.save_trials() self.save_trials()
self.log_trials_result() self.log_trials_result()
sys.exit(0)
def start(args: Namespace) -> None: def start(args: Namespace) -> None: