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

如何异步调用函数?币安订单监控程序异步执行异常问题

问题解决:Binance异步订单监控无法执行后续代码

核心问题

你编写的new_position是同步阻塞函数,内部的while死循环会持续占用主线程,导致调用该函数后,后续代码完全没有执行机会。哪怕尝试用async修饰函数,只要内部还是同步API调用+死循环,依然会阻塞事件循环,无法实现后台运行的需求。

修复方案

1. 切换到Binance异步客户端

Binance官方提供了异步版本的客户端,配合asyncio可以避免阻塞主线程,先替换导入:

from binance.asyncio.client import Client as AsyncClient

2. 重构new_position为异步函数

将所有同步Binance调用替换为异步版本,同时在监控循环中加入休眠,避免API限流:

class Position:
    async def new_position(side, symbol, price, stopl, takep):
        print('OK')
        close_side = "SELL" if side == "BUY" else "BUY"

        # 计算仓位(异步调用)
        b = await async_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

        # 获取精度参数(异步版本)
        info_exchange = await async_client.futures_exchange_info()
        q_size = None
        price_size = None
        for item in info_exchange['symbols']:
            if item['symbol'] == symbol:
                for f in item['filters']:
                    if f['filterType'] == 'LOT_SIZE':
                        q_size = f['stepSize']
                    elif f['filterType'] == 'PRICE_FILTER':
                        price_size = f['tickSize']
                break

        # 精度处理
        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)

        # 提交开仓及止盈止损订单(异步)
        await async_client.futures_change_leverage(symbol=symbol, leverage=info.laverage)
        buyorder = await async_client.futures_create_order(
            symbol=symbol, side=side, type="MARKET", quantity=q, isIsolated='TRUE'
        )
        stop = await async_client.futures_create_order(
            symbol=symbol, side="SELL", type="STOP_MARKET", stopPrice=stopl, closePosition="true"
        )
        take = await async_client.futures_create_order(
            symbol=symbol, side="SELL", type="TAKE_PROFIT_MARKET", stopPrice=takep, quantity=take_q
        )
        
        # 异步监控订单状态
        while True:
            orders = await async_client.futures_get_open_orders(symbol=symbol)
            if len(orders) == 1:
                try:
                    await async_client.futures_cancel_order(
                        symbol=symbol, orderId=take['orderId']
                    )
                    break
                except Exception as e:
                    print(f"取消订单失败: {e}")
                    break
            # 每2秒查询一次,避免触发API限流
            await asyncio.sleep(2)

3. 异步启动任务,不阻塞后续代码

使用asyncio.create_task启动订单监控任务,主线程会直接跳过任务执行后续代码:

# 初始化异步客户端
async_client = AsyncClient(api_key=info.api, api_secret=info.secret_api, testnet=False)

# 启动订单任务,后台运行
asyncio.create_task(Position.new_position("BUY", "BTCUSDT", 30000, 29000, 31000))

# 后续代码会正常执行
print("订单任务已启动,继续执行后续逻辑...")

4. 适配Discord Bot的异步环境

因为你使用的discord.ext.commands.Bot本身基于asyncio,直接在命令函数中使用create_task即可:

@DS.command()
async def start_trade(ctx):
    # 启动后台监控任务
    asyncio.create_task(Position.new_position("BUY", "BTCUSDT", 30000, 29000, 31000))
    await ctx.send("交易任务已启动")
    # 此处代码会立即执行,无需等待监控任务结束

关键注意事项

  • 必须使用Binance异步客户端,同步客户端的所有调用都会阻塞线程
  • 异步循环中必须加入asyncio.sleep,否则会高频请求API触发限流
  • 用create_task而非直接await,才能让任务后台运行,不阻塞主线程

内容的提问来源于stack exchange,提问作者Wolky

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 11:36:14