Beispiel #1
0
    async def on_event_orderbook_update(self, orderbook: Orderbook):
        """ 订单薄更新
        """
        logger.debug("orderbook:", orderbook, caller=self)
        bid3_price = orderbook.bids[2][0]  # 买三价格
        bid4_price = orderbook.bids[3][0]  # 买四价格

        # 判断是否需要撤单
        if self.order_id:
            if float(self.create_order_price) < float(bid3_price) or float(
                    self.create_order_price) > float(bid4_price):
                return
            _, error = await self.trader.revoke_order(self.order_id)
            if error:
                logger.error("revoke order error! error:", error, caller=self)
                return
            self.order_id = None
            logger.info("revoke order:", self.order_id, caller=self)

        # 创建新订单
        price = (float(bid3_price) + float(bid4_price)) / 2
        quantity = "0.1"  # 假设委托数量为0.1
        action = ORDER_ACTION_BUY
        order_id, error = await self.trader.create_order(
            action, price, quantity)
        if error:
            logger.error("create order error! error:", error, caller=self)
            return
        self.order_id = order_id
        self.create_order_price = price
        logger.info("create new order:", order_id, caller=self)
Beispiel #2
0
 def _add_event_handler(self, event: Event, callback):
     key = "{exchange}:{routing_key}".format(exchange=event.exchange, routing_key=event.routing_key)
     if key in self._event_handler:
         self._event_handler[key].append(callback)
     else:
         self._event_handler[key] = [callback]
     logger.debug("event handlers:", self._event_handler.keys(), caller=self)
Beispiel #3
0
    async def process(self, msg):
        """Process message that received from Websocket connection.

        Args:
            msg: message received from Websocket connection.
        """
        logger.debug("msg:", json.dumps(msg), caller=self)
        e = msg.get("e")
        if e == "executionReport":  # Order update.
            if msg["s"] != self._raw_symbol:
                return
            order_id = str(msg["i"])
            if msg["X"] == "NEW":
                status = ORDER_STATUS_SUBMITTED
            elif msg["X"] == "PARTIALLY_FILLED":
                status = ORDER_STATUS_PARTIAL_FILLED
            elif msg["X"] == "FILLED":
                status = ORDER_STATUS_FILLED
            elif msg["X"] == "CANCELED":
                status = ORDER_STATUS_CANCELED
            elif msg["X"] == "REJECTED":
                status = ORDER_STATUS_FAILED
            elif msg["X"] == "EXPIRED":
                status = ORDER_STATUS_FAILED
            else:
                logger.warn("unknown status:", msg, caller=self)
                SingleTask.run(self._error_callback, "order status error.")
                return
            order = self._orders.get(order_id)
            if not order:
                info = {
                    "platform": self._platform,
                    "account": self._account,
                    "strategy": self._strategy,
                    "order_id": order_id,
                    "client_order_id": msg["c"],
                    "action": ORDER_ACTION_BUY
                    if msg["S"] == "BUY" else ORDER_ACTION_SELL,
                    "order_type": ORDER_TYPE_LIMIT
                    if msg["o"] == "LIMIT" else ORDER_TYPE_MARKET,
                    "symbol": self._symbol,
                    "price": msg["p"],
                    "quantity": msg["q"],
                    "ctime": msg["O"]
                }
                order = Order(**info)
                self._orders[order_id] = order
            order.remain = float(msg["q"]) - float(msg["z"])
            order.status = status
            order.utime = msg["T"]

            SingleTask.run(self._order_update_callback, copy.copy(order))
            if status in [
                    ORDER_STATUS_FAILED, ORDER_STATUS_CANCELED,
                    ORDER_STATUS_FILLED
            ]:
                self._orders.pop(order_id)
Beispiel #4
0
    async def process_binary(self, raw):
        """Process binary message that received from websocket.

        Args:
            raw: Binary message received from websocket.

        Returns:
            None.
        """
        msg = json.loads(gzip.decompress(raw).decode())
        logger.debug("msg:", msg, caller=self)

        op = msg.get("op")

        if op == "auth":
            if msg["err-code"] != 0:
                e = Error(
                    "Websocket connection authorized failed: {}".format(msg))
                logger.error(e, caller=self)
                SingleTask.run(self._error_callback, e)
                SingleTask.run(self._init_callback, False)
                return
            logger.info("Websocket connection authorized successfully.",
                        caller=self)
            await self._auth_success_callback()
        elif op == "ping":  # ping
            params = {"op": "pong", "ts": msg["ts"]}
            await self._ws.send(params)
        elif op == "sub":
            if msg["topic"] != self._order_channel:
                return
            if msg["err-code"] != 0:
                e = Error("subscribe order event error: {}".format(msg))
                SingleTask.run(self._error_callback, e)
                SingleTask.run(self._init_callback, False)
            else:
                SingleTask.run(self._init_callback, True)
        elif op == "notify":
            if msg["topic"] != self._order_channel:
                return
            data = msg["data"]
            data["utime"] = msg["ts"]
            self._update_order(data)
Beispiel #5
0
    async def send(self, data) -> bool:
        """ Send message to Websocket server.

        Args:
            data: Message content, must be dict or string.

        Returns:
            If send successfully, return True, otherwise return False.
        """
        if not self.ws:
            logger.warn("Websocket connection not connected yet!", caller=self)
            return False
        if isinstance(data, dict):
            await self.ws.send_json(data)
        elif isinstance(data, str):
            await self.ws.send_str(data)
        else:
            logger.error("send message failed:", data, caller=self)
            return False
        logger.debug("send message:", data, caller=self)
        return True
Beispiel #6
0
    async def connect(self, reconnect=False):
        """Connect to RabbitMQ server and create default exchange.

        Args:
            reconnect: If this invoke is a re-connection ?
        """
        logger.info("host:", self._host, "port:", self._port, caller=self)
        if self._connected:
            return

        # Create a connection.
        try:
            transport, protocol = await aioamqp.connect(host=self._host, port=self._port, login=self._username,
                                                        password=self._password, login_method="PLAIN")
        except Exception as e:
            logger.error("connection error:", e, caller=self)
            return
        finally:
            if self._connected:
                return
        channel = await protocol.channel()
        self._protocol = protocol
        self._channel = channel
        self._connected = True
        logger.info("Rabbitmq initialize success!", caller=self)

        # Create default exchanges.
        exchanges = ["Orderbook", "Kline", "Trade"]
        for name in exchanges:
            await self._channel.exchange_declare(exchange_name=name, type_name="topic")
        logger.debug("create default exchanges success!", caller=self)

        if reconnect:
            self._bind_and_consume()
        else:
            # Maybe we should waiting for all modules to be initialized successfully.
            asyncio.get_event_loop().call_later(5, self._bind_and_consume)
Beispiel #7
0
    async def fetch(cls,
                    method,
                    url,
                    params=None,
                    body=None,
                    data=None,
                    headers=None,
                    timeout=30,
                    **kwargs):
        """ Create a HTTP request.

        Args:
            method: HTTP request method. `GET` / `POST` / `PUT` / `DELETE`
            url: Request url.
            params: HTTP query params.
            body: HTTP request body, string or bytes format.
            data: HTTP request body, dict format.
            headers: HTTP request header.
            timeout: HTTP request timeout(seconds), default is 30s.

            kwargs:
                proxy: HTTP proxy.

        Return:
            code: HTTP response code.
            success: HTTP response data. If something wrong, this field is None.
            error: If something wrong, this field will holding a Error information, otherwise it's None.

        Raises:
            HTTP request exceptions or response data parse exceptions. All the exceptions will be captured and return
            Error information.
        """
        session = cls._get_session(url)
        if not kwargs.get("proxy"):
            kwargs[
                "proxy"] = config.proxy  # If there is a `HTTP PROXY` Configuration in config file?
        try:
            if method == "GET":
                response = await session.get(url,
                                             params=params,
                                             headers=headers,
                                             timeout=timeout,
                                             **kwargs)
            elif method == "POST":
                response = await session.post(url,
                                              params=params,
                                              data=body,
                                              json=data,
                                              headers=headers,
                                              timeout=timeout,
                                              **kwargs)
            elif method == "PUT":
                response = await session.put(url,
                                             params=params,
                                             data=body,
                                             json=data,
                                             headers=headers,
                                             timeout=timeout,
                                             **kwargs)
            elif method == "DELETE":
                response = await session.delete(url,
                                                params=params,
                                                data=body,
                                                json=data,
                                                headers=headers,
                                                timeout=timeout,
                                                **kwargs)
            else:
                error = "http method error!"
                return None, None, error
        except Exception as e:
            logger.error("method:",
                         method,
                         "url:",
                         url,
                         "headers:",
                         headers,
                         "params:",
                         params,
                         "body:",
                         body,
                         "data:",
                         data,
                         "Error:",
                         e,
                         caller=cls)
            return None, None, e
        code = response.status
        if code not in (200, 201, 202, 203, 204, 205, 206):
            text = await response.text()
            logger.error("method:",
                         method,
                         "url:",
                         url,
                         "headers:",
                         headers,
                         "params:",
                         params,
                         "body:",
                         body,
                         "data:",
                         data,
                         "code:",
                         code,
                         "result:",
                         text,
                         caller=cls)
            return code, None, text
        try:
            result = await response.json()
        except:
            result = await response.text()
            logger.debug("response data is not json format!",
                         "method:",
                         method,
                         "url:",
                         url,
                         "headers:",
                         headers,
                         "params:",
                         params,
                         "body:",
                         body,
                         "data:",
                         data,
                         "code:",
                         code,
                         "result:",
                         result,
                         caller=cls)
        logger.debug("method:",
                     method,
                     "url:",
                     url,
                     "headers:",
                     headers,
                     "params:",
                     params,
                     "body:",
                     body,
                     "data:",
                     data,
                     "code:",
                     code,
                     "result:",
                     json.dumps(result),
                     caller=cls)
        return code, result, None
Beispiel #8
0
    async def process_binary(self, raw):
        """Process binary message that received from websocket.

        Args:
            raw: Binary message received from websocket.

        Returns:
            None.
        """
        decompress = zlib.decompressobj(-zlib.MAX_WBITS)
        msg = decompress.decompress(raw)
        msg += decompress.flush()
        msg = msg.decode()
        if msg == "pong":
            return
        logger.debug("msg:", msg, caller=self)
        msg = json.loads(msg)

        # Authorization message received.
        if msg.get("event") == "login":
            if not msg.get("success"):
                e = Error(
                    "Websocket connection authorized failed: {}".format(msg))
                logger.error(e, caller=self)
                SingleTask.run(self._error_callback, e)
                SingleTask.run(self._init_callback, False)
                return
            logger.info("Websocket connection authorized successfully.",
                        caller=self)

            # Fetch orders from server. (open + partially filled)
            order_infos, error = await self._rest_api.get_open_orders(
                self._raw_symbol)
            if error:
                e = Error("get open orders error: {}".format(msg))
                SingleTask.run(self._error_callback, e)
                SingleTask.run(self._init_callback, False)
                return
            if len(order_infos) > 100:
                logger.warn("order length too long! (more than 100)",
                            caller=self)
            for order_info in order_infos:
                order_info["ctime"] = order_info["created_at"]
                order_info["utime"] = order_info["timestamp"]
                self._update_order(order_info)

            # Subscribe order channel.
            data = {"op": "subscribe", "args": [self._order_channel]}
            await self._ws.send(data)
            return

        # Subscribe response message received.
        if msg.get("event") == "subscribe":
            if msg.get("channel") == self._order_channel:
                SingleTask.run(self._init_callback, True)
            else:
                e = Error("subscribe order event error: {}".format(msg))
                SingleTask.run(self._error_callback, e)
                SingleTask.run(self._init_callback, False)
            return

        # Order update message received.
        if msg.get("table") == "spot/order":
            for data in msg["data"]:
                data["ctime"] = data["timestamp"]
                data["utime"] = data["last_fill_time"]
                self._update_order(data)