Keyboard Shortcuts
Likes
Search
non-simultaneous clients w/ different ID#s won't receive price ticks
I've noticed what appears to be a bug in the 10.x versions of TWS/IBGateway.
After signing into the IBGateway (or TWS) application, a client program can't get ticks for a stock unless subsequent invocations use the same client ID as the first instance which requested those ticks. This wasn't how things worked in the 9.x versions. Indeed, the documentation claims that up to 24 clients can be connected at the same time. This would lead me to believe that there shouldn't be any problems with clients that connect and disconnect one after another. This is happening when requesting both live and delayed/frozen data. Also, it's happening with real money as well as demo accounts. Basically, it always happens in these circumstances: if your client connects with ID x, requests market data for a particular stock, and disconnects as soon as it gets a price tick. Then, the next client to connect won't be able to get any price ticks for that particular stock unless it also connects with the same ID #. Has anyone else noticed the same problem? There's some example code written in Python located but the problem also happens in C++ (and I assume all the other supported languages). This makes me think there's a buggy Java destructor in the 10.x branch of the API implementation... any thoughts? |
¿ªÔÆÌåÓýI think your claim is rather too strong. ? There may well be a bug as you suggest (I need to do my own test in another language to confirm it ¨C I¡¯m not equipped for Python), but it¡¯s a very restricted circumstance. Your sample code is asking for delayed frozen data. Then it¡¯s disconnecting as soon as it receives the very first price tick, without even checking what the tick type is. ? So it¡¯s a totally unrealistic scenario. ? Perhaps you can narrow it down a bit more. Does it still happen if you disconnect after the second tick is received? If not, then that is useful evidence, and would be helpful to people trying to assess whether there¡¯s a problem here that might affect them. If it does, then what about the third tick, or if you wait for say 5 millisecs, 10 millisecs, 1 second, before disconnecting? Similarly what happens if you disconnect immediately when you receive the first tick, but then delay for a short time before actually exiting? ? I can certainly confirm that the normal usage of requesting non-delayed non-frozen data, making some sort of sensible use of the stream, and then disconnecting, works just fine with multiple clients either simultaneously or serially. ? So as far as I¡¯m concerned, with what you¡¯ve said so far, there is nothing in this to prevent the vast majority of API users working with the 10.nn versions. ? Nevertheless a bug is a bug, so it probably should be fixed assuming it can be confirmed. ? |
First, sorry for the lengthy post. TLDR:? The sample code is a cut down, bare bones, test case meant to do nothing but tickle the inner-workings of TWS/IBGW 10.x in a way that highlights the core problem. It has no other purpose.
My personal real-world use case is more complex, naturally, but it doesn't make sense to share that code since it will certainly confuse the demonstration of the bug. That said, it's not a big stretch to simply add some "useful" check of the tick-type (9 is a good example), print the price and then exit. Thus you get a program which prints yesterday's close... granted it's a basic program. But, it's important IMHO to focus on the bug itself. And, as you suggest, a bug is a bug so basic programs should work just as well as more complex ones. Indeed, if the most basic programs don't work then there's no solid foundation to build more complex programs. Also, the sample code only requests delayed frozen data so it can be used with a trial account. That line can be deleted or commented; the problem will still occur. As far as your suggestion to narrow down the scope goes, it is well-taken. I wish I could give additional insight as to what exactly triggers the problem. As mentioned earlier however, this sample code is as simplified as possible given the knowledge about the issue so far. Credit should go to IB support for providing the bulk of this example code as they've been helping me isolate the issue for the last four months. Thanks Andrew! It's certainly possible there is some sequence of necessary events that can prevent the problem from occurring. Unfortunately, I don't know such a sequence and I have tried many types of things you suggest (sleeping here, exiting somewhere else, etc). If you (or anyone else for that matter) discover something of that nature, posting it would be hugely appreciated. Please feel free to leave comments on the github page as well. You say... I can certainly confirm that the normal usage of requesting non-delayed non-frozen data, making some sort of sensible use of the stream, and then disconnecting, works just fine with multiple clients either simultaneously or serially.but, if you are using 10.x, I suggest you double and triple check. The test case as outlined on the github page works perfectly 100% of the time with TWS/IBGW 9x; not so with 10.x. Granted, using multiple clients in a serial (non-simultaneos) manner may not be common and so you could be mistaken in your certainty. Actually following the instructions on the github page and exercising the test case precisely is the best indicator IMHO; again that is it's sole purpose. Also, if you really think your code is susceptible to this problem, run it against 9.x too... the ultimate problem is the client will hang indefinitely so it should be easy to spot. However, if you're running clients inside of the issue could be obscured. Again, the problem only happens for clients that are genuinely serial (i.e. non-simultaneos). If, e.g., you start one client, then another, exit the first, and start a third... the third won't have a problem. Testing has shown it's a resource acquisition issue and that TWS/IBGW internal data structures are not corrupted until *all* previous clients have disconnected and exited. Then, only when all the previous clients disconnect, the new client programs exhibit the problem. It should go without saying that testing this should be done in a "clean room" environment. Although the problem exists in "live" real-money environments too, it's just wise to avoid using those during trading hours. That said, if you want to shut down all your software after hours, and give the test a go then I personally don't see a problem with that. I can't be held responsible for any catastrophies though ;-) Hopefully I've addressed the concerns you have and helped clarify things a bit. If there's anything else don't hesitate to ask here, or on the github page. P.S. Richard, if you haven't played at all with Python yet I encourage you to do so. Not just for working with TWS/IBGW but there's so much cool new development happening with it that it's definitely worth dabbling a little. I'm not sure what you mean by "not being equipped"... it should be really easy to install on any platform. In fact, most new Linux distributions come with it by default. But in case: https://www.python.org/downloads/ |
¿ªÔÆÌåÓýNo problems with the lengthy post, and thanks for the detail. ? I can confirm what you¡¯re observing, after doing some quick and not-very-carefully controlled experiments earlier this evening. Rather than write new code, I just modified the code of an existing application which allows me to specify the client id explicitly on each run. But I need to do this in a more systematic way to try and tease out the conditions that are necessary to make this happen. I know you¡¯ve probably done all this already, but I may just come across something new that throws additional light on it. ? I can also re-assert that my various API programs are definitely not suffering from this issue, and I¡¯d be very surprised if any ¡®normal¡¯ API program (if there is such a thing!) were to be affected by it. My gut feel is that the early disconnection and program exit may well have something to do with it, but I certainly wouldn¡¯t put my money on that until I¡¯ve done more controlled testing. ? So I¡¯ll try to find time for some of that tomorrow morning. ? Regarding Python, I understand exactly why it has gained so much popularity in recent times, and if I had the time to explore it I could probably find odd use cases here and there for it, but the simple fact is that I have a massive investment in .Net and VB6 (believe it or not), and to a lesser extent in Java, and Python just doesn¡¯t fit in there (and I have zero spare time¡I shouldn¡¯t be looking at this current issue, but it¡¯s sort of grabbed my attention). ? Richard ? ? From: [email protected] <[email protected]> On Behalf Of buddy
Sent: 15 September 2022 15:50 To: [email protected] Subject: Re: [TWS API] non-simultaneous clients w/ different ID#s won't receive price ticks ? First, sorry for the lengthy post. TLDR:? The sample code is a cut down, bare bones, test case meant to do nothing but tickle the inner-workings of TWS/IBGW 10.x in a way that highlights the core problem. It has no other purpose.
but, if you are using 10.x, I suggest you double and triple check. The test case as outlined on the github page works perfectly 100% of the time with TWS/IBGW 9x; not so with 10.x. Granted, using multiple clients in a serial (non-simultaneos) manner may not be common and so you could be mistaken in your certainty. |
Oh, great! Thank you for showing interest and taking time to look into this. A second pair of eyes is always helpful and I definitely value your contribution.
Merely confirming the same observation, but in your environment, is a big consolation. I use Linux almost exclusively and have managed to reproduce the problem in a Windows 10 Home virtual machine too (using Python). But a VM and bare metal aren't the same thing. Not to mention your network configuration is probably different than mine (along with a slew of other things). Just having another person see the same effect but on native Windows (with VB? C#?) is notable. And, knowing that I'm not alone is oddly reassuring. Burying oneself in the intricacies of a tricky problem can get awefully lonely sometimes, lol. Al that said, today IB support acknowledged that "TWS appears to fail to properly clean up its own connection to the backend market data farm on behalf of the requesting API client, and this blocks subsequent API clients from making equivalent requests". I'm hoping they'll get a fix in at some point. It's a low priority issue to them... but some priority is better than no priority :-) If I hear anything new I'll post it here. Thanks again. |
¿ªÔÆÌåÓýI¡¯ve managed to clarify exactly what the cause of this problem is, and it couldn¡¯t be much simpler to describe. ? [It¡¯s actually very easy to demonstrate the bug using IB¡¯s own API sample programs, and you might want to feed this back to IB (though it sounds like they¡¯re getting a handle on it themselves). See the ¡®what to do¡¯ below.] ? The issue occurs when the first subscriber to a specific reqMktData() stream disconnects from the API without calling cancelMktData90, and before any other client (with a different clientid) tries to request the same data. ? It doesn¡¯t matter how long the first stream is running for, or whether it¡¯s in the same or a different machine than the next requester. ? Therefore it¡¯s vital to ALWAYS call cancelMktData() before calling disconnect(), even in error situations. ? This explains why I haven¡¯t had any issues with this problem in my own software: everything is always tidied up nicely before disconnecting. But now that I know this crucial fact, I¡¯ll actually make some improvements to my code base to ensure this happens at the lowest level (there is only a single module in my platform that has any interaction with the TWS API, so there¡¯s only one place that this needs to be done: it has a table that maintains the state of all tickers, so it¡¯s easy to cancel them one by one). ? Here¡¯s what to do using the Visual Basic sample at \tws-api\samples\VB\VB_API_Sample (the Java sample works in much the same way but will need to be built first if it hasn¡¯t been used before ¨C actually that may be true of the Visual Basic sample too, but that¡¯s much easier to build with Visual Studio). ?
? So thanks very much for catching this, and let¡¯s hope IB get it sorted soon. ? Richard ? |
I previously thought that could be a solution too and so I actually tried using cancelMktData before disconnecting as well. I just tried it again and it doesn't solve the problem.
However, it does appear to solve the problem for you Richard because... Your step 8 sets the Client Id back to 1 (which was the original Client Id the request was made with). The problem is that no other Client Id can get the stream. If you change step 8 to use an ID that is not the same ID as step 2 you should see what I mean. In a nutshell, with 10.x you have to go back and use the same Client ID that you used the very fist time; this wasn't the case with 9.x because it cleaned up the internal connections properly. LMK if this makes sense. |
In other words... once all clients disconnect, you MUST re-connect with the same ID that the first connection was made with. It's a ridiculous requirement, I know... but that's the nature of this bug. TWS/IBGW 9.x cleaned up internal connections correctly(tm) and so you could use any Client ID you wanted (even after all previous clients disconnected).
|
¿ªÔÆÌåÓýOk, maybe I wasn¡¯t explicit enough. ? The point of step 7 is to demonstrate your original observation that after the first connection is broken, another client cannot get the data for that same security. I¡¯m sure you¡¯re happy with that. ? The point of step 8 is to demonstrate that even though another client (ie with a different client ID) cannot get the data, reconnecting with the original client id works, and that was also part of your original claim, so I¡¯m sure you¡¯ll agree with that. ? Let¡¯s call all this Case 1. ? And what I didn¡¯t say, and perhaps should have, we can call Case 2. First disconnect the clients, THEN RESTART TWS. Now repeat the sequence, but this time in step 5 click the ¡®Cancel Mkt Data¡¯ button BEFORE ?clicking ¡®Disconnect¡¯: ?then the subsequent step 7 works fine. ? And there is also a Case 3. Here start again with a fresh instance of TWS then do steps 1 to 5 for the first client id (so don¡¯t cancel or disconnect). Now repeat steps 1 to 5 for the second client id, and the data will stream for that one as well. If you now disconnect one or both clients without first cancelling the data, you can subsequently connect with any client id and it will work fine. ? So in other words, with a fresh TWS instance, the first time you get market data for any particular contract you need to make sure you cancel the market data first if you disconnect before a different client requests data for that contract. Then everything works fine after that whether you cancel data before disconnecting or not. ? The only sensible rule that ensures that everything is always ok is to always cancel market data before disconnecting. ? I do this all day every trading day of the week: I have some clients ¨C for example data collection programs - that make their data requests as soon as TWS starts on Sunday evening, and keep the same tickers all week (including re-establishing market data if necessary after nightly resets or other breaks in service). And I have other programs that I run on an as-required basis, using many of the same contracts, some of which I run many times a day, and I never experience the slightest problem. ? I hope this clarifies things. ? ? ? From: [email protected] <[email protected]> On Behalf Of buddy
Sent: 16 September 2022 19:17 To: [email protected] Subject: Re: [TWS API] non-simultaneous clients w/ different ID#s won't receive price ticks ? I previously thought that could be a solution too and so I actually tried using cancelMktData before disconnecting as well. I just tried it again and it doesn't solve the problem. |
Thanks for this Richard. I know there are a number of workarounds and since I am "Linux folk" I haven't looked closely at what you're proposing since it's heavily based on VB.
At the end of the day though, I'm just happy IB has acknowledged this is a bug(tm) w/ 10.x; even if it's subtle and minor by some standards. I've got a workaround of my own waiting to be merged if I'm forced to retire 9.x for some reason (*cough* log4shell *cough*)... and I'm optimistic they'll get around to fixing it at some point. It's a pretty small thing to fix for a capable dev. Anyway... It's too bad we don't have access to their Java source for issues like this. In open-source land I think these things get identified and fixed much faster. But, sometimes you eat the bear and sometimes the bear eats you! c'est la vie |
Unfortunately I'm late to the party. I am working on upgrading from version 9.x to API 10.19 and Gateway 10.22. I have just spent two days figuring out why I got such strange behavior from reqMktData() after upgrading to version 10.x. A reference in another, more recent, thread pointed me to here. What is happening in my case:
Program A connects to Gateway, using clientId1. One of its activities is getting streaming data for an instrument, using reqMktData(). After it has completed its activities it sends cancelMktData() and finally disconnects clientId1. Some seconds later program B connects to Gateway, using clientId2. After a while it tries to use reqMktData() for the same instrument. It does not receive any data. It then sends cancelMktData() and disconnects clientId2. All my programs are coded in Java. My understanding from this thread is that I am not allowed to use two different numbers clientId1 and clientId2, but that both programs must use and re-use the same clientId number. |
On Wed, Apr 5, 2023 at 02:02 PM, J G wrote:
Well, IDK if "not allowed" is the right term but yes... there appears to be a race condition problem introduced in some of the 10.x branch's clean-up code that complicates this. Off the top of my head I have two recommendations:
If there are some long running computations that are necessary, off-load them to separate processes or threads and manage the IPC on your own. If you don't rely on shared data and keep things on the stack... thread-safety should be easy to guarantee. The later option of keeping all data collection on a single thread is my personal preference. And, I've previously mentioned that using makes this pretty easy. But, it's been a long time since I've used Java and so, although there may be an analogue, you'll have to research that solution yourself. Perhaps someone else can help there. I'm sure there are other solutions that achieve a more fine-grained, perhaps higher-throughput, solution but IMHO it likely won't be worth the trouble. -Good luck |
Years ago I used to use only one client Id and kept it open almost the entire week (my system runs from Sunday evening until the following Saturday morning). But then IB started to develop problems and the connection would sometimes "go dead". I was then advised to use multiple client Id's: create a new one when needed and discard it after use (within limits of course). That required quite some work from me as I had to rewrite a lot of my software. The structure I used for assigning client Id's is at odds with the limitations which have now popped up in TWS/Gateway 10.x. Meaning that I again have to rethink my strategy related to client Id assignment. And have to update all my software accordingly.
IB is good at keeping me busy with meaningless activities that don't add any value. |
On Fri, Apr 7, 2023 at 03:06 PM, J G wrote:
The Fed also seems to be very good at this. Anyway... I empathize and wish IB could give more priority to fixing the bug too. OTOH, good software engineers don't come cheap, so IB needs to triage within the constraints of the labor market. It's a tricky balancing act. And, if experience has taught me anything, the very moment you finish what's necessary to accommodate the foibles of their new "improved" version, they'll fix the bug and your time will have been wasted. Ultimately, the following helps me come to terms with that sort of thing:
Of course, IDK how much all this is specifically related to software engineering or the IB API. ?³å(¥Ä)³å/? |
btw, there seems to be a funky character escaping issue w/ the groups.io web-client in order to get the right arm of the shruggie to show up you need to place 3 backslashes in a row instead of just one ?°À³å(¥Ä)³å/? accept my most sincere apologies for overlooking this and mangling the previous emoji |