async def cancel_orders(self): """ 取消订单 """ order_nos = [orderno for orderno in self.trader.orders] #if order_nos and self.last_mark_price != self.mark_price: if order_nos: _, errors = await self.trader.revoke_order(*order_nos) if errors: logger.error(self.strategy, "cancel option order error! error:", errors, caller=self) # 出错则取消所有挂单 _, errors = await self.trader.revoke_order() if errors: logger.error(self.strategy, "cancel all option orders error! error:", errors, caller=self) else: logger.info(self.strategy, "cancel all option orders success!", caller=self) else: logger.info(self.strategy, "cancel option order:", order_nos, caller=self)
async def place_orders(self): """ 下单 """ orders_data = [] if self.trader.position and self.trader.position.short_quantity: # 平空单 price = round(self.ask1_price - 0.1, 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, "lever_rate": 5}) self.last_ask_price = self.ask1_price if self.trader.assets and self.trader.assets.assets.get(self.raw_symbol): # 开空单 price = round(self.bid1_price + 0.1, 1) volume = int(float(self.trader.assets.assets.get(self.raw_symbol).get("free")) * 5/ price / self.contract_size) if volume >= 1: quantity = - volume # 空1张 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, "lever_rate": 5}) self.last_bid_price = self.bid1_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)
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 cancel_orders(self): """ 取消订单 """ order_nos = [ orderno for orderno in self.trader.orders ] if order_nos and self.last_ask_price != self.ask1_price: _, errors = await self.trader.revoke_order(*order_nos) if errors: logger.error(self.strategy,"cancel future order error! error:", errors, caller=self) else: logger.info(self.strategy,"cancel future order:", order_nos, caller=self)
def start(self): """Start the event loop.""" def keyboard_interrupt(s, f): print("KeyboardInterrupt (ID: {}) has been caught. Cleaning up...". format(s)) self.loop.stop() signal.signal(signal.SIGINT, keyboard_interrupt) logger.info("start io loop ...", caller=self) self.loop.run_forever()
async def _connect(self): logger.info("url:", self._url, caller=self) METHOD_LOCKERS = {} proxy = config.proxy self.session = aiohttp.ClientSession() try: self.ws = await self.session.ws_connect(self._url, proxy=proxy) self.closed = False except aiohttp.ClientConnectionError: logger.error("connect to server error! url:", self._url, caller=self) return asyncio.create_task(self.connected_callback()) asyncio.create_task(self.receive())
async def on_event_position_update(self, position: Position): """ 仓位更新 """ logger.info("position update:", position, caller=self)
async def on_event_asset_update(self, asset: Asset): """ 资产更新 """ logger.info("asset update:", asset, caller=self)
async def on_event_order_update(self, order: Order): """ 订单状态更新 """ logger.info("order update:", order, caller=self)
def _update_order(self, order_info): """ Order update. Args: order_info: Order information. """ if order_info["contract_code"] != self._symbol: 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, "client_order_id": order_info.get("client_order_id"), "order_price_type": order_info.get("order_price_type"), "order_type": order_info["order_type"], "action": ORDER_ACTION_BUY if order_info["direction"] == "buy" else ORDER_ACTION_SELL, "symbol": self._symbol + '/' + self._contract_type, "price": order_info["price"], "quantity": order_info["volume"], "trade_type": trade_type } order = Order(**info) self._orders[order_no] = order order.trade_quantity = None order.trade_price = None if order_info.get("trade"): quantity = 0 price = 0 amount = 0 count = len(order_info.get("trade")) for trade in order_info.get("trade"): order.role = trade.get("role") quantity += float(trade.get("trade_volume")) amount += float( trade.get("trade_volume") * trade.get("trade_price")) price = amount / quantity order.trade_quantity = int(quantity) order.trade_price = price 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) # publish order logger.info("symbol:", order.symbol, "order:", order, caller=self)
def _get_version(self): """ get software version """ logger.info("version:", VERSION, caller=self)
def stop(self): """Stop the event loop.""" logger.info("stop io loop.", caller=self) self.loop.stop()
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"] if item["delta"] else 0 o_gamma = item["gamma"] if item["gamma"] else 0 o_theta = item["theta"] if item["theta"] else 0 o_vega = item["vega"] if item["vega"] else 0 option_delta = o_delta + o_margin_balance #增加delta对冲,使用期货对冲。 accounts, error = await self.swap_trader.rest_api.get_account_position( self.swap_symbol) if error: logger.error(self.strategy, "get swap 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.swap_volume_usd * int( long_position) / float(long_last_price) if short_position: delta_short = self.swap_volume_usd * int( short_position) / float(short_last_price) swap_delta = margin_balance - delta_short + delta_long t_delta = option_delta + swap_delta orders_data = [] # 对冲对应数量的币 if abs(t_delta) >= self.delta_limit: if t_delta > 0: # 开空单 price = 0 volume = int(t_delta * long_last_price / self.swap_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, "lever_rate": 10 }) else: # 开多单 price = 0 volume = abs( int(t_delta * long_last_price / self.swap_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, "lever_rate": 10 }) if orders_data: order_nos, error = await self.swap_trader.create_orders( orders_data) if error: logger.error(self.strategy, "create swap order error! error:", error, caller=self) else: logger.info(self.strategy, "create swap orders success:", order_nos, caller=self)
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)