I'm developing an API (using Sanic) which is a gateway to IB, using ib_insync This API exposes endpoints to place a new order and getting live positions, but also is in charge to update order statuses in a DB using the events of ib_insync.
My question is - is it possible to have the API connect only once to IB when it goes up, and re-using the same connection for all requests?
I'm currently connecting to IB using connectAsync
on every request. And while this is working - the API will not receive events if not currently handling a request.
This is one endpoint code, for reference
@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)
So I wish to not use the with
statement, and just use a global ib connection.
When I'm connecting on the module init (using connectAsync
), every later call that is async, like qualifyContractsAsync
, just hangs. Debugging showed me that it hangs on asyncio.gather
which means I'm doing something wrong with the event loops.
I'm not familiar with this particular connection, but yes it should be possible. Presumably the with
statement is opening and closing the connection.
Instead, open and close it with a listener.
@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()