You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 07:55:19