Example #1
0
 async def _reset_listen_key(self, *args, **kwargs):
     """Reset listen key."""
     if not self._listen_key:
         logger.error("listen key not initialized!", caller=self)
         return
     await self._rest_api.put_listen_key(self._listen_key)
     logger.info("reset listen key success!", caller=self)
Example #2
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)
Example #3
0
    def ticker(self):
        """Loop run ticker per self._interval.
        """
        self._count += 1

        if self._print_interval > 0:
            if self._count % self._print_interval == 0:
                logger.info("do server heartbeat, count:",
                            self._count,
                            caller=self)

        # Later call next ticker.
        asyncio.get_event_loop().call_later(self._interval, self.ticker)

        # Exec tasks.
        for task_id, task in self._tasks.items():
            interval = task["interval"]
            if self._count % interval != 0:
                continue
            func = task["func"]
            args = task["args"]
            kwargs = task["kwargs"]
            kwargs["task_id"] = task_id
            kwargs["heart_beat_count"] = self._count
            asyncio.get_event_loop().create_task(func(*args, **kwargs))
 async def get_k_line(self):
     """获取K线数据"""
     symbol = self.symbol
     success, error = await self._rest_api.get_klines(symbol,
                                                      interval="1m",
                                                      limit=10)
     logger.info("success", success, caller=self)
     logger.info("error", error, caller=self)
Example #5
0
    async def on_event_order_update(self, order: Order):
        """ 订单状态更新
        """
        logger.info("order update:", order, caller=self)

        # 如果订单失败、订单取消、订单完成交易
        if order.status in [
                ORDER_STATUS_FAILED, ORDER_STATUS_CANCELED, ORDER_STATUS_FILLED
        ]:
            self.order_id = None
    async def on_init_callback(self, success: bool, **kwargs):
        """用于标记: 初始化Trade()成功或失败"""
        logger.info("success", success, caller=self)
        if not success:
            return

        _, error = await self._trade.revoke_order()
        if error:
            return

        self._is_ok = True
Example #7
0
    async def subscribe(self, event: Event, callback=None, multi=False):
        """Subscribe a event.

        Args:
            event: Event type.
            callback: Asynchronous callback.
            multi: If subscribe multiple channel(routing_key) ?
        """
        logger.info("NAME:", event.name, "EXCHANGE:", event.exchange, "QUEUE:", event.queue, "ROUTING_KEY:",
                    event.routing_key, caller=self)
        self._subscribers.append((event, callback, multi))
 async def create_new_order(self, price: float):
     """下单"""
     action = self._action
     quantity = self._quantity  # min 2.5
     logger.info("Doing price: ", price, "quantity: ", self._quantity)
     order_id, error = await self._trade.create_order(
         action, price, quantity)
     if error:
         return
     self._order_id = order_id
     self._price = price
     logger.info("order_id", self._order_id, "price", price, caller=self)
Example #9
0
 async def _connect(self) -> None:
     logger.info("url:", self._url, caller=self)
     proxy = config.proxy
     session = aiohttp.ClientSession()
     try:
         self._ws = await session.ws_connect(self._url, proxy=proxy)
     except aiohttp.ClientConnectorError:
         logger.error("connect to Websocket server error! url:",
                      self._url,
                      caller=self)
         return
     if self._connected_callback:
         SingleTask.run(self._connected_callback)
     SingleTask.run(self._receive)
Example #10
0
    async def connected_callback(self):
        """After websocket connection created successfully, pull back all open order information."""
        logger.info("Websocket connection authorized successfully.", caller=self)
        order_infos, error = await self._rest_api.get_open_orders(self._raw_symbol)
        if error:
            e = Error("get open orders error: {}".format(error))
            SingleTask.run(self._error_callback, e)
            SingleTask.run(self._init_callback, False)
            return
        for order_info in order_infos:
            if order_info["status"] == "NEW":
                status = ORDER_STATUS_SUBMITTED
            elif order_info["status"] == "PARTIALLY_FILLED":
                status = ORDER_STATUS_PARTIAL_FILLED
            elif order_info["status"] == "FILLED":
                status = ORDER_STATUS_FILLED
            elif order_info["status"] == "CANCELED":
                status = ORDER_STATUS_CANCELED
            elif order_info["status"] == "REJECTED":
                status = ORDER_STATUS_FAILED
            elif order_info["status"] == "EXPIRED":
                status = ORDER_STATUS_FAILED
            else:
                logger.warn("unknown status:", order_info, caller=self)
                SingleTask.run(self._error_callback, "order status error.")
                continue

            order_id = str(order_info["orderId"])
            info = {
                "platform": self._platform,
                "account": self._account,
                "strategy": self._strategy,
                "order_id": order_id,
                "client_order_id": order_info["clientOrderId"],
                "action": ORDER_ACTION_BUY if order_info["side"] == "BUY" else ORDER_ACTION_SELL,
                "order_type": ORDER_TYPE_LIMIT if order_info["type"] == "LIMIT" else ORDER_TYPE_MARKET,
                "symbol": self._symbol,
                "price": order_info["price"],
                "quantity": order_info["origQty"],
                "remain": float(order_info["origQty"]) - float(order_info["executedQty"]),
                "status": status,
                "avg_price": order_info["price"],
                "ctime": order_info["time"],
                "utime": order_info["updateTime"]
            }
            order = Order(**info)
            self._orders[order_id] = order
            SingleTask.run(self._order_update_callback, copy.copy(order))

        SingleTask.run(self._init_callback, True)
Example #11
0
    def start(self, config_file=None, entrance_func=None) -> None:
        """Start the event loop."""
        def keyboard_interrupt(s, f):
            print("KeyboardInterrupt (ID: {}) has been caught. Cleaning up...".format(s))
            self.stop()
        signal.signal(signal.SIGINT, keyboard_interrupt)

        self._initialize(config_file)
        if entrance_func:
            if inspect.iscoroutinefunction(entrance_func):
                self.loop.create_task(entrance_func())
            else:
                entrance_func()

        logger.info("start io loop ...", caller=self)
        self.loop.run_forever()
 async def on_order_update_callback(self, order: Order):
     """不会主动被调用,当订单有变化的时候会被调用"""
     logger.info("order", order, caller=self)
     if order.status == ORDER_STATUS_FILLED:
         # 完全成交
         self._order_id = ""
         self._price = 0.0
         # TODO: 完全对冲
     elif order.status == ORDER_STATUS_PARTIAL_FILLED:
         # 部分成交
         # TODO: 部分对冲
         pass
     elif order.status == ORDER_STATUS_FAILED:
         # 报警, 触发风控
         pass
     else:
         return
Example #13
0
 async def _initialize(self, event: Event, callback=None, multi=False):
     if event.queue:
         await self._channel.queue_declare(queue_name=event.queue, auto_delete=True)
         queue_name = event.queue
     else:
         result = await self._channel.queue_declare(exclusive=True)
         queue_name = result["queue"]
     await self._channel.queue_bind(queue_name=queue_name, exchange_name=event.exchange,
                                    routing_key=event.routing_key)
     await self._channel.basic_qos(prefetch_count=event.prefetch_count)
     if callback:
         if multi:
             await self._channel.basic_consume(callback=callback, queue_name=queue_name, no_ack=True)
             logger.info("multi message queue:", queue_name, caller=self)
         else:
             await self._channel.basic_consume(self._on_consume_event_msg, queue_name=queue_name)
             logger.info("queue:", queue_name, caller=self)
             self._add_event_handler(event, callback)
Example #14
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)
    async def dynamic_trade_with_binance(self, *args, **kwargs):
        """简化版的吃盘口毛刺策略"""
        if not self._is_ok:
            return
        success, error = await self._trade.rest_api.get_orderbook(
            self._symbol, 10)
        if error:
            # 通过 钉钉、微信等发送通知...
            # 或 接入风控系统;
            self._is_ok = False
            logger.warn("error: ", error, caller=self)
            return

        ask6_price = float(success["asks"][5][0])
        ask8_price = float(success["asks"][7][0])
        average_price = round((ask6_price + ask8_price) / 2, 4)
        logger.info(f"the average price is {average_price}....", caller=self)

        await self.strategy_process(ask6_price, ask8_price, average_price)
Example #16
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)
 async def on_error_callback(self, error: Error, **kwargs):
     """执行过程中有任意的失败情况下都会报错"""
     self._is_ok = False
     logger.info("error", error, caller=self)
     quant.stop()
 async def revoke_order(self, order_id: str):
     """撤销订单"""
     _, error = await self._trade.revoke_order(order_id)
     if error:
         return
     logger.info("order_id: ", order_id, caller=self)
 async def get_trade(self):
     """获取最新的逐笔成交数据"""
     symbol = self.symbol
     success, error = await self._rest_api.get_latest_trade(symbol, 10)
     logger.info("success", success, caller=self)
     logger.info("error", error, caller=self)
Example #20
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)
 async def get_orderbook(self):
     """获取盘口订单薄数据"""
     symbol = self.symbol
     success, error = await self._rest_api.get_orderbook(symbol, 10)
     logger.info("success", success, caller=self)
Example #22
0
 async def on_event_error_callback(self, error, **kwargs):
     """错误回调"""
     logger.info("error:", error, "kwargs:", kwargs, caller=self)
Example #23
0
 async def on_event_init_callback(self, success: bool, **kwargs):
     """初始化回调"""
     logger.info("success:", success, "kwargs:", kwargs, caller=self)
Example #24
0
 def stop(self) -> None:
     """Stop the event loop."""
     logger.info("stop io loop.", caller=self)
     # TODO: clean up running coroutine
     self.loop.stop()