"Head First Design Patterns" has some entertainment value, plus Java code. "Effective Java" has strong, positive reviews at Amazon -- will the sequel be better? As there is a lot of pre 1.5 code out there, it could be useful to know how things were done earlier. I'll be looking for it. At some point I want to do a bot with an abstract broker and data vendor, but for now will continue with what I've got. Doing that will give me some more experience working with a broker API -- trying to recover from the "lost order" problem -- and then I'll be in a better position to decide what sort of methods an abstract broker should offer.
You might be better to create Broker and Feed interfaces rather than abstract classes. You can then implement Broker and Feed in the same class for TWS API and thereby sidestep the absence of multiple inheritance in Java. As a side note, I don't think there is really that much difference between 1.4 and 1.5. Generics and java.util.concurrent are probably the main things.
Thanks for the idea, dcraig. With IB, which is a broker and data-vendor, it would be necessary to be careful about instantiating the broker and data-vendor, otherwise there would be a situation where the concrete broker and data-vendor would both try to connect to TWS. I think that "class IB extends Broker implements EWrapper" side-steps the multiple inheritance limitation -- IB inherits from Broker but has an EWrapper interface. No? By the way, I did buy the "Head First" book and look forward to reading it.
Oh, I see. "class IB" cannot extend 'Broker' and 'DataProvider'. It would have to be something like: "class BrokerIB extends Broker implements EWrapper" and "class DataVendorIB extends DataVendor implements EWrapper" unless it isn't possible to have two classes that implement 'EWrapper'. In that case it might be possible to split 'EWrapper' into two interfaces: one for the brokerage functionality and another for the data vendor functionality, but that could create a maintenance problem whenever IB updates the API.
"public class InteractiveBrokers implements com.ib.client.EWrapper, IBroker, IDataFeed" Thanks. That's close to triple-inheritance.
Preparing to find out what can be done about a "lost order." It looks as though the API doc. on IB's website may be out of date: there is no 'winError' method. 'setServerLogLevel' appears to work -- entries that appear to be what is described in the doc. do appear in the log (on the TWS side). 'execDetails' will be called when either 'reqExecutions' is called or when an order is filled; unfortunately, the bot didn't override the stub in Wrapper.java. The doc. indicates that error(int id, int code, String msg) may be called with an 'id' that is an 'orderId' or a 'tickerId'; however, I have only seen an 'id' of -1. How can 'error(int, int, String)', 'orderStatus',. and 'execDetails' be used together? It may be another ten years before another order is lost, so there may have to be some trial-and-error game played. Hopefully, it can be done with IB's 'Sample' app. using valid and invalid orderId(s). 'openOrders' may also be useful.
Yesterday, there was a TWS<->IB disconnection and when TWS tried to log back into IB a dialog box announcing a new version appeared and waited for a yes/no answer. So, I upgraded TWS. Again, yesterday, without providing a "trusted" ip address in the API config., when the bot started, a dialog box about whether to allow the connection appeared. So, I re-configured with a trusted ip address. Again, yesterday, with the "fire openorder ..." checkbox checked in API configuration, this is the sequence of callbacks after an order is placed: execDetails openOrder orderStatus openOrder orderStatus The 'openOrder' and 'orderStatus' calls did occur twice for a quantity one market order. The id, status, quantity and remaining arguments to orderStatus were the same in both cases. At some point, it should be checked whether all the arguments to 'openOrder' and 'orderStatus' are the same for both calls. Without "fire openorder ..." checked, the sequence is: execDetails orderStatus orderStatus Today, there was an IB<->TWS disconnection/reconnection, all of which occurred while the bot was sleeping, waiting to place its entry order. There was no confirmation of the order (no orderStatus call); there was no execDetails call; there was no openOrder call -- but TWS received the order and filled it. Unfortunately, setServerLogLevel() had not been called, so there may be incomplete info. in the server-side log. Several days ago, there was a TWS<->IB disconnect/reconnect, then an order was placed and orderStatus was not called. It remains to be seen whether the extra orderStatus/openOrder calls are redundant. If they are, why should they be called twice? Is/Was once not enough? If two calls are better than one, shouldn't three calls be even better? At this time I am not optimistic that a bot can work reliably with TWS. It would be helpful if IB had some API order placement usage scenarios. I may place a trouble ticket with IB after checking whether the orderStatus and openOrder info. is redundant, but it will have to wait because I have decided to take a vacation.
This is a well-known bug in the IB's API. You can ignore the duplicate callback. If the order was executed during a temporary disconnect between TWS and the IB server, neither orderStatus() nor execDetails() would be called. You have to request executions explicitly when you detect that the connection between TWS and the server was re-establised. Look at errors 1101 and 1102 signaling a successful re-connection.
Thanks for the info, nonlinear. Both times when the order was "lost," there was a TWS disconnect/reconnect that happened before any order was placed -- the reconnect/login succeeded before any order was placed. It may be a repeatable problem: start the bot, then once it goes to sleep waiting for the entry time, disconnect TWS from the net, wait for the disconnect message, then reconnect TWS to the net, then wait for the first order to be submitted to see whether the order gets lost -- if so, another TWS bug may become well known. The workaround might be: if there is a disconnect/reconnect, try: after TWS reconnects, disconnect/reconnect the bot or, maybe even, after TWS reconnects, disconnect the bot, then restart TWS, then restart the bot.