Example #1
0
    def setUp(self) -> None:
        try:
            os.remove(TEST_DATABASE)
        except IOError as e:
            print(e)
        print('cwd: ', os.getcwd())

        self.dbm = DBManager(db_name=TEST_DATABASE, order_tables=['orders'])

        self.order = Order(
            session_id='S_20210501_2008',
            order_id='ORDER_ID',
            pt_id='PT_ID',
            k_side=k_binance.SIDE_BUY,
            price=50_000.0,
            amount=1.0,
        )
        self.order_2 = Order(
            session_id='S_20210501_2008',
            order_id='OR_000001',
            pt_id='PT_000001',
            k_side=k_binance.SIDE_SELL,
            price=60_000.88,
            amount=1.0876548765,
            uid='0123456789abcdef'
        )
Example #2
0
 def place_order(self, order: Order) -> Optional[dict]:
     # TODO: check and test it
     try:
         msg = self.client.create_order(
             symbol='BTCEUR',
             side=order.k_side,
             type=k_binance.ORDER_TYPE_LIMIT,
             timeInForce=k_binance.TIME_IN_FORCE_GTC,
             # TODO: check precision
             quantity=order.get_amount(precision=6),
             price=order.get_price_str(precision=2),
             newClientOrderId=order.uid)
         if msg:
             d = dict(binance_id=msg['orderId'], status=msg.get('status'))
             return d
         else:
             log.critical(f'error when placing order {order}')
     except (BinanceRequestException, BinanceAPIException,
             BinanceOrderException, BinanceOrderMinAmountException,
             BinanceOrderMinPriceException, BinanceOrderMinTotalException,
             BinanceOrderUnknownSymbolException,
             BinanceOrderInactiveSymbolException) as e:
         log.critical(e)
     except (ConnectionError, ReadTimeout) as e:
         log.critical(e)
     return None  # msg['orderId'], msg['status'] == 'FILLED' or 'NEW'
    def setUp(self) -> None:
        m1 = Order(
            session_id='S_TEST',
            order_id='OR_M1',
            pt_id='PT_ID',
            k_side=k_binance.SIDE_BUY,
            price=47300.0,
            amount=0.012,
            uid='abcdef0123456789'
        )

        m2 = Order(
            session_id='S_TEST',
            order_id='OR_M2',
            pt_id='PT_ID',
            k_side=k_binance.SIDE_SELL,
            price=47900.0,
            amount=0.012,
            uid='0123456789abcdef'
        )
        orders = [m1, m2]
        dbm = FakeDBManager()
        table = 'test_table'

        # create orders book
        self.orders_book = PendingOrdersBook(orders=orders, dbm=dbm, table=table)
Example #4
0
 def place_back_order(self, order: Order) -> None:
     if order in self.placed:
         self.placed.remove(order)
         self.monitor.append(order)
         order.set_status(OrderStatus.MONITOR)
     else:
         log.critical(
             f'trying to place back to monitor an order not found in the placed list: {order}'
         )
Example #5
0
 def place_order(self, order: Order) -> None:
     if order in self.monitor:
         self.monitor.remove(order)
         self.placed.append(order)
         # in session, once placement confirmed, will be set to status PLACED
         order.set_status(OrderStatus.TO_BE_PLACED)
     else:
         log.critical(
             f'trying to place an order not found in the monitor list: {order}'
         )
Example #6
0
 def _process_place_order(self, order: Order) -> bool:
     new_placement_allowed = True
     self.pob.place_order(order=order)
     is_order_placed, new_status = self._place_order(order=order)
     if is_order_placed:
         # 2. placed: (s: PLACED, t: pending_orders, l: placed)
         order.set_status(status=OrderStatus.PLACED)
         # to control one new placement per cycle mode
         if K_ONE_PLACE_PER_CYCLE_MODE:
             new_placement_allowed = False
     else:
         self.pob.place_back_order(order=order)
         log.critical(f'for unknown reason the order has not been placed: {order}')
     return new_placement_allowed
Example #7
0
class TestOrder(unittest.TestCase):
    def setUp(self) -> None:
        self.order = Order(
            session_id='S_20210501_2008',
            order_id='ORDER_ID',
            pt_id='PT_ID',
            k_side=k_binance.SIDE_BUY,
            price=50_000.0,
            amount=1.0,
        )

        self.order_2 = Order(session_id='S_20210501_2008',
                             order_id='OR_000001',
                             pt_id='PT_000001',
                             k_side=k_binance.SIDE_SELL,
                             price=60_000.88,
                             amount=1.0876548765,
                             uid='0123456789abcdef')

    def test_init(self):
        self.assertNotEqual('', self.order.uid)
        print(self.order)
        self.assertEqual('0123456789abcdef', self.order_2.uid)
        self.assertEqual('MONITOR', self.order.status.name)
        print(self.order_2)

    def test_is_ready_for_placement(self):
        self.assertTrue(
            self.order.is_ready_for_placement(cmp=50_020.0, min_dist=25))
Example #8
0
    def setUp(self) -> None:
        self.order = Order(
            session_id='S_20210501_2008',
            order_id='ORDER_ID',
            pt_id='PT_ID',
            k_side=k_binance.SIDE_BUY,
            price=50_000.0,
            amount=1.0,
        )

        self.order_2 = Order(session_id='S_20210501_2008',
                             order_id='OR_000001',
                             pt_id='PT_000001',
                             k_side=k_binance.SIDE_SELL,
                             price=60_000.88,
                             amount=1.0876548765,
                             uid='0123456789abcdef')
Example #9
0
 def get_order_from_row(row) -> Order:
     order = Order(session_id=row[6],
                   pt_id=row[5],
                   uid=row[0],
                   k_side=row[1],
                   price=row[2],
                   amount=row[3],
                   status=OrderStatus[row[4]],
                   order_id='FROM_DATABASE')
     return order
Example #10
0
    def get_b1s1(self,
                 dynamic_parameters: dict,
                 ) -> (Optional[Order], Optional[Order]):
        b1 = None
        s1 = None

        order_id = 'NA'

        # get perfect trade
        b1_qty, b1_price, s1_price, g = get_pt_values(**dynamic_parameters)
        s1_qty = dynamic_parameters.get('s1_qty')

        # check filters before creating order
        if Order.is_filter_passed(filters=self.symbol_filters, qty=b1_qty, price=b1_price):
            # create orders
            b1 = Order(
                session_id=self.session_id,
                order_id=order_id,
                pt_id='PENDING',
                k_side=k_binance.SIDE_BUY,
                price=b1_price,
                amount=b1_qty,
                name='b1'
            )
        else:
            log.critical(f'trying to create an order that do not meet limits: {dynamic_parameters}')

        if Order.is_filter_passed(filters=self.symbol_filters, qty=s1_qty, price=s1_price):
            s1 = Order(
                session_id=self.session_id,
                order_id=order_id,
                pt_id='PENDING',
                k_side=k_binance.SIDE_SELL,
                price=s1_price,
                amount=s1_qty,
                name='s1'
            )
        else:
            log.critical(f'trying to create an order that do not meet limits: {dynamic_parameters}')

        return b1, s1
    def is_balance_enough(self, order: Order) -> (bool, float):
        # if not enough balance, it returns False and the balance needed
        is_balance_enough = False
        if order.k_side == k_binance.SIDE_BUY:
            balance_allowance = self.current_ab.get_free_price_s2()
            available_liquidity = balance_allowance - EUR_MIN_BALANCE  # [EUR]
            if (available_liquidity - order.get_total()) > 0:
                is_balance_enough = True
        else:  # SIDE_SELL
            balance_allowance = self.current_ab.get_free_amount_s1()
            available_liquidity = balance_allowance - BTC_MIN_BALANCE  # [BTC]
            if (available_liquidity - order.amount) > 0:
                is_balance_enough = True

        return is_balance_enough
    def split_n_order(self, order: Order, inter_distance: float,
                      child_count: int) -> List[Order]:
        new_orders = []
        # calculate new amount
        new_amount = order.amount / child_count

        # create positions list
        positions = []
        if (child_count % 2) != 0:
            positions.append(0)  # child_count is odd
        # add positive
        positions += [x for x in range(1, 1 + int(child_count / 2))
                      ]  # if n=4: [1, 2]
        # add negative
        positions += [-x for x in range(1, 1 + int(child_count / 2))
                      ]  # if n=4: [1, 2, -1, -2]

        # loop positions
        for n in positions:
            new_price = order.price + inter_distance * n
            new_order = Order(session_id=order.session_id,
                              order_id=f'CHILD({n:+})',
                              pt_id=order.pt_id,
                              k_side=order.k_side,
                              price=new_price,
                              amount=new_amount,
                              status=OrderStatus.MONITOR,
                              uid=Order.get_new_uid(),
                              name=order.name + f'({n:+})')
            new_order.split_count = order.split_count + 1
            new_order.compensation_count = order.compensation_count
            new_order.concentration_count = order.concentration_count
            # add to monitor and pending_orders table
            self.pob.monitor.append(new_order)

            # add to return list
            new_orders.append(new_order)

        # delete original order from orders book
        self.pob.monitor.remove(order)

        return new_orders
    def concentrate_orders(self, orders: List[Order], ref_mp: float,
                           ref_gap: float) -> bool:
        """concentration does not include n-split
        :param orders: list of orders to concentrate
        :param ref_mp: market price to concentrate to
        :param ref_gap: concentration gap
        :return: True if concentration is successful
        """
        # check orders list is not empty
        if len(orders) < 1:
            return False

        # get equivalent amount and total
        amount, total, _, _ = BalanceManager.get_balance_for_list(orders)

        # get equivalent pair b1-s1
        s1_p, b1_p, s1_qty, b1_qty = get_compensation(cmp=ref_mp,
                                                      gap=ref_gap,
                                                      qty_bal=amount,
                                                      price_bal=total,
                                                      buy_fee=self.buy_fee,
                                                      sell_fee=self.sell_fee)

        # validate values received for b1 and s1
        if s1_p < 0 or b1_p < 0 or s1_qty < 0 or b1_qty < 0:
            log.critical(
                f'!!!!!!!!!! negative value(s) after compensation: b1p: {b1_p} - b1q: {b1_qty} !!!!!!!!!!'
                f'- s1p: {s1_p} - s1q: {s1_qty}')
            return False
        else:
            # get pt_id of all orders to concentrate
            pt_ids = []
            for order in orders:
                if order.pt_id not in pt_ids:
                    pt_ids.append(order.pt_id)

            # increment counter and save mapping between count and pt_ids
            # at this point the concentration is sure and will return True
            self.concentrator_count += 1
            self.concentrated_pt_id.append((self.concentrator_count, pt_ids))
            print(self.concentrated_pt_id)

            # change pending orders with this pt_id to new pt_id
            new_pt_id = f'C-{self.concentrator_count:04}'
            for order in self.pob.get_pending_orders():
                if order.pt_id in pt_ids:
                    order.pt_id = new_pt_id
            # change pt_id also in traded orders
            self.tob.set_new_pt_id(new_pt_id=new_pt_id, pt_id_list=pt_ids)

            # create both orders
            session_id = orders[0].session_id  # same session_id
            b1 = Order(session_id=session_id,
                       order_id='CONCENTRATED',
                       pt_id=new_pt_id,
                       k_side=k_binance.SIDE_BUY,
                       price=b1_p,
                       amount=b1_qty,
                       status=OrderStatus.MONITOR,
                       uid=Order.get_new_uid(),
                       name='con-b1')
            s1 = Order(session_id=session_id,
                       order_id='CONCENTRATED',
                       pt_id=new_pt_id,
                       k_side=k_binance.SIDE_SELL,
                       price=s1_p,
                       amount=s1_qty,
                       status=OrderStatus.MONITOR,
                       uid=Order.get_new_uid(),
                       name='con-s1')

            # add new orders to appropriate list
            self.pob.monitor.append(b1)
            self.pob.monitor.append(s1)

            # delete original orders from list
            for order in orders:
                self.pob.monitor.remove(order)

            # log
            log.info('////////// ORDER COMPENSATED //////////')
            for order in orders:
                log.info(f'initial order:  {order}')
                log.info(f'compensation count: {order.compensation_count}')
            log.info(f'compensated b1: {b1}')
            log.info(f'compensated s1: {s1}')

            # update concentrated variables and inverse counter
            b1.concentration_count = 1
            s1.concentration_count = 1

            # update variables
            b1.compensation_count = 0
            b1.split_count = 0
            s1.compensation_count = 0
            s1.split_count = 0

            # split n
            # self.split_n_order(order=b1, inter_distance=interdistance_after_concentration, child_count=n_for_split)
            # self.split_n_order(order=s1, inter_distance=interdistance_after_concentration, child_count=n_for_split)

            return True
    def concentrate_for_liquidity(self, order: Order, ref_mp: float,
                                  ref_gap: float) -> bool:
        """concentration does not include n-split
        :param order: order to concentrate
        :param ref_mp: market price to concentrate to
        :param ref_gap: concentration gap
        :return: True if concentration is successful
        """

        # get equivalent amount and total
        amount, total, _, _ = BalanceManager.get_balance_for_list([order])

        # get equivalent pair b1-s1
        s1_p, b1_p, s1_qty, b1_qty = get_compensation(cmp=ref_mp,
                                                      gap=ref_gap,
                                                      qty_bal=amount,
                                                      price_bal=total,
                                                      buy_fee=self.buy_fee,
                                                      sell_fee=self.sell_fee)

        # validate values received for b1 and s1
        if s1_p < 0 or b1_p < 0 or s1_qty < 0 or b1_qty < 0:
            log.critical(
                f'!!!!!!!!!! negative value(s) after compensation: b1p: {b1_p} - b1q: {b1_qty} !!!!!!!!!!'
                f'- s1p: {s1_p} - s1q: {s1_qty}')
            return False
        else:

            # increment counter and save mapping between count and pt_ids
            # at this point the concentration is sure and will return True
            self.concentrator_count += 1

            # create both orders
            session_id = order.session_id  # same session_id
            b1 = Order(session_id=session_id,
                       order_id='CONCENTRATED',
                       pt_id=order.pt_id,
                       k_side=k_binance.SIDE_BUY,
                       price=b1_p,
                       amount=b1_qty,
                       status=OrderStatus.MONITOR,
                       uid=Order.get_new_uid(),
                       name='con-b1')
            s1 = Order(session_id=session_id,
                       order_id='CONCENTRATED',
                       pt_id=order.pt_id,
                       k_side=k_binance.SIDE_SELL,
                       price=s1_p,
                       amount=s1_qty,
                       status=OrderStatus.MONITOR,
                       uid=Order.get_new_uid(),
                       name='con-s1')

            # add new orders to appropriate list
            self.pob.monitor.append(b1)
            self.pob.monitor.append(s1)

            # delete original order from list
            self.pob.monitor.remove(order)

            # log
            print(f'concentrated order: {order}')
            log.info(f'initial order:  {order}')
            log.info(f'concentration count: {order.concentration_count}')
            log.info(f'compensated b1: {b1}')
            log.info(f'compensated s1: {s1}')

            # update concentrated variables and inverse counter
            b1.concentration_count = 1
            s1.concentration_count = 1

            # update variables
            b1.compensation_count = 0
            b1.split_count = 0
            s1.compensation_count = 0
            s1.split_count = 0

            return True