***Capture of the messages received as a result of market order being submitted. Not all fields are present, only ones I deem relevant for myself.
Msg [EXECUTION_DATA]->[(2, 37955052, 'CL', 'FUT', '20110520', 'NYMEX', 'USD', 'CLM1', '0001f4e5.4dc4368a.01.01', '20110506 11:11:31', 'DU***', 'NYMEX', 'SLD', 1, '101.95', 1687424472, 55555, 0, 1, '101.95')]
Msg [OPEN_ORDER]->[(2, 37955052, 'CL', 'FUT', '20110520', 'NYMEX', 'USD', 'CLM1', 55555, 1687424472, 'SELL', 1, 'MKT', '101.95', '0.0', 'GTC', None, 'DU***', 'O', 0, None, '0', '1', 0, None, None, None, None, 'Filled', '1.7976931348623157E308', '1.7976931348623157E308', '1.7976931348623157E308', None, None, None, 'USD', None)]
Msg [ORDER_STATUS]->[(2, 'Filled', 1, 0, '101.95', 1687424472, 0, '101.95', 55555, None)]
Msg [OPEN_ORDER]->[(2, 37955052, 'CL', 'FUT', '20110520', 'NYMEX', 'USD', 'CLM1', 55555, 1687424472, 'SELL', 1, 'MKT', '101.95', '0.0', 'GTC', None, 'DU***', 'O', 0, None, '0', '1', 0, None, None, None, None, 'Filled', '1.7976931348623157E308', '1.7976931348623157E308', '1.7976931348623157E308', '2.32', None, None, 'USD', None)]
Msg [ORDER_STATUS]->[(2, 'Filled', 1, 0, '101.95', 1687424472, 0, '101.95', 55555, None)]
Msg [OPEN_ORDER]->[(2, 37955052, 'CL', 'FUT', '20110520', 'NYMEX', 'USD', 'CLM1', 55555, 1687424472, 'SELL', 1, 'MKT', '101.95', '0.0', 'GTC', None, 'DU***', 'O', 0, None, '0', '1', 0, None, None, None, None, 'Filled', '1.7976931348623157E308', '1.7976931348623157E308', '1.7976931348623157E308', '2.32', None, None, 'USD', None)]
Msg [ORDER_STATUS]->[(2, 'Filled', 1, 0, '101.95', 1687424472, 0, '101.95', 55555, None)]
***Capture of the messages received as a result of limit order being submitted.
Msg [OPEN_ORDER]->[(3, 37955052, 'CL', 'FUT', '20110520', 'NYMEX', 'USD', 'CLM1', 55555, 1687424473, 'SELL', 1, 'LMT', '100.0', '0.0', 'GTC', None, 'DU***', 'O', 0, None, '0', '1', 0, None, None, None, None, 'Submitted', '1.7976931348623157E308', '1.7976931348623157E308', '1.7976931348623157E308', None, None, None, 'USD', None)]
Msg [ORDER_STATUS]->[(3, 'Submitted', 0, 1, '0', 1687424473, 0, '0', 55555, None)]
***Capture of the messages received as a result of stop order being submitted.
Msg [OPEN_ORDER]->[(5, 37955052, 'CL', 'FUT', '20110520', 'NYMEX', 'USD', 'CLM1', 55555, 1687424474, 'BUY', 1, 'STP', '99.18', '100.0', 'GTC', None, 'DU***', 'O', 0, None, '1', '1', 0, None, None, None, None, 'PreSubmitted', '1.7976931348623157E308', '1.7976931348623157E308', '1.7976931348623157E308', None, None, None, 'USD', None)]
Msg [ORDER_STATUS]->[(5, 'PreSubmitted', 0, 1, '0', 1687424474, 0, '0', 55555, 'trigger')]
As I've mentioned earlier, it is mimicking the FIX behaviour. Not really interested digging too much into the IB backend, I don't know if they are running FIX server as a central place for trade management or something proprietary, I know there is a FIX gateway so they are either mapping TWS API into FIX or vice-verse.
Regardless of what's in place, system has to keep track of different order statuses, hence multiple OPEN_ORDER and ORDER_STATUS messages when market order submitted. For example, order life cycle goes through Submitted, Accepted, Pending, Working, Cancelled, Filled, etc. For some (stupid) reason IB have decided not to show the status change and have 'Filled' in all messages, but still transmit all of them instead of only the final one.
You can notice that in the first OPEN_ORDER msg, the fifth field from the end does not have the value, which is commission, but subsequent messages does. I am speculating
(unfortunately), this is the msg for Submitted/Accepted/Pending order status and the next two are for the Working and Filled order status.
Submitting the limit or stop order results in a single message where you can see the status Submitted/PreSubmitted.
Never heard of that before, what a name... I personally do not like when stuff like that creeps into the software architecture, too abstract and largely unnecesary in software design, there are already plenty specific methodologies we can use to design the software and explain the software.
Having said that, I believe this is the wrong example for "idempotent operation" because the status is not the same. Those are multiple events that are changing the status. The fact that somebody in IB decided not to show it, is wrong. In such case they should be sending only one message. If, on the other hand, they don't care about the status order for market orders and process only Filled status (which I do not believe), then it's plain stupid to send multiple messages after single event.
Well, it's working and that's about it. Hardly robust, there is no structure in protocol low-level, no validation, no recovery, and list goes on and on....
Historical data msgs are same as everything else, what makes it additional nightmare is actually extremely restrictive policies regarding the amount of data you can get and the fact that it is not separated from the real-time communication, which forces you to spin-off something (I do separate process, they do that horrible Java threading).
At the first opportunity, I will ditch the data portion and retain only execution. For data, I am looking into DDF BarChart, looks well designed and platform agnostic. Thankfully no Java involved. No secret I can't stand it, nor the whole OOP, gone bezirk, mental exercise. However, I perfectly do not mind anybody enjoying it...
Msg [EXECUTION_DATA]->[(2, 37955052, 'CL', 'FUT', '20110520', 'NYMEX', 'USD', 'CLM1', '0001f4e5.4dc4368a.01.01', '20110506 11:11:31', 'DU***', 'NYMEX', 'SLD', 1, '101.95', 1687424472, 55555, 0, 1, '101.95')]
Msg [OPEN_ORDER]->[(2, 37955052, 'CL', 'FUT', '20110520', 'NYMEX', 'USD', 'CLM1', 55555, 1687424472, 'SELL', 1, 'MKT', '101.95', '0.0', 'GTC', None, 'DU***', 'O', 0, None, '0', '1', 0, None, None, None, None, 'Filled', '1.7976931348623157E308', '1.7976931348623157E308', '1.7976931348623157E308', None, None, None, 'USD', None)]
Msg [ORDER_STATUS]->[(2, 'Filled', 1, 0, '101.95', 1687424472, 0, '101.95', 55555, None)]
Msg [OPEN_ORDER]->[(2, 37955052, 'CL', 'FUT', '20110520', 'NYMEX', 'USD', 'CLM1', 55555, 1687424472, 'SELL', 1, 'MKT', '101.95', '0.0', 'GTC', None, 'DU***', 'O', 0, None, '0', '1', 0, None, None, None, None, 'Filled', '1.7976931348623157E308', '1.7976931348623157E308', '1.7976931348623157E308', '2.32', None, None, 'USD', None)]
Msg [ORDER_STATUS]->[(2, 'Filled', 1, 0, '101.95', 1687424472, 0, '101.95', 55555, None)]
Msg [OPEN_ORDER]->[(2, 37955052, 'CL', 'FUT', '20110520', 'NYMEX', 'USD', 'CLM1', 55555, 1687424472, 'SELL', 1, 'MKT', '101.95', '0.0', 'GTC', None, 'DU***', 'O', 0, None, '0', '1', 0, None, None, None, None, 'Filled', '1.7976931348623157E308', '1.7976931348623157E308', '1.7976931348623157E308', '2.32', None, None, 'USD', None)]
Msg [ORDER_STATUS]->[(2, 'Filled', 1, 0, '101.95', 1687424472, 0, '101.95', 55555, None)]
***Capture of the messages received as a result of limit order being submitted.
Msg [OPEN_ORDER]->[(3, 37955052, 'CL', 'FUT', '20110520', 'NYMEX', 'USD', 'CLM1', 55555, 1687424473, 'SELL', 1, 'LMT', '100.0', '0.0', 'GTC', None, 'DU***', 'O', 0, None, '0', '1', 0, None, None, None, None, 'Submitted', '1.7976931348623157E308', '1.7976931348623157E308', '1.7976931348623157E308', None, None, None, 'USD', None)]
Msg [ORDER_STATUS]->[(3, 'Submitted', 0, 1, '0', 1687424473, 0, '0', 55555, None)]
***Capture of the messages received as a result of stop order being submitted.
Msg [OPEN_ORDER]->[(5, 37955052, 'CL', 'FUT', '20110520', 'NYMEX', 'USD', 'CLM1', 55555, 1687424474, 'BUY', 1, 'STP', '99.18', '100.0', 'GTC', None, 'DU***', 'O', 0, None, '1', '1', 0, None, None, None, None, 'PreSubmitted', '1.7976931348623157E308', '1.7976931348623157E308', '1.7976931348623157E308', None, None, None, 'USD', None)]
Msg [ORDER_STATUS]->[(5, 'PreSubmitted', 0, 1, '0', 1687424474, 0, '0', 55555, 'trigger')]
As I've mentioned earlier, it is mimicking the FIX behaviour. Not really interested digging too much into the IB backend, I don't know if they are running FIX server as a central place for trade management or something proprietary, I know there is a FIX gateway so they are either mapping TWS API into FIX or vice-verse.
Regardless of what's in place, system has to keep track of different order statuses, hence multiple OPEN_ORDER and ORDER_STATUS messages when market order submitted. For example, order life cycle goes through Submitted, Accepted, Pending, Working, Cancelled, Filled, etc. For some (stupid) reason IB have decided not to show the status change and have 'Filled' in all messages, but still transmit all of them instead of only the final one.
You can notice that in the first OPEN_ORDER msg, the fifth field from the end does not have the value, which is commission, but subsequent messages does. I am speculating
(unfortunately), this is the msg for Submitted/Accepted/Pending order status and the next two are for the Working and Filled order status.
Submitting the limit or stop order results in a single message where you can see the status Submitted/PreSubmitted.
Quote from dcraig:
Multiple status events reporting the same status should never be a problem. The operation is, in the jargon, idempotent. http://en.wikipedia.org/wiki/Idempotence#Computer_science_meaning
Never heard of that before, what a name... I personally do not like when stuff like that creeps into the software architecture, too abstract and largely unnecesary in software design, there are already plenty specific methodologies we can use to design the software and explain the software.
Having said that, I believe this is the wrong example for "idempotent operation" because the status is not the same. Those are multiple events that are changing the status. The fact that somebody in IB decided not to show it, is wrong. In such case they should be sending only one message. If, on the other hand, they don't care about the status order for market orders and process only Filled status (which I do not believe), then it's plain stupid to send multiple messages after single event.
Quote from dcraig:
Some of it is not the way I would have done it, but it is reliable and robust which does count for quite a bit. The historical data portion of the API is a bit horrible and unnecessarily complicated to use. It is, however, perfectly possibly to make decent charts by using it.
Well, it's working and that's about it. Hardly robust, there is no structure in protocol low-level, no validation, no recovery, and list goes on and on....
Historical data msgs are same as everything else, what makes it additional nightmare is actually extremely restrictive policies regarding the amount of data you can get and the fact that it is not separated from the real-time communication, which forces you to spin-off something (I do separate process, they do that horrible Java threading).
At the first opportunity, I will ditch the data portion and retain only execution. For data, I am looking into DDF BarChart, looks well designed and platform agnostic. Thankfully no Java involved. No secret I can't stand it, nor the whole OOP, gone bezirk, mental exercise. However, I perfectly do not mind anybody enjoying it...