如何修复sys:1: RuntimeWarning: coroutine 'Position.new_position'未被await的问题?
解决Binance订单程序的协程未执行问题
问题根源
你遇到的RuntimeWarning: coroutine 'Position.new_position' was never awaited,本质是异步函数调用未触发执行,只是创建了一个协程对象;同时Position.new_position作为类方法缺少必要的参数定义,直接调用会引发错误;另外若直接用await调用该函数,会阻塞Discord命令的响应,不符合你“启动函数后程序继续执行”的需求。
分步解决方案
1. 修正new_position方法定义
给new_position添加@staticmethod装饰器(因为该方法不需要访问类/实例属性),确保异步方法能被正确调用:
class Position: @staticmethod async def new_position(side, symbol, price, stopl, takep): await asyncio.sleep(60) print('OK') if side == "BUY": close_side = "SELL" else: close_side = "BUY" # 计算数量逻辑不变 b=client.futures_account_balance() b = pd.DataFrame.from_dict(b) b = b.loc[b['asset']=='USDT'] balance = float(b['balance'].values) * 0.05 q = balance / price * info.laverage # 精度处理逻辑不变 q_size = get_qsize(symbol) price_size = get_pricesize(symbol) price = round_step_size(float(price), float(price_size)) stopl = round_step_size(float(stopl), float(price_size)) takep = round_step_size(float(takep), float(price_size)) q = round_step_size(q, q_size) take_q = round_step_size(q/2, q_size) # 开单逻辑不变 client.futures_change_leverage(symbol=symbol, leverage=info.laverage) buyorder = client.futures_create_order(symbol=symbol, side=side, type="MARKET", quantity=q, isIsolated='TRUE') stop = client.futures_create_order(symbol=symbol, side=close_side, type="STOP_MARKET", stopPrice=stopl, closePosition="true") take = client.futures_create_order(symbol=symbol, side=close_side, type="TAKE_PROFIT_MARKET", stopPrice=takep, quantity=take_q) # 监控逻辑不变 a = True while a == True: print('OK') await asyncio.sleep(60) orders = client.futures_get_open_orders(symbol=symbol) if len(orders) == 1: try: client.futures_cancel_order(symbol=symbol, orderId=take['orderId'], timestamp='true') a = False except: a = False
2. 后台启动协程,避免阻塞命令响应
在open_position命令中,用asyncio.create_task启动协程,这样协程会在后台执行,Discord命令能立即响应:
@DS.command(aliases=["open"]) async def open_position(ctx, side, symbol, price, stopl, takep): global pos_list print(price) # 创建并启动后台协程 task = asyncio.create_task(Position.new_position(side, symbol.replace("PERP", ""), float(price), float(stopl), float(takep))) pos_list[symbol] = task # 保存任务对象,方便后续取消(可选) print(pos_list) await ctx.send("订单监控任务已启动") # 给用户反馈(可选)
3. 修复平仓逻辑的参数问题
原close_position方法依赖Position实例属性,但之前的实现未保存订单信息,建议调整为实例化类,更易维护:
class Position: def __init__(self, side, symbol, price, stopl, takep): self.side = side self.symbol = symbol self.price = price self.stopl = stopl self.takep = takep self.close_side = "SELL" if side == "BUY" else "BUY" self.buyorder = None self.stop_order = None self.take_order = None async def start(self): await asyncio.sleep(60) print('OK') # 计算数量 b=client.futures_account_balance() b = pd.DataFrame.from_dict(b) b = b.loc[b['asset']=='USDT'] balance = float(b['balance'].values) * 0.05 q = balance / self.price * info.laverage # 精度处理 q_size = get_qsize(self.symbol) price_size = get_pricesize(self.symbol) self.price = round_step_size(float(self.price), float(price_size)) self.stopl = round_step_size(float(self.stopl), float(price_size)) self.takep = round_step_size(float(self.takep), float(price_size)) q = round_step_size(q, q_size) take_q = round_step_size(q/2, q_size) # 开单并保存订单信息 client.futures_change_leverage(symbol=self.symbol, leverage=info.laverage) self.buyorder = client.futures_create_order(symbol=self.symbol, side=self.side, type="MARKET", quantity=q, isIsolated='TRUE') self.stop_order = client.futures_create_order(symbol=self.symbol, side=self.close_side, type="STOP_MARKET", stopPrice=self.stopl, closePosition="true") self.take_order = client.futures_create_order(symbol=self.symbol, side=self.close_side, type="TAKE_PROFIT_MARKET", stopPrice=self.takep, quantity=take_q) # 监控逻辑 a = True while a == True: print('OK') await asyncio.sleep(60) orders = client.futures_get_open_orders(symbol=self.symbol) if len(orders) == 1: try: client.futures_cancel_order(symbol=self.symbol, orderId=self.take_order['orderId'], timestamp='true') a = False except: a = False def close(self): # 平仓主订单 if self.buyorder: q = round_step_size(float(self.buyorder['quantity']), get_qsize(self.symbol)) client.futures_create_order(symbol=self.symbol, side=self.close_side, type="MARKET", quantity=q, reduceOnly='true') # 取消止损/止盈订单 try: if self.stop_order: client.futures_cancel_order(symbol=self.symbol, orderId=self.stop_order['orderId'], timestamp='true') except: pass try: if self.take_order: client.futures_cancel_order(symbol=self.symbol, orderId=self.take_order['orderId'], timestamp='true') except: pass
对应的命令修改:
@DS.command(aliases=["open"]) async def open_position(ctx, side, symbol, price, stopl, takep): global pos_list print(price) symbol_clean = symbol.replace("PERP", "") # 创建Position实例 position = Position(side, symbol_clean, float(price), float(stopl), float(takep)) # 启动后台协程 task = asyncio.create_task(position.start()) pos_list[symbol] = (position, task) # 保存实例和任务对象 print(pos_list) await ctx.send("订单任务已启动") @DS.command(aliases=["close"]) async def close_position(ctx, symbol): global pos_list symbol_clean = symbol.replace("PERP", "") if symbol in pos_list: position, task = pos_list[symbol] position.close() task.cancel() # 取消监控协程 del pos_list[symbol] await ctx.send("已执行平仓操作") else: await ctx.send("未找到该订单")
4. 额外优化建议
- 替换Binance同步客户端为
binance.AsyncClient,避免同步API阻塞异步事件循环; - 异常处理不要用
except:捕获所有异常,应针对性捕获BinanceAPIException等特定错误,便于排查问题。
内容的提问来源于stack exchange,提问作者k k
相关产品推荐
相关产品推荐

