예제 #1
0
 async def _initialize(self):
     """ 初始化
     """
     # 获取当前所有未完全成交的订单
     order_nos, error = await self._rest_api.get_open_order_nos(
         self._raw_symbol)
     if error:
         e = Error("get open order nos failed: {}".format(error))
         logger.error(e, caller=self)
         if self._init_success_callback:
             SingleTask.run(self._init_success_callback, False, e)
         return
     if order_nos:
         success, error = await self._rest_api.get_order_list(order_nos)
         if error:
             e = Error("get order infos failed: {}".format(error))
             logger.error(e, caller=self)
             if self._init_success_callback:
                 SingleTask.run(self._init_success_callback, False, e)
             return
         for order_info in success:
             await self._update_order(order_info)
     if self._init_success_callback:
         SingleTask.run(self._init_success_callback, True, None)
예제 #2
0
    async def process_binary(self, raw):
        """ 处理websocket上接收到的消息
        @param raw 原始的压缩数据
        """
        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._init_success_callback, False, e)
                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._init_success_callback, False, e)
            else:
                SingleTask.run(self._init_success_callback, True, None)
        elif op == "notify":  # 订单更新通知
            if msg["topic"] != self._order_channel:
                return
            data = msg["data"]
            data["utime"] = msg["ts"]
            self._update_order(data)
예제 #3
0
    def __init__(self, **kwargs):
        """ 初始化
        """
        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:10442"
        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)
            if kwargs.get("init_success_callback"):
                SingleTask.run(kwargs["init_success_callback"], False, e)
            return

        self._account = kwargs["account"]
        self._strategy = kwargs["strategy"]
        self._platform = OKEX_FUTURE
        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._asset_update_callback = kwargs.get("asset_update_callback")
        self._order_update_callback = kwargs.get("order_update_callback")
        self._position_update_callback = kwargs.get("position_update_callback")
        self._init_success_callback = kwargs.get("init_success_callback")

        url = self._wss + "/ws/v3"
        super(OKExFutureTrade, self).__init__(url, send_hb_interval=5)
        self.heartbeat_msg = "ping"

        self._orders = {}  # 订单
        self._position = Position(self._platform, self._account,
                                  self._strategy, self._symbol)  # 仓位

        # 订阅频道
        # ch_account = "futures/account:BTC"
        self._order_channel = "futures/order:{symbol}".format(
            symbol=self._symbol)
        self._position_channel = "futures/position:{symbol}".format(
            symbol=self._symbol)

        # 标记订阅订单、持仓是否成功
        self._subscribe_order_ok = False
        self._subscribe_position_ok = False

        # 初始化 REST API 对象
        self._rest_api = OKExFutureRestAPI(self._host, self._access_key,
                                           self._secret_key, self._passphrase)

        self.initialize()
예제 #4
0
    def __init__(self, **kwargs):
        """ 初始化
        """
        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.bitmex.com"
        if not kwargs.get("wss"):
            kwargs["wss"] = "wss://www.bitmex.com"
        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)
            if kwargs.get("init_success_callback"):
                SingleTask.run(kwargs["init_success_callback"], False, e)
            return

        self._account = kwargs["account"]
        self._strategy = kwargs["strategy"]
        self._platform = BITMEX
        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._asset_update_callback = kwargs.get("asset_update_callback")
        self._order_update_callback = kwargs.get("order_update_callback")
        self._position_update_callback = kwargs.get("position_update_callback")
        self._init_success_callback = kwargs.get("init_success_callback")

        url = self._wss + "/realtime"
        super(BitmexTrade, self).__init__(url, send_hb_interval=5)
        self.heartbeat_msg = "ping"

        self._order_channel = "order:{symbol}".format(
            symbol=self._symbol)  # 订单订阅频道
        self._position_channel = "position:{symbol}".format(
            symbol=self._symbol)  # 持仓订阅频道

        # 标记订阅订单、持仓是否成功
        self._subscribe_order_ok = False
        self._subscribe_position_ok = False

        self._assets = {
        }  # 资产 {"XBT": {"free": "1.1", "locked": "2.2", "total": "3.3"}, ... }
        self._orders = {}
        self._position = Position(self._platform, self._account,
                                  self._strategy, self._symbol)  # 仓位

        # 初始化REST API对象
        self._rest_api = BitmexAPI(self._host, self._access_key,
                                   self._secret_key)

        # 初始化资产订阅
        if self._asset_update_callback:
            AssetSubscribe(self._platform, self._account,
                           self.on_event_asset_update)

        self.initialize()
예제 #5
0
 def publish(self):
     """ 发布此事件
     """
     from quant.quant import quant
     SingleTask.run(quant.handle_event_center.publish, self)
예제 #6
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))
            if self._init_success_callback:
                SingleTask.run(self._init_success_callback, False, e)
            return
        for order_info in order_infos:
            order_no = "{}_{}".format(order_info["orderId"],
                                      order_info["clientOrderId"])
            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)
                continue

            info = {
                "platform":
                self._platform,
                "account":
                self._account,
                "strategy":
                self._strategy,
                "order_no":
                order_no,
                "action":
                order_info["side"],
                "order_type":
                order_info["type"],
                "symbol":
                self._symbol,
                "price":
                order_info["price"],
                "quantity":
                order_info["origQty"],
                "remain":
                float(order_info["origQty"]) -
                float(order_info["executedQty"]),
                "status":
                status,
                "ctime":
                order_info["time"],
                "utime":
                order_info["updateTime"]
            }
            order = Order(**info)
            self._orders[order_no] = order
            if self._order_update_callback:
                SingleTask.run(self._order_update_callback, copy.copy(order))

        if self._init_success_callback:
            SingleTask.run(self._init_success_callback, True, None)
예제 #7
0
    def _update_order(self, order_info):
        """ Order update.

        Args:
            order_info: Order information.

        Returns:
            None.
        """
        order_no = str(order_info["order_id"])
        state = order_info["state"]
        remain = int(order_info["size"]) - int(order_info["filled_qty"])
        ctime = tools.utctime_str_to_mts(order_info["timestamp"])
        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:
            return None

        order = self._orders.get(order_no)
        if not order:
            info = {
                "platform":
                self._platform,
                "account":
                self._account,
                "strategy":
                self._strategy,
                "order_no":
                order_no,
                "client_order_id":
                order_info["client_oid"],
                "action":
                ORDER_ACTION_BUY
                if order_info["type"] in ["1", "4"] else ORDER_ACTION_SELL,
                "symbol":
                self._symbol,
                "price":
                order_info["price"],
                "quantity":
                order_info["size"],
                "trade_type":
                int(order_info["type"])
            }
            order = Order(**info)
        order.remain = remain
        order.status = status
        order.avg_price = order_info["price_avg"]
        order.ctime = ctime
        order.utime = ctime
        self._orders[order_no] = order

        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_no)
예제 #8
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)
            if kwargs.get("init_success_callback"):
                SingleTask.run(kwargs["init_success_callback"], False, e)
            return

        self._account = kwargs["account"]
        self._strategy = kwargs["strategy"]
        self._platform = OKEX_FUTURE
        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._asset_update_callback = kwargs.get("asset_update_callback")
        self._order_update_callback = kwargs.get("order_update_callback")
        self._position_update_callback = kwargs.get("position_update_callback")
        self._init_success_callback = kwargs.get("init_success_callback")

        url = self._wss + "/ws/v3"
        super(OKExFutureTrade, self).__init__(url, send_hb_interval=5)
        self.heartbeat_msg = "ping"

        self._assets = {
        }  # Asset object. e.g. {"BTC": {"free": "1.1", "locked": "2.2", "total": "3.3"}, ... }
        self._orders = {}  # Order objects. e.g. {"order_no": Order, ... }
        self._position = Position(self._platform, self._account,
                                  self._strategy, self._symbol)

        # Subscribing our channels.
        self._order_channel = "futures/order:{symbol}".format(
            symbol=self._symbol)
        self._position_channel = "futures/position:{symbol}".format(
            symbol=self._symbol)

        # If our channels that subscribed successfully.
        self._subscribe_order_ok = False
        self._subscribe_position_ok = False

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

        # Subscribing our asset event.
        if self._asset_update_callback:
            AssetSubscribe(self._platform, self._account,
                           self.on_event_asset_update)

        self.initialize()
예제 #9
0
    async def _update_order(self, order_info):
        """ 处理委托单更新
        @param order_info 委托单详情
        """
        if not order_info:
            return
        status_updated = False
        order_no = str(order_info["orderNo"])
        state = order_info["state"]

        order = self._orders.get(order_no)
        if not order:
            info = {
                "platform": self._platform,
                "account": self._account,
                "strategy": self._strategy,
                "order_no": order_no,
                "action": order_info["action"],
                "symbol": self._symbol,
                "price": order_info["priceLimit"],
                "quantity": order_info["quantity"],
                "remain": order_info["quantityRemaining"],
                "avg_price": order_info["priceLimit"]
            }
            order = Order(**info)
            self._orders[order_no] = order

        # 已提交
        if state == "UNDEAL" or state == "PROCESSING":
            if order.status != ORDER_STATUS_SUBMITTED:
                order.status = ORDER_STATUS_SUBMITTED
                status_updated = True
        # 订单部分成交
        elif state == "PARTDEAL":
            order.status = ORDER_STATUS_PARTIAL_FILLED
            if order.order_type == ORDER_TYPE_LIMIT:
                if float(order.remain) != float(order_info["quantityRemaining"]):
                    status_updated = True
                    order.remain = float(order_info["quantityRemaining"])
            else:
                if float(order.remain) != float(order_info["amountRemaining"]):
                    status_updated = True
                    order.remain = float(order_info["amountRemaining"])
        # 订单成交完成
        elif state == "DEAL":
            order.status = ORDER_STATUS_FILLED
            order.remain = 0
            status_updated = True
        # 订单取消
        elif state == "CANCEL":
            order.status = ORDER_STATUS_CANCELED
            if order.order_type == ORDER_TYPE_LIMIT:
                if float(order.remain) != float(order_info["quantityRemaining"]):
                    order.remain = float(order_info["quantityRemaining"])
            else:
                if float(order.remain) != float(order_info["amountRemaining"]):
                    order.remain = float(order_info["amountRemaining"])
            status_updated = True
        else:
            logger.warn("state error! order_info:", order_info, caller=self)
            return

        # 有状态更新 执行回调
        if status_updated:
            order.ctime = order_info["utcCreate"]
            order.utime = order_info["utcUpdate"]
            if self._order_update_callback:
                SingleTask.run(self._order_update_callback, copy.copy(order))

        # 删除已完成订单
        if order.status in [ORDER_STATUS_FAILED, ORDER_STATUS_CANCELED, ORDER_STATUS_FILLED]:
            self._orders.pop(order_no)
예제 #10
0
 async def on_event_update_orderbook(self, *args, **kwargs):
     """ Loop run to fetch orderbook information.
     """
     for symbol in self._symbols:
         SingleTask.run(self.get_newest_orderbook, symbol)
예제 #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://fapi.binance.com"
        if not kwargs.get("wss"):
            kwargs["wss"] = "wss://fstream.binance.com"
        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)
            if kwargs.get("init_success_callback"):
                SingleTask.run(kwargs["init_success_callback"], False, e)
            return

        self._account = kwargs["account"]
        self._strategy = kwargs["strategy"]
        self._platform = BINANCE_FUTURE
        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._asset_update_callback = kwargs.get("asset_update_callback")
        self._order_update_callback = kwargs.get("order_update_callback")
        self._position_update_callback = kwargs.get("position_update_callback")
        self._init_success_callback = kwargs.get("init_success_callback")

        self._ok = False  # Initialize successfully ?

        self._raw_symbol = self._symbol  # 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_no: order, ... }
        self._position = Position(self._platform, self._account,
                                  self._strategy, self._symbol)  # 仓位

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

        # Subscribe our AssetEvent.
        if self._asset_update_callback:
            AssetSubscribe(self._platform, self._account,
                           self.on_event_asset_update)

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

        # Create a loop run task to check position information per 1 second.
        LoopRunTask.register(self._check_position_update, 1)

        # Create a loop run task to send ping message to server per 30 seconds.
        # LoopRunTask.register(self._send_heartbeat_msg, 10)

        # Create a coroutine to initialize Websocket connection.
        SingleTask.run(self._init_websocket)
예제 #12
0
 def initialize(self):
     LoopRunTask.register(self._check_connection, self._check_conn_interval)
     if self._send_hb_interval > 0:
         LoopRunTask.register(self._send_heartbeat_msg, self._send_hb_interval)
     SingleTask.run(self._connect)
예제 #13
0
    def _update_order(self, order_info):
        """ 更新订单信息
        @param order_info 订单信息
        * NOTE:
            order-state: 订单状态, submitting , submitted 已提交, partial-filled 部分成交, partial-canceled 部分成交撤销,
                filled 完全成交, canceled 已撤销
        """
        order_no = 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:
            logger.error("status error! order_info:", order_info, caller=self)
            return None

        order = self._orders.get(order_no)
        if not order:
            info = {
                "platform": self._platform,
                "account": self._account,
                "strategy": self._strategy,
                "order_no": order_no,
                "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_no] = order
        order.remain = remain
        order.status = status
        order.avg_price = avg_price
        order.ctime = ctime
        order.utime = utime
        if status in [
                ORDER_STATUS_FAILED, ORDER_STATUS_CANCELED, ORDER_STATUS_FILLED
        ]:
            self._orders.pop(order_no)
        if order and self._order_update_callback:
            SingleTask.run(self._order_update_callback, copy.copy(order))
        # publish order
        EventOrder(**order.__dict__).publish()
        logger.info("symbol:", order.symbol, "order:", order, caller=self)
예제 #14
0
 def _update_asset(self, data):
     ast = self._convert_asset_format(data)
     if self.cb.on_asset_update_callback:
         SingleTask.run(self.cb.on_asset_update_callback, ast)
예제 #15
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"):
                state = State(
                    self._platform, self._account,
                    "Websocket connection authorized failed: {}".format(msg),
                    State.STATE_CODE_GENERAL_ERROR)
                logger.error(state, caller=self)
                SingleTask.run(self.cb.on_state_update_callback, state)
                return
            logger.info("Websocket connection authorized successfully.",
                        caller=self)
            await self._auth_success_callback()

        # Subscribe response message received.
        elif msg.get("event") == "subscribe":
            #msg.get("channel")
            self._subscribe_response_count = self._subscribe_response_count + 1  #每来一次订阅响应计数就加一
            count = len(self._account_channel) + len(
                self._order_channel)  #应该要返回的订阅响应数
            if self._subscribe_response_count == count:  #所有的订阅都成功了,通知上层接口都准备好了
                state = State(self._platform, self._account,
                              "Environment ready", State.STATE_CODE_READY)
                SingleTask.run(self.cb.on_state_update_callback, state)

        elif msg.get("event") == "error":
            state = State(self._platform, self._account,
                          "Websocket processing failed: {}".format(msg),
                          State.STATE_CODE_GENERAL_ERROR)
            SingleTask.run(self.cb.on_state_update_callback, state)

        # Order update message received.
        elif msg.get("table") == "spot/order":
            """
            {
            "table":"spot/order",
            "data":[
                {
                "client_oid":"",
                "filled_notional":"0",
                "filled_size":"0",
                "instrument_id":"ETC-USDT",
                "last_fill_px":"0",
                "last_fill_qty":"0",
                "last_fill_time":"1970-01-01T00:00:00.000Z",
                "margin_trading":"1",
                "notional":"",
                "order_id":"3576398568830976",
                "order_type":"0",
                "price":"5.826",
                "side":"buy",
                "size":"0.1",
                "state":"0",
                "status":"open",
                "timestamp":"2019-09-24T06:45:11.394Z",
                "type":"limit",
                "created_at":"2019-09-24T06:45:11.394Z"
                }
                ]
            }
            """
            for data in msg["data"]:
                self._update_order(data)

        elif msg.get("table") == "spot/account":
            self._update_asset(msg["data"])
예제 #16
0
    async def process_binary(self, raw):
        """ 处理websocket上接收到的消息
        @param raw 原始的压缩数据
        """
        decompress = zlib.decompressobj(-zlib.MAX_WBITS)
        msg = decompress.decompress(raw)
        msg += decompress.flush()
        msg = msg.decode()
        if msg == "pong":  # 心跳返回
            return
        msg = json.loads(msg)
        logger.debug("msg:", msg, caller=self)

        # 登陆成功之后再订阅数据
        if msg.get("event") == "login":
            if not msg.get("success"):
                e = Error(
                    "Websocket connection authorized failed: {}".format(msg))
                logger.error(e, caller=self)
                if self._init_success_callback:
                    SingleTask.run(self._init_success_callback, False, e)
                return
            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(msg))
                if self._init_success_callback:
                    SingleTask.run(self._init_success_callback, False, e)
                return
            for order_info in order_infos:
                order_info["ctime"] = order_info["created_at"]
                order_info["utime"] = order_info["timestamp"]
                order = self._update_order(order_info)
                if self._order_update_callback:
                    SingleTask.run(self._order_update_callback, order)

            # 订阅 order
            data = {"op": "subscribe", "args": [self._order_channel]}
            await self.ws.send_json(data)
            return

        # 订阅返回消息
        if msg.get("event") == "subscribe":
            if msg.get("channel") == self._order_channel:
                if self._init_success_callback:
                    SingleTask.run(self._init_success_callback, True, None)
            else:
                if self._init_success_callback:
                    e = Error("subscribe order event error: {}".format(msg))
                    SingleTask.run(self._init_success_callback, False, e)
            return

        # 订单更新
        if msg.get("table") == "spot/order":
            for data in msg["data"]:
                data["ctime"] = data["timestamp"]
                data["utime"] = data["last_fill_time"]
                order = self._update_order(data)
                if order and self._order_update_callback:
                    SingleTask.run(self._order_update_callback, order)
예제 #17
0
    def __init__(self,
                 strategy=None,
                 platform=None,
                 symbol=None,
                 host=None,
                 wss=None,
                 account=None,
                 access_key=None,
                 secret_key=None,
                 passphrase=None,
                 asset_update_callback=None,
                 order_update_callback=None,
                 position_update_callback=None,
                 init_success_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["asset_update_callback"] = asset_update_callback
        kwargs["order_update_callback"] = self._on_order_update_callback
        kwargs["position_update_callback"] = self._on_position_update_callback
        kwargs["init_success_callback"] = self._on_init_success_callback

        self._order_update_callback = order_update_callback
        self._position_update_callback = position_update_callback
        self._init_success_callback = init_success_callback

        if platform == const.OKEX:
            from quant.platform.okex import OKExTrade as T
        elif platform == const.OKEX_MARGIN:
            from quant.platform.okex_margin import OKExMarginTrade as T
        elif platform == const.OKEX_FUTURE:
            from quant.platform.okex_future import OKExFutureTrade as T
        elif platform == const.OKEX_SWAP:
            from quant.platform.okex_swap import OKExSwapTrade as T
        elif platform == const.DERIBIT:
            from quant.platform.deribit import DeribitTrade as T
        elif platform == const.BITMEX:
            from quant.platform.bitmex import BitmexTrade as T
        elif platform == const.BINANCE:
            from quant.platform.binance import BinanceTrade as T
        elif platform == const.HUOBI:
            from quant.platform.huobi import HuobiTrade as T
        elif platform == const.COINSUPER:
            from quant.platform.coinsuper import CoinsuperTrade as T
        elif platform == const.COINSUPER_PRE:
            from quant.platform.coinsuper_pre import CoinsuperPreTrade as T
        elif platform == const.KRAKEN:
            from quant.platform.kraken import KrakenTrade as T
        elif platform == const.GATE:
            from quant.platform.gate import GateTrade as T
        elif platform == const.KUCOIN:
            from quant.platform.kucoin import KucoinTrade as T
        else:
            logger.error("platform error:", platform, caller=self)
            e = Error("platform error")
            SingleTask.run(self._init_success_callback, False, e)
            return
        kwargs.pop("platform")
        self._t = T(**kwargs)
예제 #18
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("contract_type"):
            e = Error("param contract_type miss")
        if not kwargs.get("contract_code"):
            e = Error("param contract_code miss")
        if not kwargs.get("host"):
            kwargs["host"] = "https://api.hbdm.com"
        if not kwargs.get("wss"):
            kwargs["wss"] = "wss://api.hbdm.com"
        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)
            if kwargs.get("init_success_callback"):
                SingleTask.run(kwargs["init_success_callback"], False, e)
            return

        self._account = kwargs["account"]
        self._strategy = kwargs["strategy"]
        self._platform = HUOBI_FUTURE
        self._symbol = kwargs["symbol"]
        self._contract_type = kwargs["contract_type"]
        self._contract_code = kwargs["contract_code"]
        self._host = kwargs["host"]
        self._wss = kwargs["wss"]
        self._access_key = kwargs["access_key"]
        self._secret_key = kwargs["secret_key"]
        self._asset_update_callback = kwargs.get("asset_update_callback")
        self._order_update_callback = kwargs.get("order_update_callback")
        self._position_update_callback = kwargs.get("position_update_callback")
        self._init_success_callback = kwargs.get("init_success_callback")

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

        self._assets = {
        }  # Asset detail, {"BTC": {"free": "1.1", "locked": "2.2", "total": "3.3"}, ... }.
        self._orders = {}  # Order objects, {"order_id": order, ...}.
        self._position = Position(self._platform, self._account,
                                  self._strategy, self._contract_code)

        self._order_channel = "orders.{symbol}".format(
            symbol=self._symbol.lower())
        self._position_channel = "positions.{symbol}".format(
            symbol=self._symbol.lower())

        self._subscribe_order_ok = False
        self._subscribe_position_ok = False

        self._rest_api = HuobiFutureRestAPI(self._host, self._access_key,
                                            self._secret_key)

        # Subscribe AssetEvent.
        if self._asset_update_callback:
            AssetSubscribe(self._platform, self._account,
                           self.on_event_asset_update)
예제 #19
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._init_success_callback, False, e)
                return
            logger.info("Websocket connection authorized successfully.",
                        caller=self)

            # Fetch orders from server. (open + partially filled)
            result, error = await self._rest_api.get_order_list(
                self._symbol, 6)
            if error:
                e = Error("get open orders error: {}".format(error))
                SingleTask.run(self._init_success_callback, False, e)
                return
            if len(result) > 100:
                logger.warn("order length too long! (more than 100)",
                            caller=self)
            for order_info in result["order_info"]:
                self._update_order(order_info)

            # Fetch positions from server.
            position, error = await self._rest_api.get_position(self._symbol)
            if error:
                e = Error("get position error: {}".format(error))
                SingleTask.run(self._init_success_callback, False, e)
                return
            if len(position["holding"]) > 0:
                self._update_position(position["holding"][0])

            # Subscribe order channel and position channel.
            data = {
                "op": "subscribe",
                "args": [self._order_channel, self._position_channel]
            }
            await self.ws.send_json(data)
            return

        # Subscribe response message received.
        if msg.get("event") == "subscribe":
            if msg.get("channel") == self._order_channel:
                self._subscribe_order_ok = True
            if msg.get("channel") == self._position_channel:
                self._subscribe_position_ok = True
            if self._subscribe_order_ok and self._subscribe_position_ok:
                SingleTask.run(self._init_success_callback, True, None)
            return

        # Order update message received.
        if msg.get("table") == "futures/order":
            for data in msg["data"]:
                self._update_order(data)
            return

        # Position update message receive.
        if msg.get("table") == "futures/position":
            for data in msg["data"]:
                self._update_position(data)
예제 #20
0
    def _update_order(self, order_info):
        """ Order update.

        Args:
            order_info: Order information.
        """
        if order_info["contract_code"] != self._contract_code:
            return
        order_no = str(order_info["order_id"])
        status = order_info["status"]

        order = self._orders.get(order_no)
        if not order:
            if order_info["direction"] == "buy":
                if order_info["offset"] == "open":
                    trade_type = TRADE_TYPE_BUY_OPEN
                else:
                    trade_type = TRADE_TYPE_BUY_CLOSE
            else:
                if order_info["offset"] == "close":
                    trade_type = TRADE_TYPE_SELL_CLOSE
                else:
                    trade_type = TRADE_TYPE_SELL_OPEN

            info = {
                "platform":
                self._platform,
                "account":
                self._account,
                "strategy":
                self._strategy,
                "order_no":
                order_no,
                "action":
                ORDER_ACTION_BUY
                if order_info["direction"] == "buy" else ORDER_ACTION_SELL,
                "symbol":
                self._contract_code,
                "price":
                order_info["price"],
                "quantity":
                order_info["volume"],
                "trade_type":
                trade_type
            }
            order = Order(**info)
            self._orders[order_no] = order

        if status in [1, 2, 3]:
            order.status = ORDER_STATUS_SUBMITTED
        elif status == 4:
            order.status = ORDER_STATUS_PARTIAL_FILLED
            order.remain = int(order.quantity) - int(
                order_info["trade_volume"])
        elif status == 6:
            order.status = ORDER_STATUS_FILLED
            order.remain = 0
        elif status in [5, 7]:
            order.status = ORDER_STATUS_CANCELED
            order.remain = int(order.quantity) - int(
                order_info["trade_volume"])
        else:
            return

        order.avg_price = order_info["trade_avg_price"]
        order.ctime = order_info["created_at"]
        order.utime = order_info["ts"]

        SingleTask.run(self._order_update_callback, copy.copy(order))

        # Delete order that already completed.
        if order.status in [
                ORDER_STATUS_FAILED, ORDER_STATUS_CANCELED, ORDER_STATUS_FILLED
        ]:
            self._orders.pop(order_no)
예제 #21
0
    async def _update_order(self, order_info):
        """ Update order object.

        Args:
            order_info: Order information.
        """
        if not order_info:
            return
        status_updated = False
        order_no = str(order_info["orderNo"])
        state = order_info["state"]

        order = self._orders.get(order_no)
        if not order:
            info = {
                "platform": self._platform,
                "account": self._account,
                "strategy": self._strategy,
                "order_no": order_no,
                "action": order_info["action"],
                "symbol": self._symbol,
                "price": order_info["priceLimit"],
                "quantity": order_info["quantity"],
                "remain": order_info["quantityRemaining"],
                "avg_price": order_info["priceLimit"]
            }
            order = Order(**info)
            self._orders[order_no] = order

        if state == "UNDEAL" or state == "PROCESSING":
            if order.status != ORDER_STATUS_SUBMITTED:
                order.status = ORDER_STATUS_SUBMITTED
                status_updated = True
        elif state == "PARTDEAL":
            order.status = ORDER_STATUS_PARTIAL_FILLED
            if order.order_type == ORDER_TYPE_LIMIT:
                if float(order.remain) != float(
                        order_info["quantityRemaining"]):
                    status_updated = True
                    order.remain = float(order_info["quantityRemaining"])
            else:
                if float(order.remain) != float(order_info["amountRemaining"]):
                    status_updated = True
                    order.remain = float(order_info["amountRemaining"])
        elif state == "DEAL":
            order.status = ORDER_STATUS_FILLED
            order.remain = 0
            status_updated = True
        elif state == "CANCEL":
            order.status = ORDER_STATUS_CANCELED
            status_updated = True
        else:
            logger.warn("state error! order_info:", order_info, caller=self)
            return

        # If order status updated, callback newest order information.
        if status_updated:
            order.ctime = order_info["utcCreate"]
            order.utime = order_info["utcUpdate"]
            if self._order_update_callback:
                SingleTask.run(self._order_update_callback, copy.copy(order))

        # Delete order that already completed.
        if order.status in [
                ORDER_STATUS_FAILED, ORDER_STATUS_CANCELED, ORDER_STATUS_FILLED
        ]:
            self._orders.pop(order_no)
예제 #22
0
    async def _update_order(self, order_info):
        """ Update order object.

        Args:
            order_info: Order information.
        """
        if not order_info:
            return
        status_updated = False
        order_no = str(order_info["orderNumber"])
        state = order_info["status"]

        order = self._orders.get(order_no)
        if not order:
            info = {
                "platform": self._platform,
                "account": self._account,
                "strategy": self._strategy,
                "order_no": order_no,
                "action": ORDER_ACTION_BUY
                if order_info["type"] == "buy" else ORDER_ACTION_SELL,
                "symbol": self._symbol,
                "price": order_info["rate"],
                "quantity": order_info["amount"],
                "remain": order_info["amount"],
                "avg_price": order_info["filledRate"]
            }
            order = Order(**info)
            self._orders[order_no] = order

        if state == "open":
            filled_amount = float(order_info["filledAmount"])
            if filled_amount == 0:
                state = ORDER_STATUS_SUBMITTED
                if order.status != state:
                    order.status = ORDER_STATUS_SUBMITTED
                    status_updated = True
            else:
                remain = float(order.quantity) - filled_amount
                if order.remain != remain:
                    order.status = ORDER_STATUS_PARTIAL_FILLED
                    order.remain = remain
                    status_updated = True
        elif state == "closed":
            order.status = ORDER_STATUS_FILLED
            order.remain = 0
            status_updated = True
        elif state == "cancelled":
            order.status = ORDER_STATUS_CANCELED
            status_updated = True
        else:
            logger.warn("state error! order_info:", order_info, caller=self)
            return

        if status_updated:
            order.avg_price = order_info["filledRate"]
            order.ctime = int(order_info["timestamp"] * 1000)
            order.utime = int(order_info["timestamp"] * 1000)
            if self._order_update_callback:
                SingleTask.run(self._order_update_callback, copy.copy(order))

        # Delete order that already completed.
        if order.status in [
                ORDER_STATUS_FAILED, ORDER_STATUS_CANCELED, ORDER_STATUS_FILLED
        ]:
            self._orders.pop(order_no)
예제 #23
0
 def publish(self):
     """Publish this event."""
     from quant.quant import quant
     SingleTask.run(quant.event_center.publish, self)
예제 #24
0
    async def _update_order(self, order_info):
        """ Update order object.

        Args:
            order_info: Order information.
        """
        if not order_info:
            return
        status_updated = False
        order_no = str(order_info["order_id"])
        status = order_info[
            "status"]  # 订单状态,0-未成交,1-部分成交,2-完全成交,3-已撤销未成交,4-已撤销部分成交

        order = self._orders.get(order_no)
        if not order:
            info = {
                "platform": self._platform,
                "account": self._account,
                "strategy": self._strategy,
                "order_no": order_no,
                "action": ORDER_ACTION_BUY
                if order_info["type"] == "buy" else ORDER_ACTION_SELL,
                "symbol": self._symbol,
                "price": order_info["price"],
                "quantity": order_info["amount"],
                "remain": order_info["amount"],
                "avg_price": order_info["avg_price"]
            }
            order = Order(**info)
            self._orders[order_no] = order

        if status == 0:
            if order.status != ORDER_STATUS_SUBMITTED:
                order.status = ORDER_STATUS_SUBMITTED
                status_updated = True
        elif status == 1:
            remain = float(order_info["amount"]) - float(
                order_info["executed_amount"])
            if order.remain != remain:
                order.remain = remain
                order.status = ORDER_STATUS_PARTIAL_FILLED
                status_updated = True
        elif status == 2:
            order.status = ORDER_STATUS_FILLED
            order.remain = 0
            status_updated = True
        elif status == 3 or status == 4:
            order.status = ORDER_STATUS_CANCELED
            remain = float(order_info["amount"]) - float(
                order_info["executed_amount"])
            order.remain = remain
            status_updated = True
        else:
            logger.warn("state error! order_info:", order_info, caller=self)
            return

        if status_updated:
            order.avg_price = order_info["avg_price"]
            order.ctime = int(order_info["created_date"] * 1000)
            order.utime = int(order_info["finished_date"] * 1000)
            SingleTask.run(self._order_update_callback, copy.copy(order))

        # Delete order that already completed.
        if order.status in [
                ORDER_STATUS_FAILED, ORDER_STATUS_CANCELED, ORDER_STATUS_FILLED
        ]:
            self._orders.pop(order_no)
예제 #25
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)
예제 #26
0
 def initialize(self):
     LoopRunTask.register(self._check_connection, self._check_conn_interval)
     SingleTask.run(self._connect)
예제 #27
0
 async def on_event_asset_update(self, asset: Asset):
     """ 资产数据更新回调
     """
     self._assets = asset
     SingleTask.run(self._asset_update_callback, asset)
예제 #28
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._init_success_callback, False, e)
                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._init_success_callback, False, e)
                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_json(data)
            return

        # Subscribe response message received.
        if msg.get("event") == "subscribe":
            if msg.get("channel") == self._order_channel:
                SingleTask.run(self._init_success_callback, True, None)
            else:
                e = Error("subscribe order event error: {}".format(msg))
                SingleTask.run(self._init_success_callback, False, e)
            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)
예제 #29
0
    async def process_binary(self, raw):
        """ 处理websocket上接收到的消息
        @param raw 原始的压缩数据
        """
        decompress = zlib.decompressobj(-zlib.MAX_WBITS)
        msg = decompress.decompress(raw)
        msg += decompress.flush()
        msg = msg.decode()
        if msg == "pong":  # 心跳返回
            return
        msg = json.loads(msg)
        logger.debug("msg:", msg, caller=self)

        # 登陆成功之后再订阅数据
        if msg.get("event") == "login":
            if not msg.get("success"):
                e = Error(
                    "Websocket connection authorized failed: {}".format(msg))
                logger.error(e, caller=self)
                if self._init_success_callback:
                    SingleTask.run(self._init_success_callback, False, e)
                return
            logger.info("Websocket connection authorized successfully.",
                        caller=self)

            # 获取当前等待成交和部分成交的订单信息
            result, error = await self._rest_api.get_order_list(
                self._symbol, 6)
            if error:
                e = Error("get open orders error: {}".format(error))
                if self._init_success_callback:
                    SingleTask.run(self._init_success_callback, False, e)
                return
            for order_info in result["order_info"]:
                order = self._update_order(order_info)
                if self._order_update_callback:
                    SingleTask.run(self._order_update_callback, order)

            # 获取当前持仓
            position, error = await self._rest_api.get_position(self._symbol)
            if error:
                e = Error("get position error: {}".format(error))
                if self._init_success_callback:
                    SingleTask.run(self._init_success_callback, False, e)
                return
            if len(position["holding"]) > 0:
                self._update_position(position["holding"][0])
            if self._position_update_callback:
                SingleTask.run(self._position_update_callback, self.position)

            # 订阅account, order, position
            data = {
                "op": "subscribe",
                "args": [self._order_channel, self._position_channel]
            }
            await self.ws.send_json(data)
            return

        # 订阅返回消息
        if msg.get("event") == "subscribe":
            if msg.get("channel") == self._order_channel:
                self._subscribe_order_ok = True
            if msg.get("channel") == self._position_channel:
                self._subscribe_position_ok = True
            if self._subscribe_order_ok and self._subscribe_position_ok:
                if self._init_success_callback:
                    SingleTask.run(self._init_success_callback, True, None)
            return

        # 订单更新
        if msg.get("table") == "futures/order":
            for data in msg["data"]:
                order = self._update_order(data)
                if order and self._order_update_callback:
                    SingleTask.run(self._order_update_callback, order)
            return

        # 持仓更新
        if msg.get("table") == "futures/position":
            for data in msg["data"]:
                self._update_position(data)
                if self._position_update_callback:
                    SingleTask.run(self._position_update_callback,
                                   self.position)
예제 #30
0
    def __init__(self, **kwargs):
        """ 初始化
        """
        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:10442"
        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)
            if kwargs.get("init_success_callback"):
                SingleTask.run(kwargs["init_success_callback"], False, e)
            return

        self._account = kwargs["account"]
        self._strategy = kwargs["strategy"]
        self._platform = OKEX
        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._asset_update_callback = kwargs.get("asset_update_callback")
        self._order_update_callback = kwargs.get("order_update_callback")
        self._init_success_callback = kwargs.get("init_success_callback")

        self._raw_symbol = self._symbol.replace("/", "-")  # 转换成交易所对应的交易对格式
        self._order_channel = "spot/order:{symbol}".format(
            symbol=self._raw_symbol)  # 订单订阅频道

        url = self._wss + "/ws/v3"
        super(OKExTrade, self).__init__(url, send_hb_interval=5)
        self.heartbeat_msg = "ping"

        self._assets = {
        }  # 资产 {"BTC": {"free": "1.1", "locked": "2.2", "total": "3.3"}, ... }
        self._orders = {}  # 订单 {"order_no": order, ... }

        # 初始化 REST API 对象
        self._rest_api = OKExRestAPI(self._host, self._access_key,
                                     self._secret_key, self._passphrase)

        # 初始化资产订阅
        if self._asset_update_callback:
            AssetSubscribe(self._platform, self._account,
                           self.on_event_asset_update)

        self.initialize()