与 Sanic 保持 运行 ib_insync 联系

Keeping an always-running ib_insync connection with Sanic

我正在开发 API(使用 Sanic),它是 IB 的网关,使用 ib_insync API 公开端点以下新订单和获取实时头寸,但也负责使用 ib_insync.

的事件更新数据库中的订单状态

我的问题是 - 是否可以让 API 在 IB 启动时仅连接一次,并为所有请求重新使用相同的连接?

我目前在每次请求时都使用 connectAsync 连接到 IB。虽然这是有效的 - 如果当前没有处理请求,API 将不会接收事件。

这是一个端点代码,供参考

@app.post("/order/<symbol>")
async def post_order(request, symbol):
    order = jsonpickle.decode(request.body)
    with await IB().connectAsync("127.0.0.1", 7496, clientId=100) as ib:
        ib.orderStatusEvent += onOrderStatus
        ib.errorEvent += onTWSError
        ib.newOrderEvent += onNewOrderEvent

        contract = await ib.qualifyContractsAsync(contract)
        trade = ib.placeOrder(contract[0], order)

    return text(trade.order.orderId)

所以我希望不使用with语句,而只使用全局ib连接。

当我在模块 init 上连接时(使用 connectAsync),以后的每个异步调用(如 qualifyContractsAsync)都会挂起。调试显示它挂在 asyncio.gather 上,这意味着我在事件循环中做错了。

我不熟悉这个特定的连接,但是应该可以。据推测 with 语句正在打开和关闭连接。

相反,使用侦听器打开和关闭它。

Docs re: listeners

@app.before_server_start
async def connect(app,_):
    app.ctx.foo = await Foobar()

@app.route("/")
async def handler(request):
    await request.app.ctx.foo.do_something()

@app.after_server_stop
async def close(app,_):
    app.ctx.foo.close()