Beispiel #1
0
    async def process_binary(self, msg):
        """ Process binary message that received from Websocket connection.
        """
        data = json.loads(gzip.decompress(msg).decode())
        logger.debug("data:", json.dumps(data), caller=self)
        channel = data.get("ch")
        if not channel:
            if data.get("ping"):
                hb_msg = {"pong": data.get("ping")}
                await self.ws.send_json(hb_msg)
            if data.get("rep"):
                await self.process_hist_kline(data)
            return

        symbol = self._c_to_s[channel]

        if channel.find("kline") != -1:
            await self.process_kline(data)

        elif channel.find("depth") != -1:
            await self.process_orderbook(data)
        
        elif channel.find("trade") != -1:
            await self.process_trade(data)
        else:
            logger.error("event error! msg:", msg, caller=self)
 async def process_orderbook(self, data):
     """ process orderbook data
     """
     channel = data.get("ch")
     symbol = self._c_to_s[channel]
     d = data.get("tick")
     asks, bids = [], []
     if d.get("asks"):
         for item in d.get("asks")[:self._orderbook_length]:
             price = "%.8f" % item[0]
             quantity = "%.8f" % item[1]
             asks.append([price, quantity])
     if d.get("bids"):
         for item in d.get("bids")[:self._orderbook_length]:
             price = "%.8f" % item[0]
             quantity = "%.8f" % item[1]
             bids.append([price, quantity])
     info = {
         "platform": self._platform,
         "symbol": symbol,
         "asks": asks,
         "bids": bids,
         "timestamp": d.get("ts")
     }
     orderbook = Orderbook(**info)
     self._orderbooks.append(orderbook)
     SingleTask.run(self._orderbook_update_callback, copy.copy(orderbook))
     logger.debug("symbol:", symbol, "orderbook:", orderbook, caller=self)
Beispiel #3
0
    async def process_binary(self, raw):
        """ 处理websocket上接收到的消息
        @param raw 原始的压缩数据
        """
        data = json.loads(gzip.decompress(raw).decode())
        logger.debug("data:", data, caller=self)

        op = data.get("op")
        if op == "ping":
            hb_msg = {"op": "pong", "ts": data.get("ts")}
            await self.ws.send_json(hb_msg)

        elif op == "auth":
            await self.auth_callback(data)

        elif op == "sub":
            await self.sub_callback(data)

        elif op == "notify":
            if data["topic"].startswith("orders"):
                self._update_order(data)
            elif data["topic"].startswith("positions"):
                self._update_position(data)
            elif data["topic"].startswith("accounts"):
                self._update_asset(data)
Beispiel #4
0
 async def on_event_init_success_callback(self, success: bool, error: Error,
                                          **kwargs):
     """ init success callback
     """
     logger.debug("init success callback update:",
                  success,
                  error,
                  kwargs,
                  caller=self)
 async def on_ticker(self, *args, **kwargs):
     """ 定时执行任务
     """
     ts_diff = int(time.time() * 1000) - self.last_orderbook_timestamp
     if ts_diff > self.orderbook_invalid_seconds * 1000:
         logger.debug("received orderbook timestamp exceed:",
                      self.strategy,
                      self.symbol,
                      ts_diff,
                      caller=self)
         return
Beispiel #6
0
 async def on_event_orderbook_update(self, orderbook: Orderbook):
     """  orderbook更新
         self.market.orderbooks 是最新的orderbook组成的队列,记录的是历史N次orderbook的数据。
         本回调所传的orderbook是最新的单次orderbook。
     """
     logger.debug("orderbook:", orderbook, caller=self)
     if orderbook.asks:
         self.ask1_price = float(orderbook.asks[0][0])  # 卖一价格
         self.ask1_volume = float(orderbook.asks[0][1])  # 卖一数量
     if orderbook.bids:
         self.bid1_price = float(orderbook.bids[0][0])  # 买一价格
         self.bid1_volume = float(orderbook.bids[0][1])  # 买一数量
     self.last_orderbook_timestamp = orderbook.timestamp
 async def on_event_kline_update(self, kline: Kline):
     """ kline更新
         self.market.klines 是最新的kline组成的队列,记录的是历史N次kline的数据。
         本回调所传的kline是最新的单次kline。
     """
     logger.debug("kline update:", kline, caller=self)
     result = await mongo.MongoDBBase('quant', 'kline').find_one_and_update({'platform': kline.platform, 'symbol': kline.symbol, \
         'timestamp': kline.timestamp, 'kline_type': kline.kline_type}, {'$set': {'open': kline.open, 'high': kline.high, \
         'close': kline.close, 'low': kline.low, 'volume': kline.volume }}, upsert=True, return_document=True)
     if not result:
         logger.error("insert mongo error ", kline.platform + kline.symbol,
                      kline, result)
     logger.debug("insert mongo success: ", result)
    async def process_kline(self, data):
        """ process kline data
        """
        channel = data.get("ch")
        symbol = self._c_to_s[channel]
        d = data.get("tick")
        info = {
            "platform": self._platform,
            "symbol": symbol,
            "open": "%.8f" % d["open"],
            "high": "%.8f" % d["high"],
            "low": "%.8f" % d["low"],
            "close": "%.8f" % d["close"],
            "volume": "%.8f" % d["amount"],
            "timestamp": int(data.get("ts")),
            "kline_type": MARKET_TYPE_KLINE
        }
        kline = Kline(**info)
        self._klines.append(kline)
        SingleTask.run(self._kline_update_callback, copy.copy(kline))

        logger.debug("symbol:", symbol, "kline:", kline, caller=self)
Beispiel #9
0
 async def process_trade(self, data):
     """ process trade
     """
     channel = data.get("ch")
     symbol = self._c_to_s[channel]
     ticks = data.get("tick")
     for tick in ticks["data"]: 
         direction = tick.get("direction")
         price = tick.get("price")
         quantity = tick.get("amount")
         info = {
             "platform": self._platform,
             "symbol": symbol,
             "action": ORDER_ACTION_BUY if direction == "buy" else ORDER_ACTION_SELL,
             "price": "%.8f" % price,
             "quantity": "%.8f" % quantity,
             "timestamp": tick.get("ts")
         }
         trade = Trade(**info)
         self._trades.append(trade)
         SingleTask.run(self._trade_update_callback, copy.copy(trade))
         logger.debug("symbol:", symbol, "trade:", trade, caller=self)
Beispiel #10
0
 async def _send_heartbeat_msg(self, *args, **kwargs):
     """ 发送心跳给服务器
     """
     if not self.ws:
         logger.warn("websocket connection not connected yet!", caller=self)
         return
     if self.heartbeat_msg:
         try:
             if isinstance(self.heartbeat_msg, dict):
                 await self.ws.send_json(self.heartbeat_msg)
             elif isinstance(self.heartbeat_msg, str):
                 await self.ws.send_str(self.heartbeat_msg)
             else:
                 logger.error("send heartbeat msg failed! heartbeat msg:",
                              self.heartbeat_msg,
                              caller=self)
                 return
             logger.debug("send ping message:",
                          self.heartbeat_msg,
                          caller=self)
         except ConnectionResetError:
             traceback.print_exc()
             await asyncio.get_event_loop().create_task(self._reconnect())
Beispiel #11
0
    def ticker(self):
        """ 启动心跳, 每interval间隔执行一次
        """
        self._count += 1

        # 打印心跳次数
        if self._print_interval > 0:
            if self._count % int(self._print_interval*200) == 0:
                logger.debug("do server heartbeat, count:", self._count, caller=self)

        # 设置下一次心跳回调
        asyncio.get_event_loop().call_later(self._interval, self.ticker)

        # 执行任务回调
        for task_id, task in self._tasks.items():
            interval = task["interval"]
            if self._count % int(interval*200) != 0:
                continue
            func = task["func"]
            args = task["args"]
            kwargs = task["kwargs"]
            kwargs["task_id"] = task_id
            kwargs["heart_beat_count"] = self._count
            asyncio.get_event_loop().create_task(func(*args, **kwargs))
Beispiel #12
0
    async def fetch(cls,
                    method,
                    url,
                    params=None,
                    body=None,
                    data=None,
                    headers=None,
                    timeout=30,
                    **kwargs):
        """ Create a HTTP request.

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

            kwargs:
                proxy: HTTP proxy.

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

        Raises:
            HTTP request exceptions or response data parse exceptions. All the exceptions will be captured and return
            Error information.
        """
        session = cls._get_session(url)
        if not kwargs.get("proxy"):
            kwargs["proxy"] = config.proxy
        try:
            if method == "GET":
                response = await session.get(url,
                                             params=params,
                                             headers=headers,
                                             timeout=timeout,
                                             **kwargs)
            elif method == "POST":
                response = await session.post(url,
                                              params=params,
                                              data=body,
                                              json=data,
                                              headers=headers,
                                              timeout=timeout,
                                              **kwargs)
            elif method == "PUT":
                response = await session.put(url,
                                             params=params,
                                             data=body,
                                             json=data,
                                             headers=headers,
                                             timeout=timeout,
                                             **kwargs)
            elif method == "DELETE":
                response = await session.delete(url,
                                                params=params,
                                                data=body,
                                                json=data,
                                                headers=headers,
                                                timeout=timeout,
                                                **kwargs)
            else:
                error = "http method error!"
                return None, None, error
        except Exception as e:
            logger.error("method:",
                         method,
                         "url:",
                         url,
                         "headers:",
                         headers,
                         "params:",
                         params,
                         "body:",
                         body,
                         "data:",
                         data,
                         "Error:",
                         e,
                         caller=cls)
            return None, None, e
        code = response.status
        if code not in (200, 201, 202, 203, 204, 205, 206):
            text = await response.text()
            logger.error("method:",
                         method,
                         "url:",
                         url,
                         "headers:",
                         headers,
                         "params:",
                         params,
                         "body:",
                         body,
                         "data:",
                         data,
                         "code:",
                         code,
                         "result:",
                         text,
                         caller=cls)
            return code, None, text
        try:
            result = await response.json()
        except:
            result = await response.text()
            logger.warn("response data is not json format!",
                        "method:",
                        method,
                        "url:",
                        url,
                        "headers:",
                        headers,
                        "params:",
                        params,
                        "body:",
                        body,
                        "data:",
                        data,
                        "code:",
                        code,
                        "result:",
                        result,
                        caller=cls)
        logger.debug("method:",
                     method,
                     "url:",
                     url,
                     "headers:",
                     headers,
                     "params:",
                     params,
                     "body:",
                     body,
                     "data:",
                     data,
                     "code:",
                     code,
                     "result:",
                     json.dumps(result),
                     caller=cls)
        return code, result, None
Beispiel #13
0
 async def on_event_trade_update(self, trade: MarketTrade):
     """ market trade更新
         self.market.trades 是最新的逐笔成交组成的队列,记录的是历史N次trade的数据。
         本回调所传的trade是最新的单次trade。
     """
     logger.debug("trade update:", trade, caller=self)
Beispiel #14
0
 async def on_event_kline_update(self, kline: Kline):
     """ kline更新
         self.market.klines 是最新的kline组成的队列,记录的是历史N次kline的数据。
         本回调所传的kline是最新的单次kline。
     """
     logger.debug("kline update:", kline, caller=self)
Beispiel #15
0
 async def on_event_position_update(self, position: Position):
     """ 仓位更新
     """
     logger.debug("position update:", position, caller=self)
Beispiel #16
0
 async def on_event_asset_update(self, asset: Asset):
     """ 资产更新
     """
     logger.debug("asset update:", asset, caller=self)
Beispiel #17
0
 async def on_event_order_update(self, order: Order):
     """ 订单状态更新
     """
     logger.debug("order update:", order, caller=self)
Beispiel #18
0
 async def on_event_orderbook_update_future(self, orderbook: Orderbook):
     """  orderbook更新
         self.market.orderbooks 是最新的orderbook组成的队列,记录的是历史N次orderbook的数据。
         本回调所传的orderbook是最新的单次orderbook。
     """
     logger.debug("future orderbook:", orderbook, caller=self)
Beispiel #19
0
    async def delta_hedging(self, *args, **kwargs):
        """ delta hedge
        """
        logger.debug("delta hedging", caller=self)
        option_delta = 0
        assets, error = await self.trader.rest_api.get_asset_info(
            self.raw_symbol)
        if error:
            logger.error(self.strategy,
                         "get option asset error! error:",
                         error,
                         caller=self)
        else:
            for item in assets["data"]:
                if item["symbol"] == self.raw_symbol:
                    o_margin_balance = item["margin_balance"]
                    o_delta = item["delta"]
                    o_gamma = item["gamma"]
                    o_theta = item["theta"]
                    o_vega = item["vega"]
                    option_delta = o_delta + o_margin_balance

            #增加delta对冲,使用期货对冲。
            accounts, error = await self.future_trader.rest_api.get_account_position(
                self.raw_symbol)
            if error:
                logger.error(self.strategy,
                             "get future account and position error! error:",
                             error,
                             caller=self)
            else:
                margin_balance = accounts["data"][0]["margin_balance"]
                long_position = 0
                short_position = 0
                delta_long = 0
                delta_short = 0
                long_last_price = 0
                short_last_price = 0
                for position in accounts["data"][0]["positions"]:
                    if position["direction"] == "buy":
                        long_position = position["volume"]
                        long_cost_open = position["cost_open"]
                        long_last_price = position["last_price"]
                    if position["direction"] == "sell":
                        short_position = position["volume"]
                        short_cost_open = position["cost_open"]
                        short_last_price = position["last_price"]
                if long_position:
                    delta_long = self.future_volume_usd * int(
                        long_position) / float(long_last_price)
                if short_position:
                    delta_short = self.future_volume_usd * int(
                        short_position) / float(short_last_price)
                future_delta = margin_balance - delta_short + delta_long
                t_delta = option_delta + future_delta
                orders_data = []
                # 对冲对应数量的币
                if abs(t_delta) >= self.delta_limit:
                    if t_delta > 0:
                        # 开空单
                        price = 0
                        volume = int(t_delta * long_last_price /
                                     self.future_volume_usd)
                        if volume:
                            quantity = -volume  #
                            action = ORDER_ACTION_SELL
                            new_price = str(price)  # 将价格转换为字符串,保持精度
                            if quantity:
                                orders_data.append({
                                    "price":
                                    new_price,
                                    "quantity":
                                    quantity,
                                    "action":
                                    action,
                                    "order_type":
                                    ORDER_TYPE_MARKET
                                })
                    else:
                        # 开多单
                        price = 0
                        volume = abs(
                            int(t_delta * long_last_price /
                                self.future_volume_usd))
                        if volume:
                            quantity = volume  #
                            action = ORDER_ACTION_BUY
                            new_price = str(price)  # 将价格转换为字符串,保持精度
                            if quantity:
                                orders_data.append({
                                    "price":
                                    new_price,
                                    "quantity":
                                    quantity,
                                    "action":
                                    action,
                                    "order_type":
                                    ORDER_TYPE_MARKET
                                })

                if orders_data:
                    order_nos, error = await self.future_trader.create_orders(
                        orders_data)
                    if error:
                        logger.error(self.strategy,
                                     "create future order error! error:",
                                     error,
                                     caller=self)
                    else:
                        logger.info(self.strategy,
                                    "create future orders success:",
                                    order_nos,
                                    caller=self)