def error(msg: str) -> None: if jh.app_mode() not in LOGGERS: _init_main_logger() # error logs should be logged as info logs as well info(msg) msg = str(msg) from jesse.store import store log_id = jh.generate_unique_id() log_dict = { 'id': log_id, 'timestamp': jh.now_to_timestamp(), 'message': msg } if jh.is_live() and jh.get_config('env.notifications.events.errors', True): # notify_urgently(f"ERROR at \"{jh.get_config('env.identifier')}\" account:\n{msg}") notify_urgently(f"ERROR:\n{msg}") notify(f'ERROR:\n{msg}') if (jh.is_backtesting() and jh.is_debugging()) or jh.is_collecting_data() or jh.is_live(): sync_publish('error_log', log_dict) store.logs.errors.append(log_dict) if jh.is_live() or jh.is_optimizing(): msg = f"[ERROR | {jh.timestamp_to_time(jh.now_to_timestamp())[:19]}] {msg}" logger = LOGGERS[jh.app_mode()] logger.error(msg) if jh.is_live(): from jesse.models.utils import store_log_into_db store_log_into_db(log_dict, 'error')
def error(msg: str) -> None: msg = str(msg) from jesse.store import store if jh.is_live() and jh.get_config('env.notifications.events.errors', True): notify_urgently(f"ERROR at \"{jh.get_config('env.identifier')}\" account:\n{msg}") notify(f'ERROR:\n{msg}') if (jh.is_backtesting() and jh.is_debugging()) or jh.is_collecting_data(): print(jh.color(f'[{jh.timestamp_to_time(jh.now_to_timestamp())}]: {msg}', 'red')) store.logs.errors.append({'time': jh.now_to_timestamp(), 'message': msg}) if jh.is_live() or jh.is_optimizing(): msg = f"[ERROR | {jh.timestamp_to_time(jh.now_to_timestamp())[:19]}] {msg}" logging.error(msg)
def error(msg): from jesse.store import store if jh.is_live() and jh.get_config('env.notifications.events.errors', True): notify('ERROR:\n{}'.format(msg)) if (jh.is_backtesting() and jh.is_debugging()) or jh.is_collecting_data(): print( jh.color('[{}]: {}'.format(jh.timestamp_to_time(jh.now()), msg), 'red')) store.logs.errors.append({'time': jh.now(), 'message': msg}) if jh.is_live() or jh.is_optimizing(): msg = '[ERROR | {}] '.format(jh.timestamp_to_time( jh.now())[:19]) + str(msg) import logging logging.error(msg)
def set_config(conf: dict) -> None: global config # optimization mode only if jh.is_optimizing(): # ratio config['env']['optimization']['ratio'] = conf['ratio'] # exchange info (only one because the optimize mode supports only one trading route at the moment) config['env']['optimization']['exchange'] = conf['exchange'] # warm_up_candles config['env']['optimization']['warmup_candles_num'] = int(conf['warm_up_candles']) # backtest and live if jh.is_backtesting() or jh.is_live(): # warm_up_candles config['env']['data']['warmup_candles_num'] = int(conf['warm_up_candles']) # logs config['env']['logging'] = conf['logging'] # exchanges for key, e in conf['exchanges'].items(): config['env']['exchanges'][e['name']] = { 'fee': float(e['fee']), 'type': 'futures', # used only in futures trading # 'settlement_currency': 'USDT', 'settlement_currency': jh.get_settlement_currency_from_exchange(e['name']), # accepted values are: 'cross' and 'isolated' 'futures_leverage_mode': e['futures_leverage_mode'], # 1x, 2x, 10x, 50x, etc. Enter as integers 'futures_leverage': int(e['futures_leverage']), 'assets': [ {'asset': 'USDT', 'balance': float(e['balance'])}, ], } # live mode only if jh.is_live(): config['env']['notifications'] = conf['notifications'] # TODO: must become a config value later when we go after multi account support? config['env']['identifier'] = 'main'
def _init_main_logger(): session_id = jh.get_session_id() jh.make_directory('storage/logs/live-mode') jh.make_directory('storage/logs/backtest-mode') jh.make_directory('storage/logs/optimize-mode') jh.make_directory('storage/logs/collect-mode') if jh.is_live(): filename = f'storage/logs/live-mode/{session_id}.txt' elif jh.is_collecting_data(): filename = f'storage/logs/collect-mode/{session_id}.txt' elif jh.is_optimizing(): filename = f'storage/logs/optimize-mode/{session_id}.txt' elif jh.is_backtesting(): filename = f'storage/logs/backtest-mode/{session_id}.txt' else: filename = 'storage/logs/etc.txt' new_logger = logging.getLogger(jh.app_mode()) new_logger.setLevel(logging.INFO) new_logger.addHandler(logging.FileHandler(filename, mode='w')) LOGGERS[jh.app_mode()] = new_logger
def test_is_optimizing(): assert jh.is_optimizing() is False
def register_custom_exception_handler() -> None: import sys import threading import traceback import logging from jesse.services import logger as jesse_logger import click from jesse import exceptions log_format = "%(message)s" os.makedirs('./storage/logs', exist_ok=True) if jh.is_livetrading(): logging.basicConfig(filename='storage/logs/live-trade.txt', level=logging.INFO, filemode='w', format=log_format) elif jh.is_paper_trading(): logging.basicConfig(filename='storage/logs/paper-trade.txt', level=logging.INFO, filemode='w', format=log_format) elif jh.is_collecting_data(): logging.basicConfig(filename='storage/logs/collect.txt', level=logging.INFO, filemode='w', format=log_format) elif jh.is_optimizing(): logging.basicConfig(filename='storage/logs/optimize.txt', level=logging.INFO, filemode='w', format=log_format) else: logging.basicConfig(level=logging.INFO) # main thread def handle_exception(exc_type, exc_value, exc_traceback) -> None: if issubclass(exc_type, KeyboardInterrupt): sys.excepthook(exc_type, exc_value, exc_traceback) return # handle Breaking exceptions if exc_type in [ exceptions.InvalidConfig, exceptions.RouteNotFound, exceptions.InvalidRoutes, exceptions.CandleNotFoundInDatabase ]: click.clear() print(f"{'=' * 30} EXCEPTION TRACEBACK:") traceback.print_tb(exc_traceback, file=sys.stdout) print("=" * 73) print('\n', jh.color('Uncaught Exception:', 'red'), jh.color(f'{exc_type.__name__}: {exc_value}', 'yellow')) return # send notifications if it's a live session if jh.is_live(): jesse_logger.error(f'{exc_type.__name__}: {exc_value}') if jh.is_live() or jh.is_collecting_data(): logging.error("Uncaught Exception:", exc_info=(exc_type, exc_value, exc_traceback)) else: print(f"{'=' * 30} EXCEPTION TRACEBACK:") traceback.print_tb(exc_traceback, file=sys.stdout) print("=" * 73) print('\n', jh.color('Uncaught Exception:', 'red'), jh.color(f'{exc_type.__name__}: {exc_value}', 'yellow')) if jh.is_paper_trading(): print( jh.color( 'An uncaught exception was raised. Check the log file at:\nstorage/logs/paper-trade.txt', 'red')) elif jh.is_livetrading(): print( jh.color( 'An uncaught exception was raised. Check the log file at:\nstorage/logs/live-trade.txt', 'red')) elif jh.is_collecting_data(): print( jh.color( 'An uncaught exception was raised. Check the log file at:\nstorage/logs/collect.txt', 'red')) sys.excepthook = handle_exception # other threads if jh.python_version() >= (3, 8): def handle_thread_exception(args) -> None: if args.exc_type == SystemExit: return # handle Breaking exceptions if args.exc_type in [ exceptions.InvalidConfig, exceptions.RouteNotFound, exceptions.InvalidRoutes, exceptions.CandleNotFoundInDatabase ]: click.clear() print(f"{'=' * 30} EXCEPTION TRACEBACK:") traceback.print_tb(args.exc_traceback, file=sys.stdout) print("=" * 73) print( '\n', jh.color('Uncaught Exception:', 'red'), jh.color(f'{args.exc_type.__name__}: {args.exc_value}', 'yellow')) return # send notifications if it's a live session if jh.is_live(): jesse_logger.error( f'{args.exc_type.__name__}: { args.exc_value}') if jh.is_live() or jh.is_collecting_data(): logging.error("Uncaught Exception:", exc_info=(args.exc_type, args.exc_value, args.exc_traceback)) else: print(f"{'=' * 30} EXCEPTION TRACEBACK:") traceback.print_tb(args.exc_traceback, file=sys.stdout) print("=" * 73) print( '\n', jh.color('Uncaught Exception:', 'red'), jh.color(f'{args.exc_type.__name__}: {args.exc_value}', 'yellow')) if jh.is_paper_trading(): print( jh.color( 'An uncaught exception was raised. Check the log file at:\nstorage/logs/paper-trade.txt', 'red')) elif jh.is_livetrading(): print( jh.color( 'An uncaught exception was raised. Check the log file at:\nstorage/logs/live-trade.txt', 'red')) elif jh.is_collecting_data(): print( jh.color( 'An uncaught exception was raised. Check the log file at:\nstorage/logs/collect.txt', 'red')) threading.excepthook = handle_thread_exception