Exemple #1
0
def save_daily_portfolio_balance() -> None:
    balances = []

    # add exchange balances
    for key, e in store.exchanges.storage.items():
        balances.append(e.assets[jh.app_currency()])

        # store daily_balance of assets into database
        if jh.is_livetrading():
            for asset_key, asset_value in e.assets.items():
                store_daily_balance_into_db({
                    'id':
                    jh.generate_unique_id(),
                    'timestamp':
                    jh.now(),
                    'identifier':
                    jh.get_config('env.identifier', 'main'),
                    'exchange':
                    e.name,
                    'asset':
                    asset_key,
                    'balance':
                    asset_value,
                })

    # add open position values
    for key, pos in store.positions.storage.items():
        if pos.is_open:
            balances.append(pos.pnl)

    total = sum(balances)
    store.app.daily_balance.append(total)
    logger.info('Saved daily portfolio balance: {}'.format(round(total, 2)))
Exemple #2
0
    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'
                )
            )
Exemple #3
0
    def liquidation_price(self):
        """
        The price at which the position gets liquidated. formulas are taken from:
        https://help.bybit.com/hc/en-us/articles/900000181046-Liquidation-Price-USDT-Contract-
        """
        if self.is_close:
            return np.nan

        if jh.is_livetrading():
            return self._liquidation_price

        if self.mode == 'isolated':
            if self.type == 'long':
                return self.entry_price * (1 - self._initial_margin_rate +
                                           0.004)
            elif self.type == 'short':
                return self.entry_price * (1 + self._initial_margin_rate -
                                           0.004)
            else:
                return np.nan

        elif self.mode == 'cross':
            return np.nan

        elif self.mode == 'spot':
            return np.nan

        else:
            raise ValueError
Exemple #4
0
        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'))
Exemple #5
0
def save_daily_portfolio_balance() -> None:
    balances = []

    # add exchange balances
    for key, e in store.exchanges.storage.items():
        balances.append(e.assets[jh.app_currency()])

        # # store daily_balance of assets into database
        # if jh.is_livetrading():
        #     for asset_key, asset_value in e.assets.items():
        #         store_daily_balance_into_db({
        #             'id': jh.generate_unique_id(),
        #             'timestamp': jh.now(),
        #             'identifier': jh.get_config('env.identifier', 'main'),
        #             'exchange': e.name,
        #             'asset': asset_key,
        #             'balance': asset_value,
        #         })

    # add open position values
    for key, pos in store.positions.storage.items():
        if pos.is_open:
            balances.append(pos.pnl)

    total = sum(balances)
    store.app.daily_balance.append(total)

    # TEMP: disable storing in database for now
    if not jh.is_livetrading():
        logger.info(f'Saved daily portfolio balance: {round(total, 2)}')
Exemple #6
0
def test_is_livetrading():
    assert jh.is_livetrading() is False
Exemple #7
0
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
Exemple #8
0
    def _log_position_update(self, order: Order, role: str) -> None:
        """
        A log can be either about opening, adding, reducing, or closing the position.

        Arguments:
            order {order} -- the order object
        """
        # set the trade_id for the order if we're in the middle of a trade. Otherwise, it
        # is done at order_roles.OPEN_POSITION
        if self.trade:
            order.trade_id = self.trade.id

        if role == order_roles.OPEN_POSITION:
            self.trade = CompletedTrade()
            self.trade.leverage = self.leverage
            self.trade.orders = [order]
            self.trade.timeframe = self.timeframe
            self.trade.id = jh.generate_unique_id()
            order.trade_id = self.trade.id
            self.trade.strategy_name = self.name
            self.trade.exchange = order.exchange
            self.trade.symbol = order.symbol
            self.trade.type = trade_types.LONG if order.side == sides.BUY else trade_types.SHORT
            self.trade.qty = order.qty
            self.trade.opened_at = jh.now_to_timestamp()
            self.trade.entry_candle_timestamp = self.current_candle[0]
        elif role == order_roles.INCREASE_POSITION:
            self.trade.orders.append(order)
            self.trade.qty += order.qty
        elif role == order_roles.REDUCE_POSITION:
            self.trade.orders.append(order)
            self.trade.qty += order.qty
        elif role == order_roles.CLOSE_POSITION:
            self.trade.exit_candle_timestamp = self.current_candle[0]
            self.trade.orders.append(order)

            # calculate average stop-loss price
            sum_price = 0
            sum_qty = 0
            if self._log_stop_loss is not None:
                for l in self._log_stop_loss:
                    sum_qty += abs(l[0])
                    sum_price += abs(l[0]) * l[1]
                self.trade.stop_loss_at = sum_price / sum_qty
            else:
                self.trade.stop_loss_at = np.nan

            # calculate average take-profit price
            sum_price = 0
            sum_qty = 0
            if self._log_take_profit is not None:
                for l in self._log_take_profit:
                    sum_qty += abs(l[0])
                    sum_price += abs(l[0]) * l[1]
                self.trade.take_profit_at = sum_price / sum_qty
            else:
                self.trade.take_profit_at = np.nan

            # calculate average entry_price price
            sum_price = 0
            sum_qty = 0
            for l in self.trade.orders:
                if not l.is_executed:
                    continue

                if jh.side_to_type(l.side) != self.trade.type:
                    continue

                sum_qty += abs(l.qty)
                sum_price += abs(l.qty) * l.price
            self.trade.entry_price = sum_price / sum_qty

            # calculate average exit_price
            sum_price = 0
            sum_qty = 0
            for l in self.trade.orders:
                if not l.is_executed:
                    continue

                if jh.side_to_type(l.side) == self.trade.type:
                    continue

                sum_qty += abs(l.qty)
                sum_price += abs(l.qty) * l.price
            self.trade.exit_price = sum_price / sum_qty

            self.trade.closed_at = jh.now_to_timestamp()
            self.trade.qty = pydash.sum_by(
                filter(lambda o: o.side == jh.type_to_side(self.trade.type),
                       self.trade.orders), lambda o: abs(o.qty))

            store.completed_trades.add_trade(self.trade)
            if jh.is_livetrading():
                store_completed_trade_into_db(self.trade)
            self.trade = None
            self.trades_count += 1

        if jh.is_livetrading():
            store_order_into_db(order)