erdewit/ib_insync

cancelMktDepth causes errors

nealeyoung opened this issue · 4 comments

I'm getting errors calling cancelMktDepth. Looks like it clears domBids and domAsks right away [1], but IB server keeps sending the level2 updates for a while, and when the decoder decodes them it tries to access domBids and domAsks, which have been cleared, causing an error. Below is a small example demonstrating the issue. It looks like there is a second issue as well with "can't find the subscribed market depth..",

BTW my version.py shows version_info = (0, 9, 86), but for some reason the line number in wrapper.py in the error message I get is line 921, but in the source here it looks like line 975 (?).

[1]

ticker.domBids.clear()

[2]
dom[position] = DOMLevel(price, size, marketMaker)

-Neal

--- code demonstrating the issue:

import ib_insync as ibs

ib = ibs.IB()

ib.connect()

ib.sleep(1)

contract = ibs.Stock("SPY", "SMART", "USD")
ib.qualifyContracts(contract)

ib.sleep(1)

ticker = ib.reqMktDepth(contract, numRows=50, isSmartDepth=True)

ib.sleep(2)

ib.cancelMktDepth(contract)

ib.sleep(2)

# now we get the following errors:
#
# Error 310, reqId 15049: Can't find the subscribed market depth with tickerId:15049
# Error for updateMktDepthL2:
# Traceback (most recent call last):
#   File "/Users/neal/Desktop/IB/curses_app/ib_insync/decoder.py", line 187, in handler
#     method(*args)
#   File "/Users/neal/Desktop/IB/curses_app/ib_insync/wrapper.py", line 921, in updateMktDepthL2
#     dom[position] = DOMLevel(price, size, marketMaker)
#     ~~~^^^^^^^^^^
# IndexError: list assignment index out of range

ib.disconnect()

p.s. it's conceivable that this error will show up only when the connection to IB has relatively high latency (e.g. 40ms). It's possible that it may occur only because of packets that are sent by IB after the cancel request is sent to IB but before the request is received there (after which IB presumably stops sending update packets).

I've never seen this happen before, but also note cancelMktDepth() has an extra parameter for isSmartDepth too and it must match the original request.

Looks like it clears domBids and domAsks right away [1], but IB server keeps sending the level2 updates for a while, and when the decoder decodes them it tries to access domBids and domAsks, which have been cleared, causing an error.

Yes, that is absolutely right. The error is harmless (just some logging) but I'll fix it by moving the clearing of domBids and domAsks from cancelMktDepth to reqMktDepth. They have to be cleared somewhere in case an instrument gets subscribed again (after having been canceled).

Thanks Matt. FYI if I change the cancellation call to

ib.cancelMktDepth(contract, isSmartDepth=True)

I don't get the errors any more.