ib_async/ib_insync事件回调后执行代码的报错解决求助
问题解决:ib_async事件回调调用异步方法引发的RuntimeError
问题原因
你遇到的RuntimeError: cannot enter context错误,核心原因是在同步事件回调函数里直接调用了ib_async的异步方法(ib.qualifyContracts)。ib_async基于asyncio实现,同步回调的执行上下文已被占用,异步方法尝试创建新上下文时就会触发冲突。
解决方案
要解决这个问题,需要把异步操作放入ib的事件循环中执行,具体步骤:
- 将包含异步调用的函数改为异步函数
- 在同步回调里,用
ib.runAsync()把异步任务提交到事件循环,避免上下文冲突
修改后的代码
#!/usr/bin/env python # coding: utf-8 import settings from ib_async import * util.patchAsyncio() ib = IB() connection = ib.connect(settings.host, settings.port, clientId=settings.master_client_id) async def options_trade(trade): print ("Getting option greeks and other data...") contracts = [trade.contract] print (contracts) # 异步调用qualifyContracts,必须加await await ib.qualifyContracts(*contracts) # 后续获取IV、greeks的逻辑也需用异步方式处理,比如请求市场数据 # 示例:reqMktData获取greeks # ticker = ib.reqMktData(trade.contract, '', False, False) # await ticker.updateEvent def on_exec_details(trade:Trade, fill:Fill): print ("Start execution details") print ("Order status: ", trade.orderStatus.status) print ("Fill execution price: ", fill.execution.price) print (trade.contract) print (trade.contract.secType) if trade.contract.secType != 'OPT': print ("Not an option contract, will not load greeks") else: print ("This is an option contract, will load greeks and IV data and save to spreadsheet") print (trade.filledEvent) # 用runAsync将异步任务提交到ib的事件循环 ib.runAsync(options_trade(trade)) print ("End execution details") ib.execDetailsEvent += on_exec_details ib.run()
额外说明
ib.run()是ib_async启动事件循环的正确方式,无需替换- 后续获取IV和greeks时,比如调用
reqMktData,同样需要用异步等待逻辑(如await ticker.updateEvent),否则会触发同类上下文问题 util.patchAsyncio()是必要的兼容性修复代码,保留即可
内容的提问来源于stack exchange,提问作者algebraist
相关产品推荐
相关产品推荐

