def add_candle(self, candle: np.ndarray, exchange: str, symbol: str, timeframe: str, with_execution: bool = True, with_generation: bool = True) -> None: if jh.is_collecting_data(): # make sure it's a complete (and not a forming) candle if jh.now_to_timestamp() >= (candle[0] + 60000): store_candle_into_db(exchange, symbol, candle) return arr: DynamicNumpyArray = self.get_storage(exchange, symbol, timeframe) if jh.is_live(): self.update_position(exchange, symbol, candle) # ignore new candle at the time of execution because it messes # the count of candles without actually having an impact if candle[0] >= jh.now(): return # initial if len(arr) == 0: arr.append(candle) # if it's new, add elif candle[0] > arr[-1][0]: # in paper mode, check to see if the new candle causes any active orders to be executed if with_execution and jh.is_paper_trading(): self.simulate_order_execution(exchange, symbol, timeframe, candle) arr.append(candle) # generate other timeframes if with_generation and timeframe == '1m': self.generate_bigger_timeframes(candle, exchange, symbol, with_execution) # if it's the last candle again, update elif candle[0] == arr[-1][0]: # in paper mode, check to see if the new candle causes any active orders to get executed if with_execution and jh.is_paper_trading(): self.simulate_order_execution(exchange, symbol, timeframe, candle) arr[-1] = candle # regenerate other timeframes if with_generation and timeframe == '1m': self.generate_bigger_timeframes(candle, exchange, symbol, with_execution) # past candles will be ignored (dropped) elif candle[0] < arr[-1][0]: return
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' ) )
def handle_thread_exception(args): """ :param args: :return: """ if args.exc_type == SystemExit: return # handle Breaking exceptions if args.exc_type in [ exceptions.ConfigException, exceptions.RouteNotFound, exceptions.InvalidRoutes, exceptions.CandleNotFoundInDatabase ]: click.clear() print('=' * 30 + ' EXCEPTION TRACEBACK:') traceback.print_tb(args.exc_traceback, file=sys.stdout) print("=" * 73) print( '\n', jh.color('Uncaught Exception:', 'red'), jh.color( '{}: {}'.format(args.exc_type.__name__, args.exc_value), 'yellow')) return # send notifications if it's a live session if jh.is_live(): jesse_logger.error('{}: {}'.format(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('=' * 30 + ' EXCEPTION TRACEBACK:') traceback.print_tb(args.exc_traceback, file=sys.stdout) print("=" * 73) print( '\n', jh.color('Uncaught Exception:', 'red'), jh.color( '{}: {}'.format(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:\n{}' .format('storage/logs/paper-trade.txt'), 'red')) elif jh.is_livetrading(): print( jh.color( 'An uncaught exception was raised. Check the log file at:\n{}' .format('storage/logs/live-trade.txt'), 'red')) elif jh.is_collecting_data(): print( jh.color( 'An uncaught exception was raised. Check the log file at:\n{}' .format('storage/logs/collect.txt'), 'red'))
def livetrade(): # TODO: for now, we assume that we trade on one exchange only. Later, we need to support for more than one exchange at a time # sum up balance of all trading exchanges starting_balance = 0 current_balance = 0 for e in store.exchanges.storage: starting_balance += store.exchanges.storage[e].starting_assets[ jh.app_currency()] current_balance += store.exchanges.storage[e].assets[jh.app_currency()] starting_balance = round(starting_balance, 2) current_balance = round(current_balance, 2) # short trades summary if len(store.completed_trades.trades): df = pd.DataFrame.from_records( [t.to_dict() for t in store.completed_trades.trades]) total = len(df) winning_trades = len(df.loc[df['PNL'] > 0]) losing_trades = len(df.loc[df['PNL'] < 0]) pnl = round(df['PNL'].sum(), 2) pnl_perc = round((pnl / starting_balance) * 100, 2) else: pnl, pnl_perc, total, winning_trades, losing_trades = 0, 0, 0, 0, 0 routes = [{ 'exchange': r.exchange, 'symbol': r.symbol, 'timeframe': r.timeframe, 'strategy': r.strategy_name } for r in router.routes] return { 'session_id': store.app.session_id, 'started_at': str(store.app.starting_time), 'current_time': str(jh.now_to_timestamp()), 'started_balance': str(starting_balance), 'current_balance': str(current_balance), 'debug_mode': str(config['app']['debug_mode']), 'paper_mode': str(jh.is_paper_trading()), 'count_error_logs': str(len(store.logs.errors)), 'count_info_logs': str(len(store.logs.info)), 'count_active_orders': str(store.orders.count_all_active_orders()), 'open_positions': str(store.positions.count_open_positions()), 'pnl': str(pnl), 'pnl_perc': str(pnl_perc), 'count_trades': str(total), 'count_winning_trades': str(winning_trades), 'count_losing_trades': str(losing_trades), 'routes': routes }
def test_is_paper_trading(): assert jh.is_paper_trading() 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
def add_candle(self, candle: np.ndarray, exchange: str, symbol: str, timeframe: str, with_execution=True, with_generation=True, is_forming_candle=False): """ :param candle: :param exchange: :param symbol: :param timeframe: :param with_execution: :param with_generation: :param is_forming_candle: :return: """ if jh.is_collecting_data(): # make sure it's a complete (and not a forming) candle if jh.now() >= (candle[0] + 60000): store_candle_into_db(exchange, symbol, candle) return arr: DynamicNumpyArray = self.get_storage(exchange, symbol, timeframe) if jh.is_live(): self.update_position(exchange, symbol, candle) # initial if len(arr) == 0: arr.append(candle) # if it's new, add elif candle[0] > arr[-1][0]: # in paper mode, check to see if the new candle causes any active orders to be executed if with_execution and jh.is_paper_trading(): self.simulate_order_execution(exchange, symbol, timeframe, candle) arr.append(candle) # generate other timeframes if with_generation and timeframe == '1m': self.generate_bigger_timeframes(candle, exchange, symbol, with_execution, is_forming_candle) # if it's the last candle again, update elif candle[0] == arr[-1][0]: # in paper mode, check to see if the new candle causes any active orders to get executed if with_execution and jh.is_paper_trading(): self.simulate_order_execution(exchange, symbol, timeframe, candle) arr[-1] = candle # regenerate other timeframes if with_generation and timeframe == '1m': self.generate_bigger_timeframes(candle, exchange, symbol, with_execution, is_forming_candle) # past candles will be ignored (dropped) elif candle[0] < arr[-1][0]: return