示例#1
0
    async def do_kline_update(self, symbol, kline_type):
        if kline_type == const.MARKET_TYPE_KLINE_5M:
            range_type = "5min"
        elif kline_type == const.MARKET_TYPE_KLINE_15M:
            range_type = "15min"
        else:
            return
        result, error = await self._rest_api.get_kline(symbol, 1, range_type)
        if error:
            return

        kline = {
            "platform": self._platform,
            "symbol": symbol,
            "open": "%.8f" % float(result[0]["open"]),
            "high": "%.8f" % float(result[0]["high"]),
            "low": "%.8f" % float(result[0]["low"]),
            "close": "%.8f" % float(result[0]["close"]),
            "volume": "%.8f" % float(result[0]["volume"]),
            "timestamp": result[0]["timestamp"],
            "kline_type": kline_type
        }
        EventKline(**kline).publish()
        logger.info("symbol:", symbol, "kline:", kline, caller=self)
示例#2
0
 async def connected_callback(self):
     """After create connection to Websocket server successfully, we will subscribe orderbook/kline/trade event."""
     ches = []
     for ch in self._channels:
         if ch == "orderbook":
             for symbol in self._symbols:
                 ch = "futures/depth:{s}".format(s=symbol)
                 ches.append(ch)
         elif ch == "trade":
             for symbol in self._symbols:
                 ch = "futures/trade:{s}".format(s=symbol.replace("/", '-'))
                 ches.append(ch)
         elif ch == "kline":
             for symbol in self._symbols:
                 ch = "futures/candle60s:{s}".format(
                     s=symbol.replace("/", '-'))
                 ches.append(ch)
         # else:
         #     logger.error("channel error! channel:", ch, caller=self)
         if len(ches) > 0:
             msg = {"op": "subscribe", "args": ches}
             await self._ws.send(msg)
             logger.info("subscribe orderbook/kline/trade success.",
                         caller=self)
示例#3
0
    async def check_asset_update(self, *args, **kwargs):
        """Fetch asset information."""
        result, error = await self._rest_api.get_user_account()
        if error:
            return

        assets = {}
        for name, value in result["asset"].items():
            free = float(value.get("available"))
            total = float(value.get("total"))
            if not total:
                continue
            d = {
                "free": "%.8f" % free,
                "locked": "%.8f" % (total - free),
                "total": "%.8f" % total
            }
            assets[name] = d

        if assets == self._assets:
            update = False
        else:
            update = True
        self._assets = assets

        # Publish AssetEvent.
        timestamp = tools.get_cur_timestamp_ms()
        EventAsset(self._platform, self._account, self._assets, timestamp,
                   update).publish()
        logger.info("platform:",
                    self._platform,
                    "account:",
                    self._account,
                    "asset:",
                    self._assets,
                    caller=self)
示例#4
0
 async def done(self):
     """ 回测或者数据矩阵工作完毕
     """
     if config.backtest:  #回测模式
         #保存成交列表到csv文件
         result_dir_path = os.path.dirname(os.path.abspath(
             sys.argv[0])) + "/result_report"
         csv_file = result_dir_path + "/trades.csv"
         tools.create_dir(csv_file)
         if os.path.isdir(csv_file) or os.path.ismount(
                 csv_file) or os.path.islink(csv_file):
             logger.error("无效的csv文件")
             return
         if os.path.isfile(csv_file):
             os.remove(csv_file)
         result = []
         for param in config.platforms:
             platform = param["platform"]
             account = param["account"]
             symbols = param["symbols"]
             for sym in symbols:
                 fills = self.pm.get_fills_by_symbol(platform, account, sym)
                 for f in fills:
                     result.append(vars(f))
         #保存到csv
         df = pd.DataFrame(result)
         df.to_csv(csv_file)
         #接下来读取csv文件进行分析,生成回测报告
         analyzer = Analyzer()  #回测结果分析器
         if await analyzer.initialize(file_folder=result_dir_path):
             analyzer.do_analyze(result_dir=result_dir_path)
         logger.info("回测完毕", caller=self)
         self.stop()
     elif config.datamatrix:  #数据矩阵模式
         logger.info("datamatrix 完毕", caller=self)
         self.stop()
示例#5
0
    async def on_state_update_callback(self, state: State, **kwargs):
        """ 状态变化(底层交易所接口,框架等)通知回调函数
        """
        logger.info("on_state_update_callback:", state, caller=self)

        if state.code == State.STATE_CODE_DB_SUCCESS:  #数据库连接成功
            pass
        elif state.code == State.STATE_CODE_READY:  #交易接口准备好
            #收到此状态通知,证明指定交易接口准备就绪,可以对其进行操作,比如下单
            self.syminfo, e = await self.get_symbol_info(
                self.gw, self.symbols[0])
        elif state.code == State.STATE_CODE_CONNECT_SUCCESS:  #交易接口连接成功
            pass  #仅仅是通知一下,实际策略可以不用过于关注此状态
        elif state.code == State.STATE_CODE_CONNECT_FAILED:  #交易接口连接失败
            pass  #不需要过于关注此状态,因为底层接口会自动重新连接
        elif state.code == State.STATE_CODE_DISCONNECT:  #交易接口连接断开
            pass  #不需要过于关注此状态,因为底层接口会自动重新连接
        elif state.code == State.STATE_CODE_RECONNECTING:  #交易接口重新连接中
            pass  #比如说可以记录重连次数,如果一段时间内一直在重连可能交易所出问题,可以酌情处理,如结束本策略进程等
        elif state.code == State.STATE_CODE_PARAM_MISS:  #交易接口初始化过程缺少参数
            pass  #收到此状态通知,证明无法正常初始化,应该结束本策略进程
        elif state.code == State.STATE_CODE_GENERAL_ERROR:  #交易接口常规错误
            ...  #策略进程运行过程中如果收到某些错误通知,可以根据实际情况判断,比如可以做一些策略善后工作,然后结束本策略进程
            return
示例#6
0
    async def on_kline_update_callback(self, kline: Kline):
        """ 市场K线更新
        """
        logger.info("kline:", kline, caller=self)
        #行情保存进数据库
        kwargs = {
            "open": kline.open,
            "high": kline.high,
            "low": kline.low,
            "close": kline.close,
            "volume": kline.volume,
            "begin_dt": kline.timestamp,
            "end_dt": kline.timestamp + 60 * 1000 - 1
        }

        async def save(kwargs):
            t_kline = self.t_kline_map[kline.symbol]
            if t_kline:
                s, e = await t_kline.insert(kwargs)
                if e:
                    logger.error("insert kline:", e, caller=self)

        SingleTask.run(save, kwargs)
        #发布行情到消息队列
        kwargs = {
            "platform": kline.platform,
            "symbol": kline.symbol,
            "open": kline.open,
            "high": kline.high,
            "low": kline.low,
            "close": kline.close,
            "volume": kline.volume,
            "timestamp": kline.timestamp,
            "kline_type": kline.kline_type
        }
        EventKline(**kwargs).publish()
示例#7
0
    async def do_orderbook_update(self, *args, **kwargs):
        """ Fetch orderbook information."""
        for symbol in self._symbols:
            result, error = await self._rest_api.get_orderbook(symbol, self._orderbook_length)
            if error:
                continue
            bids = []
            asks = []
            for item in result["asks"]:
                a = [item["limitPrice"], item["quantity"]]
                asks.append(a)
            for item in result["bids"]:
                b = [item["limitPrice"], item["quantity"]]
                bids.append(b)

            if not bids and not asks:
                logger.warn("no orderbook data", caller=self)
                continue

            if len(bids) > 0 and len(asks) > 0 and float(bids[0][0]) >= float(asks[0][0]):
                logger.warn("symbol:", symbol, "bids one is grate than asks one! asks:", asks, "bids:",
                            bids, caller=self)
                continue

            orderbook = {
                "platform": self._platform,
                "symbol": symbol,
                "asks": asks,
                "bids": bids,
                "timestamp": tools.get_cur_timestamp_ms()
            }
            EventOrderbook(**orderbook).publish()
            logger.info("symbol:", symbol, "orderbook:", orderbook, caller=self)

            # await 0.1 second before next request.
            await asyncio.sleep(0.1)
示例#8
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)
示例#9
0
 async def connected_callback(self):
     """After create connection to Websocket server successfully, we will subscribe orderbook/trade/kline event."""
     channels = []
     for ch in self._channels:
         if ch == "orderbook":
             for symbol in self._symbols:
                 channel = self._symbol_to_channel(symbol, "orderBook10")
                 channels.append(channel)
         if ch == "trade":
             for symbol in self._symbols:
                 channel = self._symbol_to_channel(symbol, "trade")
                 channels.append(channel)
         if ch == "kline":
             for symbol in self._symbols:
                 channel = self._symbol_to_channel(symbol, "tradeBin1m")
                 channels.append(channel)
     while channels:
         data = {
             "op": "subscribe",
             "args": channels[:10]
         }
         await self._ws.send(data)
         channels = channels[10:]
         logger.info("subscribe orderbook/trade/kline successfully.", caller=self)
示例#10
0
文件: okex.py 项目: cdyfng/cath_quant
 async def connected_callback(self):
     """After create Websocket connection successfully, we will subscribing orderbook/trade/kline."""
     ches = []
     for ch in self._channels:
         if ch == "orderbook":
             for symbol in self._symbols:
                 ch = "spot/depth:{s}".format(s=symbol.replace("/", '-'))
                 ches.append(ch)
         elif ch == "trade":
             for symbol in self._symbols:
                 ch = "spot/trade:{s}".format(s=symbol.replace("/", '-'))
                 ches.append(ch)
         elif ch == "kline":
             for symbol in self._symbols:
                 ch = "spot/candle60s:{s}".format(
                     s=symbol.replace("/", '-'))
                 ches.append(ch)
         else:
             logger.error("channel error! channel:", ch, caller=self)
     if ches:
         msg = {"op": "subscribe", "args": ches}
         await self._ws.send(msg)
         logger.info("subscribe orderbook/trade/kline success.",
                     caller=self)
示例#11
0
    async def process_trade_update(self, data):
        """ Deal with trade data, and publish trade message to EventCenter via TradeEvent.

        Args:
            data: Newest trade data.
        """
        symbol = data[0].replace("_", "/")
        for item in data[1]:
            action = ORDER_ACTION_BUY if item["type"] == "buy" else ORDER_ACTION_SELL
            price = "%.8f" % float(item["price"])
            quantity = "%.8f" % float(item["amount"])
            timestamp = int(item["time"] * 1000)

            # Publish EventTrade.
            trade = {
                "platform": self._platform,
                "symbol": symbol,
                "action": action,
                "price": price,
                "quantity": quantity,
                "timestamp": timestamp
            }
            EventTrade(**trade).publish()
            logger.info("symbol:", symbol, "trade:", trade, caller=self)
示例#12
0
    async def process(self, msg):
        """ 处理websocket上接收到的消息
        """
        logger.debug("msg:", msg, caller=self)
        if not isinstance(msg, dict):
            return

        table = msg.get("table")
        if table == "orderBook10":  # 订单薄数据
            for item in msg["data"]:
                symbol = item.get("symbol")
                orderbook = {
                    "platform": self._platform,
                    "symbol": symbol,
                    "asks": item.get("asks"),
                    "bids": item.get("bids"),
                    "timestamp": tools.utctime_str_to_mts(item["timestamp"])
                }
                EventOrderbook(**orderbook).publish()
                logger.info("symbol:",
                            symbol,
                            "orderbook:",
                            orderbook,
                            caller=self)
        elif table == "trade":  # 成交数据
            for item in msg["data"]:
                symbol = item["symbol"]
                trade = {
                    "platform": self._platform,
                    "symbol": symbol,
                    "action":
                    ORDER_ACTION_BUY if item["side"] else ORDER_ACTION_SELL,
                    "price": "%.1f" % item["price"],
                    "quantity": str(item["size"]),
                    "timestamp": tools.utctime_str_to_mts(item["timestamp"])
                }
                EventTrade(**trade).publish()
                logger.info("symbol:", symbol, "trade:", trade, caller=self)
        elif table == "tradeBin1m":  # 1分钟K线数据
            for item in msg["data"]:
                symbol = item["symbol"]
                kline = {
                    "platform": self._platform,
                    "symbol": symbol,
                    "open": "%.1f" % item["open"],  # 开盘价
                    "high": "%.1f" % item["high"],  # 最高价
                    "low": "%.1f" % item["low"],  # 最低价
                    "close": "%.1f" % item["close"],  # 收盘价
                    "volume": str(item["volume"]),  # 交易量
                    "timestamp":
                    tools.utctime_str_to_mts(item["timestamp"]),  # 时间戳
                    "kline_type": MARKET_TYPE_KLINE
                }
                EventKline(**kline).publish()
                logger.info("symbol:", symbol, "kline:", kline, caller=self)
示例#13
0
    async def on_event_order_update(self, order: Order):
        """ 订单状态更新
        """
        logger.info("order update:", order, caller=self)

        if order.status == ORDER_STATUS_FILLED:
            if order.order_no == self.buy_open_order_no:  # 开仓委托单已经完全成交
                logger.info("buy open completed.", caller=self)
                self.sell_close_time_down = 60 * 5  # 设置平仓倒计时 5分钟
            if order.order_no == self.sell_close_order_no:  # 平仓委托单已经完全成交
                logger.info("sell close completed.", caller=self)
                exit(0)
示例#14
0
    async def process(self, msg):
        """ 处理websocket上接收到的消息
        """
        if not isinstance(msg, dict):
            return
        logger.debug("msg:", json.dumps(msg), caller=self)

        # 请求授权、订阅
        if msg.get("request"):
            if msg["request"]["op"] == "authKeyExpires":  # 授权
                if msg["success"]:
                    # 订阅order和position
                    data = {
                        "op": "subscribe",
                        "args": [self._order_channel, self._position_channel]
                    }
                    await self.ws.send_json(data)
                    logger.info("Websocket connection authorized successfully.", caller=self)
                else:
                    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)
            if msg["request"]["op"] == "subscribe":  # 订阅
                if msg["subscribe"] == self._order_channel and msg["success"]:
                    self._subscribe_order_ok = True
                    logger.info("subscribe order successfully.", caller=self)
                if msg["subscribe"] == self._position_channel and msg["success"]:
                    self._subscribe_position_ok = True
                    logger.info("subscribe position successfully.", caller=self)
                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") == "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") == "position":
            for data in msg["data"]:
                self._update_position(data)
                if self._position_update_callback:
                    SingleTask.run(self._position_update_callback, self.position)
示例#15
0
    async def connect(self, reconnect=False):
        """ 建立TCP连接
        @param reconnect 是否是断线重连
        """
        logger.info("host:", self._host, "port:", self._port, caller=self)
        if self._connected:
            return

        # 建立连接
        try:
            transport, protocol = await aioamqp.connect(
                host=self._host,
                port=self._port,
                login=self._username,
                password=self._password)
        except Exception as e:
            logger.error("connection error:", e, caller=self)
            return
        finally:
            # 如果已经有连接已经建立好,那么直接返回(此情况在连续发送了多个连接请求后,若干个连接建立好了连接)
            if self._connected:
                return
        channel = await protocol.channel()
        self._protocol = protocol
        self._channel = channel
        self._connected = True
        logger.info("Rabbitmq initialize success!", caller=self)

        # 创建默认的交换机
        exchanges = [
            "Orderbook",
            "Trade",
            "Kline",
        ]
        for name in exchanges:
            await self._channel.exchange_declare(exchange_name=name,
                                                 type_name="topic")
        logger.info("create default exchanges success!", caller=self)

        # 如果是断线重连,那么直接绑定队列并开始消费数据,如果是首次连接,那么等待5秒再绑定消费(等待程序各个模块初始化完成)
        if reconnect:
            self._bind_and_consume()
        else:
            asyncio.get_event_loop().call_later(5, self._bind_and_consume)
示例#16
0
    async def start_orders(self, actions, callback):
        logger.info('start orders...', actions)
        # self.actions = [['BTC/BUSD', 'Buy', self.six_price[4], amount_usdt / self.six_price[2] / self.six_price[1]],
        #                 ['BTC/USDT', 'Sell', self.six_price[3], amount_usdt / self.six_price[3]],
        #                 ['BUSD/USDT', 'Buy', self.six_price[0], amount_usdt / self.six_price[1]]]

        # 先交易第个

        for action in actions:
            symbol = action[0]
            side = action[1]
            new_price = tools.float_to_str(action[2])
            decimal_places = 2 if symbol == "BUSD/USDT" else 6
            quantity = tools.round2(action[3], decimal_places)
            logger.info('order: ', symbol, new_price, quantity)
            order_no, error = await self.trader[symbol].create_order(side, new_price, quantity)
            if error:
                logger.error("create order error! error:", error, caller=self)
                break
            logger.info("create sell close order:", order_no, caller=self)
            await asyncio.sleep(0.01)
            if callback:
                SingleTask.run(callback, order_no)
示例#17
0
 async def connected_callback(self):
     """ After create Websocket connection successfully, we will subscribing orderbook/trade/kline events.
     """
     if not self._symbols:
         logger.warn("symbols not found in config file.", caller=self)
         return
     if not self._channels:
         logger.warn("channels not found in config file.", caller=self)
         return
     for ch in self._channels:
         if ch == "trade":
             params = []
             for s in self._symbols:
                 params.append(s.replace("/", "_"))
             request_id = await self._generate_request_id()
             d = {"id": request_id, "method": "trades.subscribe", "params": params}
             await self.ws.send_json(d)
             logger.info("subscribe trade success.", caller=self)
         elif ch == "orderbook":
             params = []
             for s in self._symbols:
                 params.append([s.replace("/", "_"), int(self._orderbook_length), str(self._orderbook_price_precious)])
             request_id = await self._generate_request_id()
             d = {"id": request_id, "method": "depth.subscribe", "params": params}
             await self.ws.send_json(d)
             logger.info("subscribe orderbook success.", caller=self)
         elif ch == "kline":
             for s in self._symbols:
                 params = [s.replace("/", "_"), 60]
                 request_id = await self._generate_request_id()
                 d = {"id": request_id, "method": "kline.subscribe", "params": params}
                 await self.ws.send_json(d)
                 logger.info("subscribe kline success.", caller=self)
         else:
             logger.error("channel error:", ch, caller=self)
             continue
示例#18
0
 async def on_time(self):
     """ 每秒钟执行一次. 因为是异步并发架构,这个函数执行的时候交易通道链接不一定已经建立好
     """
     logger.info("on_time ...", caller=self)
示例#19
0
 async def on_asset_update_callback(self, asset: Asset):
     """ 账户资产更新
     """
     logger.info("asset:", asset, caller=self)
示例#20
0
 async def on_position_update_callback(self, position: Position):
     """ 持仓更新
     """
     logger.info("position:", position, caller=self)
示例#21
0
 async def on_fill_update_callback(self, fill: Fill):
     """ 订单成交通知
     """
     logger.info("fill:", fill, caller=self)
示例#22
0
 async def on_order_update_callback(self, order: Order):
     """ 订单状态更新
     """
     logger.info("order:", order, caller=self)
示例#23
0
 async def on_ticker_update_callback(self, ticker: Ticker):
     """ 市场行情tick更新
     """
     logger.info("ticker:", ticker, caller=self)
示例#24
0
 async def on_kline_update_callback(self, kline: Kline):
     """ 市场K线更新
     """
     logger.info("kline:", kline, caller=self)
示例#25
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)
示例#26
0
 def stop(self):
     """Stop the event loop."""
     logger.info("stop io loop.", caller=self)
     self.loop.stop()
示例#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._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)
示例#28
0
 async def on_state_update_callback(self, state: State, **kwargs):
     """ 状态变化(底层交易所接口,框架等)通知回调函数
     """
     logger.info("on_state_update_callback:", state, caller=self)
示例#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
 async def on_trade_update_callback(self, trade: Trade):
     """ 市场最新成交更新
     """
     logger.info("trade:", trade, caller=self)