async def listen_for_order_book_diffs(self, ev_loop: asyncio.BaseEventLoop,
                                       output: asyncio.Queue):
     """
     Listen for orderbook diffs using websocket book channel
     """
     while True:
         async with websockets.connect(constants.WSS_URL) as ws:
             try:
                 ws: websockets.WebSocketClientProtocol = ws
                 for trading_pair in self._trading_pairs:
                     params: Dict[str, Any] = {
                         "name":
                         "SubscribeOrderBook",
                         "data":
                         k2_utils.convert_to_exchange_trading_pair(
                             trading_pair)
                     }
                     await ws.send(ujson.dumps(params))
                 async for raw_msg in self._inner_messages(ws):
                     response = ujson.loads(raw_msg)
                     timestamp = int(time.time() * 1e3)
                     if response["method"] == "SubscribeOrderBook":
                         trading_pair = k2_utils.convert_from_exchange_trading_pair(
                             response["pair"])
                         message: OrderBookMessage = K2OrderBook.snapshot_message_from_exchange(
                             msg=response,
                             timestamp=timestamp,
                             metadata={"trading_pair": trading_pair})
                     elif response["method"] == "orderbookchanged":
                         data = ujson.loads(response["data"])
                         trading_pair = k2_utils.convert_from_exchange_trading_pair(
                             data["pair"])
                         message: OrderBookMessage = K2OrderBook.diff_message_from_exchange(
                             msg=data,
                             timestamp=timestamp,
                             metadata={"trading_pair": trading_pair})
                     else:
                         # Ignores all other messages
                         continue
                     output.put_nowait(message)
             except asyncio.CancelledError:
                 raise
             except Exception:
                 self.logger().network(
                     "Unexpected error with WebSocket connection.",
                     exc_info=True,
                     app_warning_msg=
                     "Unexpected error with WebSocket connection. Retrying in 30 seconds. "
                     "Check network connection.")
                 await asyncio.sleep(30.0)
             finally:
                 await ws.close()
Ejemplo n.º 2
0
 async def get_open_orders(self) -> List[OpenOrder]:
     result = await self._api_request(method="POST",
                                      path_url=constants.GET_OPEN_ORDERS,
                                      is_auth_required=True)
     ret_val = []
     for order in result["data"]:
         # TradeType is not provided by v1/Private/GetOpenOrders endpoint
         # if order["type"] != "LIMIT":
         #     raise Exception(f"Unsupported order type {order['type']}")
         ret_val.append(
             OpenOrder(
                 client_order_id=order["orderid"],
                 trading_pair=k2_utils.convert_from_exchange_trading_pair(
                     order["symbol"]),
                 price=Decimal(str(order["price"])),
                 amount=Decimal(str(order["quantity"])),
                 executed_amount=Decimal(str(order["quantity"])) -
                 Decimal(str(order["leaveqty"])),
                 status=constants.ORDER_STATUS[order["status"]],
                 order_type=OrderType.LIMIT,
                 is_buy=True if order["type"] == "Buy" else False,
                 time=int(
                     time.time() * 1e3
                 ),  # TODO: Check in with K2 for order creation ts, order update ts
                 exchange_order_id=order[
                     "orderid"]  # TODO: Check in with K2 for unique order id
             ))
     return ret_val
Ejemplo n.º 3
0
    def update_with_trade_update(self, trade_update: Dict[str, Any]) -> bool:
        """
        Update the InFlightOrder with the trade update from Private/GetHistory API endpoint
        return: True if the order gets updated successfully otherwise False
        """
        trade_id: str = str(trade_update["id"])
        trade_order_id: str = str(trade_update["orderid"])

        if trade_order_id != self.exchange_order_id or trade_id in self.trade_id_set:
            return False

        self.trade_id_set.add(trade_id)

        trade_price: Decimal = Decimal(str(trade_update["price"]))
        trade_amount: Decimal = Decimal(str(trade_update["amount"]))

        if trade_update["type"] == "Buy":
            self.executed_amount_base += trade_amount
            self.executed_amount_quote += trade_price * trade_amount
        else:
            self.executed_amount_quote += trade_amount
            self.executed_amount_base += trade_amount / trade_price

        self.fee_paid += Decimal(str(trade_update["fee"]))

        if not self.fee_asset:
            base, quote = convert_from_exchange_trading_pair(
                trade_update["symbol"]).split("-")
            self.fee_asset = base if trade_update["type"] == "Buy" else quote

        return True
Ejemplo n.º 4
0
 async def fetch_trading_pairs() -> List[str]:
     async with aiohttp.ClientSession() as client:
         async with client.get(f"{constants.REST_URL}{constants.GET_TRADING_PAIRS}", timeout=10) as response:
             if response.status == 200:
                 try:
                     data: Dict[str, Any] = await response.json()
                     return [k2_utils.convert_from_exchange_trading_pair(item["symbol"]) for item in data["data"]]
                 except Exception:
                     pass
                     # Do nothing if the request fails -- there will be no autocomplete for kucoin trading pairs
             return []
Ejemplo n.º 5
0
 def _format_trading_rules(self, data: Dict[str,
                                            Any]) -> Dict[str, TradingRule]:
     """
     Converts json API response into a dictionary of trading rules.
     :param instruments_info: The json API response
     :return A dictionary of trading rules.
     Response Example:
     {
         "success": true,
         "data": [
             {
                 "symbol": "BEAM/BTC",
                 "buymakerfee": 0.00000000,
                 "sellmakerfee": 0.00000000,
                 "buytakerfee": 0.00200000,
                 "selltakerfee": 0.00020000,
                 "mintradevalue": 0.00010000,
                 "decimals": {
                     "price": 8,
                     "amount": 8
                 }
             },...
     """
     result = {}
     for trading_pair_stat in data["data"]:
         try:
             trading_pair = k2_utils.convert_from_exchange_trading_pair(
                 trading_pair_stat["symbol"])
             price_decimals = Decimal(
                 str(trading_pair_stat["decimals"]["price"]))
             quantity_decimals = Decimal(
                 str(trading_pair_stat["decimals"]["amount"]))
             min_trade_value = Decimal(
                 str(trading_pair_stat["mintradevalue"]))
             # E.g. a price decimal of 2 means 0.01 incremental.
             price_step = Decimal("1") / Decimal(
                 str(math.pow(10, price_decimals)))
             quantity_step = Decimal("1") / Decimal(
                 str(math.pow(10, quantity_decimals)))
             result[trading_pair] = TradingRule(
                 trading_pair,
                 min_price_increment=price_step,
                 min_base_amount_increment=quantity_step,
                 min_order_value=min_trade_value)
         except Exception:
             self.logger().error(
                 f"Error parsing the trading pair rule {data}. Skipping.",
                 exc_info=True)
             raise
     return result