async def sub_callback(self, data): if data["err-code"] != 0: e = Error("subscribe {} failed!".format(data["topic"])) logger.error(e, caller=self) SingleTask.run(self._init_success_callback, False, e) return if data["topic"] == self._order_channel: self._subscribe_order_ok = True elif data["topic"] == self._position_channel: self._subscribe_position_ok = True elif data["topic"] == self._asset_channel: self._subscribe_asset_ok = True if self._subscribe_order_ok and self._subscribe_position_ok \ and self._subscribe_asset_ok: success, error = await self._rest_api.get_open_orders(self._symbol) if error: e = Error("get open orders failed!") SingleTask.run(self._init_success_callback, False, e) elif "data" in success and "orders" in success["data"]: for order_info in success["data"]["orders"]: order_info["ts"] = order_info["created_at"] self._update_order(order_info) SingleTask.run(self._init_success_callback, True, None) else: logger.warn("get open orders:", success, caller=self) e = Error("Get Open Orders Unknown error") SingleTask.run(self._init_success_callback, False, e)
async def on_ticker(self, *args, **kwargs): """ 定时执行任务 """ if self.trader.assets is None: return if self.trader.position is None: return ts_diff = int(time.time() * 1000) - self.last_orderbook_timestamp if ts_diff > self.orderbook_invalid_seconds * 1000: logger.warn("received orderbook timestamp exceed:", self.strategy, self.symbol, ts_diff, caller=self) return # 获取标记价格,每次的挂单价格与指数价格进行比较。 success, error = await self.trader.rest_api.get_market_index( contract_code=self.symbol) if error: logger.error("Get swap market index faild:", error, caller=self) else: for item in success["data"]: if item["contract_code"] == self.symbol: self.mark_price = item["mark_price"] await self.cancel_orders() await self.place_orders()
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.warn("received orderbook timestamp exceed:", self.strategy, self.symbol, ts_diff, caller=self) return await self.cancel_orders() await self.place_orders()
async def _reconnect(self): """ 重新建立websocket连接 """ if self.closed: logger.info("websocket closed, not reconnecting", caller=self) return logger.warn("reconnecting websocket right now!", caller=self) await self._connect()
async def _check_connection(self, *args, **kwargs): """ 检查连接是否正常 """ # 检查websocket连接是否关闭,如果关闭,那么立即重连 if not self.ws or self.closed: logger.warn("websocket connection not connected yet!", caller=self) return if self.ws.closed: await asyncio.create_task(self._reconnect()) return
async def _send_heartbeat_msg(self, *args, **kwargs): """ 发送心跳给服务器 """ if not self.ws: logger.warn("websocket connection not connected yet!", caller=self) return data = {"pong": int(time.time() * 1000)} try: await self.ws.send_json(data) except ConnectionResetError: await asyncio.create_task(self._reconnect())
async def receive(self): """ 接收消息 """ async for msg in self.ws: if msg.type == aiohttp.WSMsgType.TEXT: try: data = json.loads(msg.data) except: data = msg.data await asyncio().create_task(self.process(data)) elif msg.type == aiohttp.WSMsgType.BINARY: await asyncio.create_task(self.process_binary(msg.data)) elif msg.type == aiohttp.WSMsgType.CLOSED: logger.warn("receive event CLOSED:", msg, caller=self) await asyncio.create_task(self._reconnect()) elif msg.type == aiohttp.WSMsgType.CLOSE: logger.warn("receive event CLOSE:", msg, caller=self) await asyncio.create_task(self._reconnect()) elif msg.type == aiohttp.WSMsgType.CLOSING: logger.warn("receive event CLOSING:", msg, caller=self) await asyncio.create_task(self._reconnect()) elif msg.type == aiohttp.WSMsgType.ERROR: logger.error("receive event ERROR:", msg, caller=self) await asyncio.create_task(self._reconnect()) else: logger.warn("unhandled msg:", msg, caller=self)
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.create_task(self._reconnect())
async def place_orders(self): """ 下单 """ orders_data = [] if self.trader.position and self.trader.position.short_quantity: # 平空单 price = round(self.mark_price - self.spread, 1) quantity = -self.trader.position.short_quantity action = ORDER_ACTION_BUY new_price = str(price) # 将价格转换为字符串,保持精度 if quantity: orders_data.append({ "price": new_price, "quantity": quantity, "action": action, "order_type": ORDER_TYPE_LIMIT }) self.last_mark_price = self.mark_price if self.trader.position and self.trader.position.long_quantity: # 平多单 price = round(self.mark_price + self.spread, 1) quantity = self.trader.position.long_quantity action = ORDER_ACTION_SELL new_price = str(price) # 将价格转换为字符串,保持精度 if quantity: orders_data.append({ "price": new_price, "quantity": quantity, "action": action, "order_type": ORDER_TYPE_LIMIT }) self.last_mark_price = self.mark_price if self.trader.assets and self.trader.assets.assets.get( self.raw_symbol).get("free"): # 开空单 if self.trader.position and self.trader.position.short_quantity and self.trader.position.short_quantity >= self.max_quantity: logger.warn("option short position exceeds the max quantity: ", self.symbol, self.trader.position.short_quantity, self.max_quantity, caller=self) else: price = round(self.mark_price + self.spread, 1) volume = self.volume 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_LIMIT }) self.last_mark_price = self.mark_price if self.trader.assets and self.trader.assets.assets.get( self.partition_symbol) and self.trader.assets.assets.get( self.partition_symbol).get("free"): # 开多单 if self.trader.position and self.trader.position.long_quantity and self.trader.position.long_quantity >= self.max_quantity: logger.warn("option long position exceeds the max quantity: ", self.symbol, self.trader.position.long_quantity, self.max_quantity, caller=self) else: price = round(self.mark_price - self.spread, 1) volume = self.volume 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_LIMIT }) self.last_mark_price = self.mark_price if orders_data: order_nos, error = await self.trader.create_orders(orders_data) if error: logger.error(self.strategy, "create future order error! error:", error, caller=self) logger.info(self.strategy, "create future orders success:", order_nos, caller=self)