示例#1
0
    async def _auth_success_callback(self):
        # Get current open orders.
        success, 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 success["data"]:
            data = {
                "order-id":
                order_info["id"],
                "order-type":
                order_info["type"],
                "order-state":
                order_info["state"],
                "unfilled-amount":
                float(order_info["amount"]) -
                float(order_info["filled-amount"]),
                "order-price":
                float(order_info["price"]),
                "price":
                float(order_info["price"]),
                "order-amount":
                float(order_info["amount"]),
                "created-at":
                order_info["created-at"],
                "utime":
                order_info["created-at"],
            }
            self._update_order(data)

        # Subscript order channel.
        params = {"op": "sub", "topic": self._order_channel}
        await self._ws.send(params)
示例#2
0
 async def _check_connection(self, *args, **kwargs) -> None:
     """Check Websocket connection, if connection closed, re-connect immediately."""
     if not self.ws:
         logger.warn("Websocket connection not connected yet!", caller=self)
         return
     if self.ws.closed:
         SingleTask.run(self.reconnect)
示例#3
0
    def _update_order(self, order_info):
        """Order update.

        Args:
            order_info: Order information.

        Returns:
            None.
        """
        order_id = str(order_info["order_id"])
        state = order_info["state"]
        remain = float(order_info["size"]) - float(order_info["filled_size"])
        avg_price = order_info.get("last_fill_px")
        ctime = tools.utctime_str_to_ms(order_info["ctime"])
        utime = tools.utctime_str_to_ms(order_info["utime"])

        if state == "-2":
            status = ORDER_STATUS_FAILED
        elif state == "-1":
            status = ORDER_STATUS_CANCELED
        elif state == "0":
            status = ORDER_STATUS_SUBMITTED
        elif state == "1":
            status = ORDER_STATUS_PARTIAL_FILLED
        elif state == "2":
            status = ORDER_STATUS_FILLED
        else:
            logger.error("status error! order_info:", order_info, caller=self)
            SingleTask.run(self._error_callback, "order status error.")
            return None

        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": order_info["client_oid"],
                "action": ORDER_ACTION_BUY
                if order_info["side"] == "buy" else ORDER_ACTION_SELL,
                "symbol": self._symbol,
                "price": order_info["price"],
                "quantity": order_info["size"]
            }
            order = Order(**info)
            self._orders[order_id] = order
        order.remain = remain
        order.status = status
        order.avg_price = avg_price if avg_price else 0
        order.ctime = ctime
        order.utime = utime

        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)
示例#4
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)
示例#5
0
    def __init__(self, **kwargs):
        """Initialize."""
        e = None
        if not kwargs.get("account"):
            e = Error("param account miss")
        if not kwargs.get("strategy"):
            e = Error("param strategy miss")
        if not kwargs.get("symbol"):
            e = Error("param symbol miss")
        if not kwargs.get("host"):
            kwargs["host"] = "https://www.okex.com"
        if not kwargs.get("wss"):
            kwargs["wss"] = "wss://real.okex.com:8443"
        if not kwargs.get("access_key"):
            e = Error("param access_key miss")
        if not kwargs.get("secret_key"):
            e = Error("param secret_key miss")
        if not kwargs.get("passphrase"):
            e = Error("param passphrase miss")
        if e:
            logger.error(e, caller=self)
            SingleTask.run(kwargs["error_callback"], e)
            SingleTask.run(kwargs["init_callback"], False)
            return

        self._account = kwargs["account"]
        self._strategy = kwargs["strategy"]
        self._platform = kwargs["platform"]
        self._symbol = kwargs["symbol"]
        self._host = kwargs["host"]
        self._wss = kwargs["wss"]
        self._access_key = kwargs["access_key"]
        self._secret_key = kwargs["secret_key"]
        self._passphrase = kwargs["passphrase"]
        self._order_update_callback = kwargs.get("order_update_callback")
        self._init_callback = kwargs.get("init_callback")
        self._error_callback = kwargs.get("error_callback")

        self._raw_symbol = self._symbol.replace("/", "-")
        self._order_channel = "spot/order:{symbol}".format(
            symbol=self._raw_symbol)

        url = self._wss + "/ws/v3"
        self._ws = Websocket(url,
                             self.connected_callback,
                             process_binary_callback=self.process_binary)

        self._assets = {
        }  # Asset object. e.g. {"BTC": {"free": "1.1", "locked": "2.2", "total": "3.3"}, ... }
        self._orders = {}  # Order objects. e.g. {"order_id": Order, ... }

        # Initializing our REST API client.
        self._rest_api = OKExRestAPI(self._access_key, self._secret_key,
                                     self._passphrase, self._host)

        # Create a loop run task to send ping message to server per 5 seconds.
        LoopRunTask.register(self._send_heartbeat_msg, 5)
示例#6
0
 async def _check_connection(self, *args, **kwargs):
     if self._connected and self._channel and self._channel.is_open:
         return
     logger.error("CONNECTION LOSE! START RECONNECT RIGHT NOW!", caller=self)
     self._connected = False
     self._protocol = None
     self._channel = None
     self._event_handler = {}
     SingleTask.run(self.connect, reconnect=True)
示例#7
0
    def subscribe(self, callback, multi=False):
        """Subscribe a event.

        Args:
            callback: Asynchronous callback function.
            multi: If subscribe multiple channels?
        """
        from aioquant import quant
        self._callback = callback
        SingleTask.run(quant.event_center.subscribe, self, self.callback, multi)
    def __init__(self) -> None:
        host = "https://api.binance.com"
        access_key = "access_key"
        secret_key = "secret_key"

        self._rest_api = BinanceRestAPI(host, access_key, secret_key)

        self.symbol = "EOSUSDT"

        SingleTask.run(self.get_orderbook)
示例#9
0
 async def _on_consume_event_msg(self, channel, body, envelope, properties):
     try:
         key = "{exchange}:{routing_key}".format(exchange=envelope.exchange_name, routing_key=envelope.routing_key)
         funcs = self._event_handler[key]
         for func in funcs:
             SingleTask.run(func, channel, body, envelope, properties)
     except:
         logger.error("event handle error! body:", body, caller=self)
         return
     finally:
         await self._channel.basic_client_ack(delivery_tag=envelope.delivery_tag)  # response ack
示例#10
0
 async def get_open_order_ids(self):
     """Get open order id list.
     """
     success, error = await self._rest_api.get_open_orders(self._raw_symbol)
     if error:
         SingleTask.run(self._error_callback, error)
         return None, error
     else:
         order_ids = []
         for order_info in success:
             order_id = str(order_info["orderId"])
             order_ids.append(order_id)
         return order_ids, None
示例#11
0
    def __init__(self, **kwargs):
        """Initialize Trade module."""
        e = None
        if not kwargs.get("account"):
            e = Error("param account miss")
        if not kwargs.get("strategy"):
            e = Error("param strategy miss")
        if not kwargs.get("symbol"):
            e = Error("param symbol miss")
        if not kwargs.get("host"):
            kwargs["host"] = "https://api.huobi.pro"
        if not kwargs.get("wss"):
            kwargs["wss"] = "wss://api.huobi.pro"
        if not kwargs.get("access_key"):
            e = Error("param access_key miss")
        if not kwargs.get("secret_key"):
            e = Error("param secret_key miss")
        if e:
            logger.error(e, caller=self)
            SingleTask.run(self._error_callback, e)
            SingleTask.run(kwargs["init_callback"], False)
            return

        self._account = kwargs["account"]
        self._strategy = kwargs["strategy"]
        self._platform = kwargs["platform"]
        self._symbol = kwargs["symbol"]
        self._host = kwargs["host"]
        self._wss = kwargs["wss"]
        self._access_key = kwargs["access_key"]
        self._secret_key = kwargs["secret_key"]
        self._order_update_callback = kwargs.get("order_update_callback")
        self._init_callback = kwargs.get("init_callback")
        self._error_callback = kwargs.get("error_callback")

        self._raw_symbol = self._symbol.replace("/", "").lower()
        self._order_channel = "orders.{}".format(self._raw_symbol)
        self._assets = {}
        self._orders = {}

        # Initialize our REST API client.
        self._rest_api = HuobiRestAPI(
            self._access_key,
            self._secret_key,
            self._host,
        )

        url = self._wss + "/ws/v1"
        self._ws = Websocket(url,
                             self.connected_callback,
                             process_binary_callback=self.process_binary)
示例#12
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)
示例#13
0
 async def _init_websocket(self):
     """Initialize Websocket connection."""
     # Get listen key first.
     success, error = await self._rest_api.get_listen_key()
     if error:
         e = Error("get listen key failed: {}".format(error))
         logger.error(e, caller=self)
         SingleTask.run(self._error_callback, e)
         SingleTask.run(self._init_callback, False)
         return
     self._listen_key = success["listenKey"]
     uri = "/ws/" + self._listen_key
     url = urljoin(self._wss, uri)
     self._ws = Websocket(url, self.connected_callback, process_callback=self.process)
示例#14
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)
示例#15
0
    def __init__(self,
                 strategy=None,
                 platform=None,
                 symbol=None,
                 host=None,
                 wss=None,
                 account=None,
                 access_key=None,
                 secret_key=None,
                 passphrase=None,
                 order_update_callback=None,
                 position_update_callback=None,
                 init_callback=None,
                 error_callback=None,
                 **kwargs):
        """Initialize trade object."""
        kwargs["strategy"] = strategy
        kwargs["platform"] = platform
        kwargs["symbol"] = symbol
        kwargs["host"] = host
        kwargs["wss"] = wss
        kwargs["account"] = account
        kwargs["access_key"] = access_key
        kwargs["secret_key"] = secret_key
        kwargs["passphrase"] = passphrase
        kwargs["order_update_callback"] = self._on_order_update_callback
        kwargs["position_update_callback"] = self._on_position_update_callback
        kwargs["init_callback"] = self._on_init_callback
        kwargs["error_callback"] = self._on_error_callback

        self._raw_params = copy.copy(kwargs)
        self._order_update_callback = order_update_callback
        self._position_update_callback = position_update_callback
        self._init_callback = init_callback
        self._error_callback = error_callback

        if platform == const.BINANCE:
            from aioquant.platform.binance import BinanceTrade as T
        elif platform == const.HUOBI:
            from aioquant.platform.huobi import HuobiTrade as T
        elif platform == const.OKEX:
            from aioquant.platform.okex import OKExTrade as T
        else:
            logger.error("platform error:", platform, caller=self)
            e = Error("platform error")
            SingleTask.run(self._on_error_callback, e)
            SingleTask.run(self._on_init_callback, False)
            return
        self._t = T(**kwargs)
示例#16
0
    def __init__(self,
                 url,
                 connected_callback=None,
                 process_callback=None,
                 process_binary_callback=None,
                 check_conn_interval=10):
        """Initialize."""
        self._url = url
        self._connected_callback = connected_callback
        self._process_callback = process_callback
        self._process_binary_callback = process_binary_callback
        self._check_conn_interval = check_conn_interval
        self._ws = None  # Websocket connection object.

        LoopRunTask.register(self._check_connection, self._check_conn_interval)
        SingleTask.run(self._connect)
示例#17
0
    async def revoke_order(self, *order_ids):
        """Revoke (an) order(s).

        Args:
            order_ids: Order id list, you can set this param to 0 or multiple items. If you set 0 param, you can cancel
                all orders for this symbol(initialized in Trade object). If you set 1 param, you can cancel an order.
                If you set multiple param, you can cancel multiple orders. Do not set param length more than 100.

        Returns:
            Success or error, see bellow.

        NOTEs:
            DO NOT INPUT MORE THAT 10 ORDER IDs, you can invoke many times.
        """
        # If len(order_ids) == 0, you will cancel all orders for this symbol(initialized in Trade object).
        if len(order_ids) == 0:
            order_infos, error = await self._rest_api.get_open_orders(
                self._raw_symbol)
            if error:
                SingleTask.run(self._error_callback, error)
                return False, error
            if len(order_infos) > 100:
                logger.warn("order length too long! (more than 100)",
                            caller=self)
            for order_info in order_infos:
                order_id = order_info["order_id"]
                _, error = await self._rest_api.revoke_order(
                    self._raw_symbol, order_id)
                if error:
                    SingleTask.run(self._error_callback, error)
                    return False, error
            return True, None

        # If len(order_ids) == 1, you will cancel an order.
        if len(order_ids) == 1:
            success, error = await self._rest_api.revoke_order(
                self._raw_symbol, order_ids[0])
            if error:
                SingleTask.run(self._error_callback, error)
                return order_ids[0], error
            else:
                return order_ids[0], None

        # If len(order_ids) > 1, you will cancel multiple orders.
        if len(order_ids) > 1:
            success, error = [], []
            for order_id in order_ids:
                _, e = await self._rest_api.revoke_order(
                    self._raw_symbol, order_id)
                if e:
                    SingleTask.run(self._error_callback, e)
                    error.append((order_id, e))
                else:
                    success.append(order_id)
            return success, error
示例#18
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)
示例#19
0
    async def create_order(self, action, price, quantity, *args, **kwargs):
        """Create an order.

        Args:
            action: Trade direction, `BUY` or `SELL`.
            price: Price of each order.
            quantity: The buying or selling quantity.

        Returns:
            order_id: Order id if created successfully, otherwise it's None.
            error: Error information, otherwise it's None.
        """
        client_order_id = kwargs["client_order_id"]
        result, error = await self._rest_api.create_order(action, self._raw_symbol, price, quantity, client_order_id)
        if error:
            SingleTask.run(self._error_callback, error)
            return None, error
        order_id = str(result["orderId"])
        return order_id, None
示例#20
0
    async def create_order(self, action, price, quantity, *args, **kwargs):
        """Create an order.

        Args:
            action: Trade direction, `BUY` or `SELL`.
            price: Price of each order.
            quantity: The buying or selling quantity.
            kwargs:
                order_type: Order type, `LIMIT` / `MARKET`, default is `LIMIT`.

        Returns:
            order_id: Order id if created successfully, otherwise it's None.
            error: Error information, otherwise it's None.
        """
        order_type = kwargs.get("order_type", ORDER_TYPE_LIMIT)
        client_order_id = kwargs.get("client_order_id")
        if action == ORDER_ACTION_BUY:
            if order_type == ORDER_TYPE_LIMIT:
                t = "buy-limit"
            elif order_type == ORDER_TYPE_MARKET:
                t = "buy-market"
            else:
                e = Error(
                    "order_type error! order_type: {}".format(order_type))
                logger.error(e, caller=self)
                SingleTask.run(self._error_callback, e)
                return None, "order type error"
        elif action == ORDER_ACTION_SELL:
            if order_type == ORDER_TYPE_LIMIT:
                t = "sell-limit"
            elif order_type == ORDER_TYPE_MARKET:
                t = "sell-market"
            else:
                e = Error(
                    "order_type error! order_type:: {}".format(order_type))
                logger.error(e, caller=self)
                SingleTask.run(self._error_callback, e)
                return None, "order type error"
        else:
            logger.error("action error! action:", action, caller=self)
            e = Error("action error! action:: {}".format(action))
            logger.error(e, caller=self)
            SingleTask.run(self._error_callback, e)
            return None, "action error"
        result, error = await self._rest_api.create_order(
            self._raw_symbol, price, quantity, t, client_order_id)
        if error:
            SingleTask.run(self._error_callback, error)
            return None, error
        order_id = result["data"]
        return order_id, None
示例#21
0
    async def on_event_orderbook_update(self, orderbook: Orderbook):
        """订单薄更新回调"""

        if orderbook.platform == config.A["platform"] and orderbook.symbol == config.A["symbol"]:
            self._a_orderbook_ok = True
            self._a_orderbook = orderbook
        elif orderbook.platform == config.B["platform"] and orderbook.symbol == config.B["symbol"]:
            self._b_orderbook_ok = True
            self._b_orderbook = orderbook
        elif orderbook.platform == config.C["platform"] and orderbook.symbol == config.C["symbol"]:
            self._c_orderbook_ok = True
            self._c_orderbook = orderbook

        # 判断maker和taker订单薄是否准备就绪
        if not self._a_orderbook_ok or not self._b_orderbook_ok or not self._c_orderbook_ok:
            logger.warn("orderbook not ok.", caller=self)
            return

        # A同时进行买入和卖出ETH的检查
        SingleTask.run(self.a_do_action_buy)
        SingleTask.run(self.a_do_action_sell)
示例#22
0
    async def get_open_order_ids(self):
        """Get open order id list.

        Args:
            None.

        Returns:
            order_ids: Open order id list, otherwise it's None.
            error: Error information, otherwise it's None.
        """
        success, error = await self._rest_api.get_open_orders(self._raw_symbol)
        if error:
            SingleTask.run(self._error_callback, error)
            return None, error
        else:
            if len(success) > 100:
                logger.warn("order length too long! (more than 100)",
                            caller=self)
            order_ids = []
            for order_info in success:
                order_ids.append(order_info["order_id"])
            return order_ids, None
示例#23
0
    async def create_order(self, action, price, quantity, *args, **kwargs):
        """Create an order.

        Args:
            action: Trade direction, `BUY` or `SELL`.
            price: Price of each order.
            quantity: The buying or selling quantity.

        Returns:
            order_id: Order id if created successfully, otherwise it's None.
            error: Error information, otherwise it's None.
        """
        order_type = kwargs.get("order_type", ORDER_TYPE_LIMIT)
        client_order_id = kwargs.get("client_order_id")
        result, error = await self._rest_api.create_order(
            action, self._raw_symbol, price, quantity, order_type,
            client_order_id)
        if error:
            SingleTask.run(self._error_callback, error)
            return None, error
        if not result["result"]:
            SingleTask.run(self._error_callback, result)
            return None, result
        return result["order_id"], None
示例#24
0
    def __init__(self, **kwargs):
        """Initialize Trade module."""
        e = None
        if not kwargs.get("account"):
            e = Error("param account miss")
        if not kwargs.get("strategy"):
            e = Error("param strategy miss")
        if not kwargs.get("symbol"):
            e = Error("param symbol miss")
        if not kwargs.get("host"):
            kwargs["host"] = "https://api.binance.com"
        if not kwargs.get("wss"):
            kwargs["wss"] = "wss://stream.binance.com:9443"
        if not kwargs.get("access_key"):
            e = Error("param access_key miss")
        if not kwargs.get("secret_key"):
            e = Error("param secret_key miss")
        if e:
            logger.error(e, caller=self)
            SingleTask.run(kwargs["error_callback"], e)
            SingleTask.run(kwargs["init_callback"], False)

        self._account = kwargs["account"]
        self._strategy = kwargs["strategy"]
        self._platform = kwargs["platform"]
        self._symbol = kwargs["symbol"]
        self._host = kwargs["host"]
        self._wss = kwargs["wss"]
        self._access_key = kwargs["access_key"]
        self._secret_key = kwargs["secret_key"]
        self._order_update_callback = kwargs.get("order_update_callback")
        self._init_callback = kwargs.get("init_callback")
        self._error_callback = kwargs.get("error_callback")

        self._raw_symbol = self._symbol.replace(
            "/", "")  # Row symbol name, same as Binance Exchange.
        self._listen_key = None  # Listen key for Websocket authentication.
        self._assets = {
        }  # Asset data. e.g. {"BTC": {"free": "1.1", "locked": "2.2", "total": "3.3"}, ... }
        self._orders = {}  # Order data. e.g. {order_id: order, ... }

        # Initialize our REST API client.
        self._rest_api = BinanceRestAPI(self._access_key, self._secret_key,
                                        self._host)

        # Create a loop run task to reset listen key every 30 minutes.
        LoopRunTask.register(self._reset_listen_key, 60 * 30)

        # Create a coroutine to initialize Websocket connection.
        SingleTask.run(self._init_websocket)

        LoopRunTask.register(self._send_heartbeat_msg, 10)
示例#25
0
 async def _receive(self):
     """Receive stream message from Websocket connection."""
     async for msg in self.ws:
         if msg.type == aiohttp.WSMsgType.TEXT:
             if self._process_callback:
                 try:
                     data = json.loads(msg.data)
                 except:
                     data = msg.data
                 SingleTask.run(self._process_callback, data)
         elif msg.type == aiohttp.WSMsgType.BINARY:
             if self._process_binary_callback:
                 SingleTask.run(self._process_binary_callback, msg.data)
         elif msg.type == aiohttp.WSMsgType.CLOSED:
             logger.warn("receive event CLOSED:", msg, caller=self)
             SingleTask.run(self.reconnect)
         elif msg.type == aiohttp.WSMsgType.ERROR:
             logger.error("receive event ERROR:", msg, caller=self)
         else:
             logger.warn("unhandled msg:", msg, caller=self)
示例#26
0
 def publish(self):
     """Publish a event."""
     from aioquant import quant
     SingleTask.run(quant.event_center.publish, self)
示例#27
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)
示例#28
0
 def _bind_and_consume(self):
     async def do_them():
         for event, callback, multi in self._subscribers:
             await self._initialize(event, callback, multi)
     SingleTask.run(do_them)
示例#29
0
    def _update_order(self, order_info):
        """Order update.

        Args:
            order_info: Order information.

        Returns:
            None.
        Note:
            order-state: Order status, `submitting` / `submitted` / `partial-filled` / `partial-canceled` / `filled` / `canceled`
        """
        order_id = str(order_info["order-id"])
        action = ORDER_ACTION_BUY if order_info["order-type"] in [
            "buy-market", "buy-limit"
        ] else ORDER_ACTION_SELL
        state = order_info["order-state"]
        remain = "%.8f" % float(order_info["unfilled-amount"])
        avg_price = "%.8f" % float(order_info["price"])
        ctime = order_info["created-at"]
        utime = order_info["utime"]

        if state == "canceled":
            status = ORDER_STATUS_CANCELED
        elif state == "partial-canceled":
            status = ORDER_STATUS_CANCELED
        elif state == "submitting":
            status = ORDER_STATUS_SUBMITTED
        elif state == "submitted":
            status = ORDER_STATUS_SUBMITTED
        elif state == "partial-filled":
            status = ORDER_STATUS_PARTIAL_FILLED
        elif state == "filled":
            status = ORDER_STATUS_FILLED
        else:
            e = Error("status error! order_info: {}".format(order_info))
            logger.error(e, caller=self)
            SingleTask.run(self._error_callback, e)
            return None

        order = self._orders.get(order_id)
        if not order:
            info = {
                "platform": self._platform,
                "account": self._account,
                "strategy": self._strategy,
                "order_id": order_id,
                "action": action,
                "symbol": self._symbol,
                "price": "%.8f" % float(order_info["order-price"]),
                "quantity": "%.8f" % float(order_info["order-amount"]),
                "remain": remain,
                "status": status
            }
            order = Order(**info)
            self._orders[order_id] = order
        order.remain = remain
        order.status = status
        order.avg_price = avg_price
        order.ctime = ctime
        order.utime = utime

        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)