On Wed, Jul 20, 2011 at 10:21 PM, rv
<raj...@gmail.com> wrote:
None. There is no reference to jbt being disconnected before the
following line :
Ok, good, this validates my theory. Here is what I think is happening.
Imagine the scenario when JBT submits an order, the TWS sends it to the exchange, and the connection between TWS and IB is lost (which happens occasionally). Next, the order is executed by the exchange, the confirmation is sent to IB, and IB sends it back to TWS. Since TWS is at this point disconnected from IB, the order confirmation never reaches TWS. After the connection is restored, JBT would wait indefinitely for the confirmation of execution. Another scenario is this: JBT submits an order, connection between TWS and IB is lost immediately after, so the order never reaches the IB. To work around these two situations, JBT has logic in place which makes an explicit request for executions, and attempts to find the order confirmation in the response. This logic kicks in after errorCode 1101 or errorCode 1102 are received, indicating that the connection was restored. You can see this code in Trader.java. All of this works well, except that sometimes, neither error code 1101 nor 1102 are sent after the reconnection. As a result, JBT would never invoke the explicit check for executions. So, as a fix to this problem, JBT also uses code 2104 as an indication that the connection was restored, and uses this as a trigger for the check for executions. See line 140 in Trader.java.
As it turns out, that code 2104 does not necessarily indicate that the connection with TWS was lost, but instead that the data farm is "OK".
So, in your case, as indicated in your report, here is what happened:
21:22:05.001 everything is cool and connected, JBT places order 217
21:22:05.193 JBT gets the error 2104: Market data farm connection is OK:aufarm
21:22:05.193 Because of error 2104, JBT thinks that there was a period of disconnection, so it requests executions for order 217
21:22:05.232 Only 231 milliseconds have passed since order 217 was submitted, so that order didn't get executed yet. However, JBT thinks that since there is no record of order 217, it must have been because it never reached IB because there was a disconnection.
21:22:06.001 JBT discards order 217 and places order 218
21:22:06.287 Order 218 is filled. Order 217 is also eventually filled, but JBT had previously discarded it. The end result is that both order have been executed, while JBT thinks only one got through.
So, that's the cause of the problem. As can be seen, Trader.java contains some hacks to address bugs in IB API. However, this code was put long time ago, and since them, the API was upgraded several times. So, it's quite possible that these IB API bugs were fixed. If that's the case, then the fix to your "double fill" problem is simply to replace line:
boolean isConnectivityRestored = (errorCode == 1101 || errorCode == 1102 || errorCode == 2104);
with line
boolean isConnectivityRestored = (errorCode == 1101 || errorCode == 1102);
No other code changes are necessary. However, if the IB API bug is still there (failing to send 1101 or 1102 on reconnect), then we should look for another solution. A fairly obvious alternative solution is to delay the explicit request for executions after the reconnection by a couple of seconds, if there is a pending order which was submitted recently (in the previous couple of seconds, that is). That seems rather hacky, though. If anyone can think of a better way to handle this, I am open to suggestions.