예제 #1
0
    def from_dict(values: Dict[str, Any], quantity_key: str, price_key: str = 'price', price: Decimal = None,
                  futures: bool = False) -> 'Order':
        if price is None:
            price = parse_decimal(values[price_key])

        quantity = parse_decimal(values[quantity_key])
        order_list_id = values['orderListId'] if values.get('orderListId', -1) != -1 else None

        return Order(values['symbol'], values['side'], values['type'], values['status'], values['orderId'],
                     order_list_id, quantity, price, futures)
 def process_api_spot_message(self, msg: dict) -> None:
     if msg['e'] == 'executionReport':
         order_list_id = msg['g'] if msg['g'] != -1 else None
         order = Order(symbol=msg['s'],
                       side=msg['S'],
                       order_type=msg['o'],
                       status=msg['X'],
                       order_id=msg['i'],
                       order_list_id=order_list_id,
                       quantity=parse_decimal(msg['l']),
                       price=parse_decimal(msg['L']))
         self._process_api_order(order)
 def process_api_futures_message(self, message: dict) -> None:
     if message['data']['e'] == 'ORDER_TRADE_UPDATE':
         msg = message['data']['o']
         order = Order(symbol=msg['s'],
                       side=msg['S'],
                       order_type=msg['o'],
                       original_type=msg['ot'],
                       status=msg['X'],
                       order_id=msg['i'],
                       order_list_id=None,
                       quantity=parse_decimal(msg['l']),
                       price=parse_decimal(msg['L']),
                       futures=True)
         self._process_api_order(order)
예제 #4
0
 def _check_is_empty(self, symbol: str) -> None:
     positions = self._client.futures_position_information(symbol=symbol)
     assert len(positions) == 1
     assert parse_decimal(positions[0]['positionAmt']) == Decimal(
         0), f'{symbol} has open future position'
     assert len(self._client.futures_get_open_orders(
         symbol=symbol)) == 0, f'{symbol} has open future order'
예제 #5
0
    def _get_last_buy_order(self, symbol: str) -> Optional[Order]:
        api_orders = self._client.get_all_orders(symbol=symbol)
        api_orders.sort(key=lambda o: o['updateTime'], reverse=True)

        for info in api_orders:
            if info['side'] == Order.SIDE_BUY and info[
                    'status'] == Order.STATUS_FILLED:
                # price is zero in original response
                price = parse_decimal(
                    info['cummulativeQuoteQty']) / parse_decimal(
                        info['executedQty'])

                return Order.from_dict(info,
                                       price=price,
                                       quantity_key='executedQty')
        else:
            return None
예제 #6
0
    def market_sell(self, symbol: str, quantity: Decimal) -> Order:
        info = self._client.order_market_sell(
            symbol=symbol,
            quantity=quantity,
        )

        if info['status'] != Order.STATUS_FILLED:
            sleep(1)
            info = self._client.get_order(symbol=info['symbol'],
                                          orderId=info['orderId'])

        # price is zero in original response
        price = parse_decimal(info['cummulativeQuoteQty']) / parse_decimal(
            info['executedQty'])
        order = Order.from_dict(info, price=price, quantity_key='executedQty')
        assert order.status == Order.STATUS_FILLED, f'Got {order.status}'

        return order
예제 #7
0
    def get_sell_order_pnl(self, sell_order: Order) -> Optional[Decimal]:
        assert sell_order.side == Order.SIDE_SELL
        assert sell_order.status == Order.STATUS_FILLED
        trades = self._client.futures_account_trades(symbol=sell_order.symbol)
        pln = [
            parse_decimal(info['realizedPnl']) for info in trades
            if info['orderId'] == sell_order.order_id
        ]

        return pln[0] if len(pln) != 0 else None
예제 #8
0
    def _symbol_infos(self) -> Dict[str, SymbolInfo]:
        if len(self.__symbol_infos) == 0:
            all_info = self._client.futures_exchange_info()

            for info in all_info['symbols']:
                symbol = info['symbol']
                min_notional = [
                    parse_decimal(f['notional']) for f in info['filters']
                    if f['filterType'] == 'MIN_NOTIONAL'
                ][0]
                self.__symbol_infos[symbol] = SymbolInfo(
                    int(info['quantityPrecision']),
                    int(info['pricePrecision']), min_notional)

        return self.__symbol_infos
예제 #9
0
    def get_symbol_info(self, symbol: str) -> SymbolInfo:
        if symbol not in self._symbol_infos:
            info = self._client.get_symbol_info(symbol=symbol)
            quantity_precision, price_precision, min_notional = None, None, None

            def parse(key: str) -> int:
                return int(round(-math.log(Decimal(f[key]), 10), 0))

            for f in info['filters']:
                if f['filterType'] == 'LOT_SIZE':
                    quantity_precision = parse('stepSize')
                elif f['filterType'] == 'PRICE_FILTER':
                    price_precision = parse('tickSize')
                elif f['filterType'] == 'MIN_NOTIONAL':
                    min_notional = parse_decimal(f['minNotional'])

            assert quantity_precision is not None and price_precision is not None and min_notional is not None
            self._symbol_infos[symbol] = SymbolInfo(quantity_precision,
                                                    price_precision,
                                                    min_notional)

        return self._symbol_infos[symbol]
예제 #10
0
    def get_current_price(self, symbol: str) -> Decimal:
        info = self._client.get_symbol_ticker(symbol=symbol)

        return parse_decimal(info['price'])
예제 #11
0
    def get_open_position_quantity(self, symbol: str) -> Decimal:
        info = self._client.futures_position_information(symbol=symbol)
        assert len(info) == 1

        return parse_decimal(info[0]['positionAmt'])