ib-api 10.33.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +52 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +7 -0
  5. data/CLAUDE.md +131 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +17 -0
  8. data/Gemfile.lock +120 -0
  9. data/Guardfile +24 -0
  10. data/LICENSE +674 -0
  11. data/LLM_GUIDE.md +388 -0
  12. data/README.md +114 -0
  13. data/Rakefile +11 -0
  14. data/VERSION +1 -0
  15. data/api.gemspec +50 -0
  16. data/bin/console +96 -0
  17. data/bin/console.yml +3 -0
  18. data/bin/setup +8 -0
  19. data/bin/simple +91 -0
  20. data/changelog.md +32 -0
  21. data/conditions/ib/execution_condition.rb +31 -0
  22. data/conditions/ib/margin_condition.rb +28 -0
  23. data/conditions/ib/order_condition.rb +29 -0
  24. data/conditions/ib/percent_change_condition.rb +34 -0
  25. data/conditions/ib/price_condition.rb +44 -0
  26. data/conditions/ib/time_condition.rb +42 -0
  27. data/conditions/ib/volume_condition.rb +36 -0
  28. data/lib/class_extensions.rb +167 -0
  29. data/lib/ib/base.rb +109 -0
  30. data/lib/ib/base_properties.rb +178 -0
  31. data/lib/ib/connection.rb +573 -0
  32. data/lib/ib/constants.rb +402 -0
  33. data/lib/ib/contract.rb +30 -0
  34. data/lib/ib/errors.rb +52 -0
  35. data/lib/ib/messages/abstract_message.rb +68 -0
  36. data/lib/ib/messages/incoming/abstract_message.rb +116 -0
  37. data/lib/ib/messages/incoming/abstract_tick.rb +25 -0
  38. data/lib/ib/messages/incoming/account_message.rb +26 -0
  39. data/lib/ib/messages/incoming/alert.rb +34 -0
  40. data/lib/ib/messages/incoming/contract_data.rb +105 -0
  41. data/lib/ib/messages/incoming/contract_message.rb +13 -0
  42. data/lib/ib/messages/incoming/delta_neutral_validation.rb +23 -0
  43. data/lib/ib/messages/incoming/execution_data.rb +50 -0
  44. data/lib/ib/messages/incoming/histogram_data.rb +30 -0
  45. data/lib/ib/messages/incoming/historical_data.rb +65 -0
  46. data/lib/ib/messages/incoming/historical_data_update.rb +50 -0
  47. data/lib/ib/messages/incoming/managed_accounts.rb +21 -0
  48. data/lib/ib/messages/incoming/market_depth.rb +34 -0
  49. data/lib/ib/messages/incoming/market_depth_l2.rb +15 -0
  50. data/lib/ib/messages/incoming/next_valid_id.rb +19 -0
  51. data/lib/ib/messages/incoming/open_order.rb +290 -0
  52. data/lib/ib/messages/incoming/order_status.rb +85 -0
  53. data/lib/ib/messages/incoming/portfolio_value.rb +47 -0
  54. data/lib/ib/messages/incoming/position_data.rb +21 -0
  55. data/lib/ib/messages/incoming/positions_multi.rb +15 -0
  56. data/lib/ib/messages/incoming/real_time_bar.rb +32 -0
  57. data/lib/ib/messages/incoming/receive_fa.rb +30 -0
  58. data/lib/ib/messages/incoming/scanner_data.rb +54 -0
  59. data/lib/ib/messages/incoming/tick_by_tick.rb +77 -0
  60. data/lib/ib/messages/incoming/tick_efp.rb +18 -0
  61. data/lib/ib/messages/incoming/tick_generic.rb +12 -0
  62. data/lib/ib/messages/incoming/tick_option.rb +60 -0
  63. data/lib/ib/messages/incoming/tick_price.rb +60 -0
  64. data/lib/ib/messages/incoming/tick_size.rb +55 -0
  65. data/lib/ib/messages/incoming/tick_string.rb +13 -0
  66. data/lib/ib/messages/incoming.rb +292 -0
  67. data/lib/ib/messages/outgoing/abstract_message.rb +84 -0
  68. data/lib/ib/messages/outgoing/bar_request_message.rb +247 -0
  69. data/lib/ib/messages/outgoing/new-place-order.rb +193 -0
  70. data/lib/ib/messages/outgoing/old-place-order.rb +147 -0
  71. data/lib/ib/messages/outgoing/place_order.rb +149 -0
  72. data/lib/ib/messages/outgoing/request_account_summary.rb +79 -0
  73. data/lib/ib/messages/outgoing/request_historical_data.rb +182 -0
  74. data/lib/ib/messages/outgoing/request_market_data.rb +102 -0
  75. data/lib/ib/messages/outgoing/request_market_depth.rb +57 -0
  76. data/lib/ib/messages/outgoing/request_real_time_bars.rb +48 -0
  77. data/lib/ib/messages/outgoing/request_scanner_subscription.rb +73 -0
  78. data/lib/ib/messages/outgoing/request_tick_by_tick_data.rb +21 -0
  79. data/lib/ib/messages/outgoing.rb +410 -0
  80. data/lib/ib/messages.rb +139 -0
  81. data/lib/ib/order_condition.rb +26 -0
  82. data/lib/ib/plugins.rb +27 -0
  83. data/lib/ib/prepare_data.rb +61 -0
  84. data/lib/ib/raw_message_parser.rb +99 -0
  85. data/lib/ib/socket.rb +83 -0
  86. data/lib/ib/support.rb +236 -0
  87. data/lib/ib/version.rb +6 -0
  88. data/lib/ib-api.rb +44 -0
  89. data/lib/server_versions.rb +145 -0
  90. data/lib/support/array_function.rb +28 -0
  91. data/lib/support/logging.rb +45 -0
  92. data/models/ib/account.rb +72 -0
  93. data/models/ib/account_value.rb +33 -0
  94. data/models/ib/bag.rb +55 -0
  95. data/models/ib/bar.rb +31 -0
  96. data/models/ib/combo_leg.rb +127 -0
  97. data/models/ib/contract.rb +411 -0
  98. data/models/ib/contract_detail.rb +118 -0
  99. data/models/ib/execution.rb +67 -0
  100. data/models/ib/forex.rb +12 -0
  101. data/models/ib/future.rb +64 -0
  102. data/models/ib/index.rb +14 -0
  103. data/models/ib/option.rb +149 -0
  104. data/models/ib/option_detail.rb +84 -0
  105. data/models/ib/order.rb +720 -0
  106. data/models/ib/order_state.rb +155 -0
  107. data/models/ib/portfolio_value.rb +86 -0
  108. data/models/ib/spread.rb +176 -0
  109. data/models/ib/stock.rb +25 -0
  110. data/models/ib/underlying.rb +32 -0
  111. data/plugins/ib/advanced-account.rb +442 -0
  112. data/plugins/ib/alerts/base-alert.rb +125 -0
  113. data/plugins/ib/alerts/gateway-alerts.rb +15 -0
  114. data/plugins/ib/alerts/order-alerts.rb +73 -0
  115. data/plugins/ib/auto-adjust.rb +0 -0
  116. data/plugins/ib/connection-tools.rb +122 -0
  117. data/plugins/ib/eod.rb +326 -0
  118. data/plugins/ib/greeks.rb +102 -0
  119. data/plugins/ib/managed-accounts.rb +274 -0
  120. data/plugins/ib/market-price.rb +150 -0
  121. data/plugins/ib/option-chain.rb +167 -0
  122. data/plugins/ib/order-flow.rb +157 -0
  123. data/plugins/ib/order-prototypes/abstract.rb +67 -0
  124. data/plugins/ib/order-prototypes/adaptive.rb +40 -0
  125. data/plugins/ib/order-prototypes/all-in-one.rb +46 -0
  126. data/plugins/ib/order-prototypes/combo.rb +46 -0
  127. data/plugins/ib/order-prototypes/forex.rb +40 -0
  128. data/plugins/ib/order-prototypes/limit.rb +193 -0
  129. data/plugins/ib/order-prototypes/market.rb +116 -0
  130. data/plugins/ib/order-prototypes/pegged.rb +169 -0
  131. data/plugins/ib/order-prototypes/premarket.rb +31 -0
  132. data/plugins/ib/order-prototypes/stop.rb +202 -0
  133. data/plugins/ib/order-prototypes/volatility.rb +39 -0
  134. data/plugins/ib/order-prototypes.rb +118 -0
  135. data/plugins/ib/probability-of-expiring.rb +109 -0
  136. data/plugins/ib/process-orders.rb +155 -0
  137. data/plugins/ib/roll.rb +86 -0
  138. data/plugins/ib/spread-prototypes/butterfly.rb +77 -0
  139. data/plugins/ib/spread-prototypes/calendar.rb +97 -0
  140. data/plugins/ib/spread-prototypes/stock-spread.rb +56 -0
  141. data/plugins/ib/spread-prototypes/straddle.rb +70 -0
  142. data/plugins/ib/spread-prototypes/strangle.rb +93 -0
  143. data/plugins/ib/spread-prototypes/vertical.rb +83 -0
  144. data/plugins/ib/spread-prototypes.rb +70 -0
  145. data/plugins/ib/symbols/abstract.rb +136 -0
  146. data/plugins/ib/symbols/bonds.rb +28 -0
  147. data/plugins/ib/symbols/cfd.rb +19 -0
  148. data/plugins/ib/symbols/combo.rb +46 -0
  149. data/plugins/ib/symbols/commodity.rb +17 -0
  150. data/plugins/ib/symbols/forex.rb +41 -0
  151. data/plugins/ib/symbols/futures.rb +127 -0
  152. data/plugins/ib/symbols/index.rb +43 -0
  153. data/plugins/ib/symbols/options.rb +99 -0
  154. data/plugins/ib/symbols/stocks.rb +44 -0
  155. data/plugins/ib/symbols/version.rb +5 -0
  156. data/plugins/ib/symbols.rb +118 -0
  157. data/plugins/ib/verify.rb +226 -0
  158. data/symbols/w20.yml +210 -0
  159. data/t.txt +20 -0
  160. data/update.md +71 -0
  161. metadata +327 -0
@@ -0,0 +1,247 @@
1
+ module IB
2
+ module Messages
3
+ module Outgoing
4
+ extend Messages # def_message macros
5
+
6
+ # Messages that request bar data have special processing of @data
7
+
8
+ class BarRequestMessage < AbstractMessage
9
+ # Preprocessor for some data fields
10
+ def parse data
11
+ type = data[:data_type] || data[:what_to_show]
12
+ data_type = DATA_TYPES.invert[type] || type
13
+ unless DATA_TYPES.keys.include?(data_type)
14
+ error ":data_type must be one of #{DATA_TYPES.inspect}", :args
15
+ end
16
+
17
+ #size = data[:bar_size] || data[:size]
18
+ #bar_size = BAR_SIZES.invert[size] || size
19
+ # unless BAR_SIZES.keys.include?(bar_size)
20
+ # error ":bar_size must be one of #{BAR_SIZES.inspect}", :args
21
+ # end
22
+ unless data[:contract].is_a? IB::Contract
23
+ error "contract must be a valid IB::Contract" , :args
24
+ end
25
+ [data_type, nil, data[:contract]]
26
+ end
27
+ end
28
+
29
+ # data = { :id => ticker_id (int),
30
+ # :contract => Contract ,
31
+ # :bar_size => int/Symbol? Currently only 5 second bars are supported,
32
+ # if any other value is used, an exception will be thrown.,
33
+ # :data_type => Symbol: Determines the nature of data being extracted.
34
+ # :trades, :midpoint, :bid, :ask, :bid_ask,
35
+ # :historical_volatility, :option_implied_volatility,
36
+ # :option_volume, :option_open_interest
37
+ # - converts to "TRADES," "MIDPOINT," "BID," etc...
38
+ # :use_rth => int: 0 - all data available during the time span requested
39
+ # is returned, even data bars covering time intervals where the
40
+ # market in question was illiquid. 1 - only data within the
41
+ # "Regular Trading Hours" of the product in question is returned,
42
+ # even if the time span requested falls partially or completely
43
+ # outside of them.
44
+ #
45
+ # Version 3
46
+ RequestRealTimeBars = def_message [ 50, 3 ], BarRequestMessage,
47
+ :request_id # autogenerated if not specified
48
+
49
+ class RequestRealTimeBars
50
+ def parse data
51
+ data_type, bar_size, contract = super data
52
+
53
+ size = data[:bar_size] || data[:size]
54
+ bar_size = 5 # only 5 sec bars are supported --> for future use ::> size.to_i
55
+ [data_type, bar_size, contract]
56
+ end
57
+
58
+ def encode
59
+ data_type, bar_size, contract = parse @data
60
+
61
+ [super,
62
+ contract.serialize_short(:primary_exchange), # include primary exchange in request
63
+ bar_size,
64
+ data_type.to_s.upcase,
65
+ @data[:use_rth] ,
66
+ "" # not suported realtimebars option string
67
+ ]
68
+ end
69
+ end # RequestRealTimeBars
70
+
71
+
72
+ RequestHistoricalData = def_message [20, 0], BarRequestMessage,
73
+ :request_id # autogenerated if not specified
74
+
75
+ # - data = {
76
+ # :contract => Contract: requested ticker description
77
+ # :end_date_time => String: "yyyymmdd HH:mm:ss", with optional time zone
78
+ # allowed after a space: "20050701 18:26:44 GMT"
79
+ # :duration => String, time span the request will cover, and is specified
80
+ # using the format: <integer> <unit>, eg: '1 D', valid units are:
81
+ # '1 S' (seconds, default if no unit is specified)
82
+ # '1 D' (days)
83
+ # '1 W' (weeks)
84
+ # '1 M' (months)
85
+ # '1 Y' (years, currently limited to one)
86
+ # :bar_size => String: Specifies the size of the bars that will be returned
87
+ # (within IB/TWS limits). Valid values include:
88
+ # '1 sec'
89
+ # '5 secs'
90
+ # '15 secs'
91
+ # '30 secs'
92
+ # '1 min'
93
+ # '2 mins'
94
+ # '3 mins'
95
+ # '5 mins'
96
+ # '15 mins'
97
+ # '30 min'
98
+ # '1 hour'
99
+ # '1 day'
100
+ # :what_to_show => Symbol: Determines the nature of data being extracted.
101
+ # Valid values:
102
+ # :trades, :midpoint, :bid, :ask, :bid_ask,
103
+ # :historical_volatility, :option_implied_volatility,
104
+ # :option_volume, :option_open_interest
105
+ # - converts to "TRADES," "MIDPOINT," "BID," etc...
106
+ # :use_rth => int: 0 - all data available during the time span requested
107
+ # is returned, even data bars covering time intervals where the
108
+ # market in question was illiquid. 1 - only data within the
109
+ # "Regular Trading Hours" of the product in question is returned,
110
+ # even if the time span requested falls partially or completely
111
+ # outside of them.
112
+ # :format_date => int: 1 - text format, like "20050307 11:32:16".
113
+ # 2 - offset from 1970-01-01 in sec (UNIX epoch)
114
+ # }
115
+ #
116
+ # - NB: using the D :duration only returns bars in whole days, so requesting "1 D"
117
+ # for contract ending at 08:05 will only return 1 bar, for 08:00 on that day.
118
+ # But requesting "86400 S" gives 86400/barlengthsecs bars before the end Time.
119
+ #
120
+ # - Note also that the :duration for any request must be such that the start Time is not
121
+ # more than one year before the CURRENT-Time-less-one-day (not 1 year before the end
122
+ # Time in the Request)
123
+ #
124
+ # Bar Size Max Duration
125
+ # -------- ------------
126
+ # 1 sec 2000 S
127
+ # 5 sec 10000 S
128
+ # 15 sec 30000 S
129
+ # 30 sec 86400 S
130
+ # 1 minute 86400 S, 6 D
131
+ # 2 minutes 86400 S, 6 D
132
+ # 5 minutes 86400 S, 6 D
133
+ # 15 minutes 86400 S, 6 D, 20 D, 2 W
134
+ # 30 minutes 86400 S, 34 D, 4 W, 1 M
135
+ # 1 hour 86400 S, 34 D, 4 w, 1 M
136
+ # 1 day 60 D, 12 M, 52 W, 1 Y
137
+ #
138
+ # - NB: as of 4/07 there is no historical data available for forex spot.
139
+ #
140
+ # - data[:contract] may either be a Contract object or a String. A String should be
141
+ # in serialize_ib_ruby format; that is, it should be a colon-delimited string in
142
+ # the format (e.g. for Globex British pound futures contract expiring in Sep-2008):
143
+ #
144
+ #
145
+ # - Fields not needed for a particular security should be left blank (e.g. strike
146
+ # and right are only relevant for options.)
147
+ #
148
+ # - A Contract object will be automatically serialized into the required format.
149
+ #
150
+ # - See also http://chuckcaplan.com/twsapi/index.php/void%20reqIntradayData%28%29
151
+ # for general information about how TWS handles historic data requests, whence
152
+ # the following has been adapted:
153
+ #
154
+ # - The server providing historical prices appears to not always be
155
+ # available outside of market hours. If you call it outside of its
156
+ # supported time period, or if there is otherwise a problem with
157
+ # it, you will receive error #162 "Historical Market Data Service
158
+ # query failed.:HMDS query returned no data."
159
+ #
160
+ # - For backfill on futures data, you may need to leave the Primary
161
+ # Exchange field of the Contract structure blank; see
162
+ # http://www.interactivebrokers.com/discus/messages/2/28477.html?1114646754
163
+ #
164
+ # - Version 6 implemented --> the version is not transmitted anymore
165
+ class RequestHistoricalData
166
+ def parse data
167
+ data_type, bar_size, contract = super data
168
+
169
+ size = data[:bar_size] || data[:size]
170
+ bar_size = BAR_SIZES.invert[size] || size
171
+ unless BAR_SIZES.keys.include?(bar_size)
172
+ error ":bar_size must be one of #{BAR_SIZES.inspect}", :args
173
+ end
174
+ [data_type, bar_size, contract]
175
+ end
176
+
177
+ def encode
178
+ data_type, bar_size, contract = parse @data
179
+
180
+ [super.flatten,
181
+ contract.serialize_long[0..-1], # omit sec_id_type and sec_id
182
+ @data[:end_date_time],
183
+ bar_size,
184
+ @data[:duration],
185
+ @data[:use_rth],
186
+ data_type.to_s.upcase,
187
+ 2 , # @data[:format_date], format-date is hard-coded as int_date in incoming/historicalData
188
+ contract.serialize_legs ,
189
+ @data[:keep_up_todate], # 0 / 1
190
+ '' # chartOptions:TagValueList - For internal use only. Use default value XYZ.
191
+ ]
192
+ end
193
+ end # RequestHistoricalData
194
+
195
+ end # module Outgoing
196
+ end # module Messages
197
+ end # module IB
198
+
199
+ ## python documentaion
200
+ # """Requests contracts' historical data. When requesting historical data, a
201
+ # finishing time and date is required along with a duration string. The
202
+ # resulting bars will be returned in EWrapper.historicalData()
203
+ # reqId:TickerId - The id of the request. Must be a unique value. When the
204
+ # market data returns, it whatToShowill be identified by this tag. This is also
205
+ # used when canceling the market data.
206
+ # contract:Contract - This object contains a description of the contract for which
207
+ # market data is being requested.
208
+ # endDateTime:str - Defines a query end date and time at any point during the past 6 mos.
209
+ # Valid values include any date/time within the past six months in the format:
210
+ # yyyymmdd HH:mm:ss ttt
211
+ # where "ttt" is the optional time zone.
212
+ # durationStr:str - Set the query duration up to one week, using a time unit
213
+ # of seconds, days or weeks. Valid values include any integer followed by a space
214
+ # and then S (seconds), D (days) or W (week). If no unit is specified, seconds is used.
215
+ # barSizeSetting:str - Specifies the size of the bars that will be returned (within IB/TWS listimits).
216
+ # Valid values include:
217
+ # 1 sec
218
+ # 5 secs
219
+ # 15 secs
220
+ # 30 secs
221
+ # 1 min
222
+ # 2 mins
223
+ # 3 mins
224
+ # 5 mins
225
+ # 15 mins
226
+ # 30 mins
227
+ # 1 hour
228
+ # 1 day
229
+ # whatToShow:str - Determines the nature of data beinging extracted. Valid values include:
230
+ # TRADES
231
+ # MIDPOINT
232
+ # BID
233
+ # ASK
234
+ # BID_ASK
235
+ # HISTORICAL_VOLATILITY
236
+ # OPTION_IMPLIED_VOLATILITY
237
+ # useRTH:int - Determines whether to return all data available during the requested time span,
238
+ # or only data that falls within regular trading hours. Valid values include:
239
+ # 0 - all data is returned even where the market in question was outside of its
240
+ # regular trading hours.
241
+ # 1 - only data within the regular trading hours is returned, even if the
242
+ # requested time span falls partially or completely outside of the RTH.
243
+ # formatDate: int - Determines the date format applied to returned bars. validd values include:
244
+ # 1 - dates applying to bars returned in the format: yyyymmdd{space}{space}hh:mm:dd
245
+ # 2 - dates are returned as a long integer specifying the number of seconds since
246
+ # 1/1/1970 GMT.
247
+ # chartOptions:TagValueList - For internal use only. Use default value XYZ. """
@@ -0,0 +1,193 @@
1
+ module IB
2
+ module Messages
3
+ module Outgoing
4
+ extend Messages # def_message macros
5
+
6
+ PlaceOrder = def_message [ 3,0 ]
7
+
8
+ class PlaceOrder
9
+ def encode
10
+ order = @data[:order]
11
+ contract = @data[:contract]
12
+
13
+ error 'contract has to be specified' unless contract.is_a? IB::Contract
14
+
15
+ # send place order msg
16
+ fields = [ super ]
17
+ fields << contract.serialize_short(:primary_exchange, :sec_id_type)
18
+ fields << order.serialize_main_order_fields
19
+ fields << order.serialize_extended_order_fields
20
+
21
+ # Send combo legs for BAG requests (srv v8 and above)
22
+ if contract.bag?
23
+ fields.push(combo_legs.size)
24
+ fields += combo_legs.map do |the_leg|
25
+ array = [
26
+ the_leg.con_id,
27
+ the_leg.ratio,
28
+ the_leg.side.to_sup,
29
+ the_leg.exchange,
30
+ the_leg[:open_close],
31
+ the_leg[:short_sale_slot],
32
+ the_leg.designated_location,
33
+ ]
34
+ array.push(the_leg.exempt_code) if server_version >= KNOWN_SERVERS[:min_server_ver_sshortx_old] # 51
35
+ array
36
+ end.flatten
37
+
38
+ # TODO: order_combo_leg?
39
+ if server_version >= KNOWN_SERVERS[:min_server_ver_order_combo_legs_price] # 61
40
+ fields.push(contract.combo_legs.size)
41
+ fields += contract.combo_legs.map { |leg| leg.price || '' }
42
+ end
43
+
44
+ # TODO: smartComboRoutingParams
45
+ if server_version >= KNOWN_SERVERS[:min_server_ver_smart_combo_routing_params] # 57
46
+ fields.push(order.combo_params.size)
47
+ fields += order.combo_params.to_a
48
+ end
49
+ end
50
+
51
+ fields << order.serialize_auxilery_order_fields # incluing advisory order fields
52
+
53
+ if server_version >= KNOWN_SERVERS[:min_server_ver_models_support]
54
+ fields.push(order.model_code )
55
+ end
56
+
57
+ fields += [
58
+ order[:short_sale_slot] , # 0 only for retail, 1 or 2 for institution (Institutional)
59
+ order.designated_location # only populate when short_sale_slot == 2 (Institutional)
60
+ ]
61
+
62
+ fields.push(order.exempt_code) if server_version >= KNOWN_SERVERS[:min_server_ver_sshortx_old]
63
+
64
+ fields.push(order[:oca_type])
65
+ fields += [
66
+ order[:rule_80a], # .to_sup[0..0],
67
+ order.settling_firm,
68
+ order.all_or_none,
69
+ order.min_quantity,
70
+ order.percent_offset,
71
+ false, # was: order.etrade_only || false, desupported in TWS > 981
72
+ false, # was: order.firm_quote_only || false, desupported in TWS > 981
73
+ '', ## desupported in TWS > 981, too. maybe we have to insert a hard-coded "" here
74
+ order[:auction_strategy], # AUCTION_MATCH, AUCTION_IMPROVEMENT, AUCTION_TRANSPARENT
75
+ order.starting_price ,
76
+ order.stock_ref_price ,
77
+ order.delta ,
78
+ order.stock_range_lower ,
79
+ order.stock_range_upper ,
80
+ order.override_percentage_constraints,
81
+ order.serialize_volatility_order_fields,
82
+ order.serialize_delta_neutral_order_fields
83
+ ]
84
+
85
+ fields += [
86
+ order.continuous_update,
87
+ order[:reference_price_type] ,
88
+ order.trail_stop_price,
89
+ order.trailing_percent
90
+ ]
91
+
92
+ fields << order.serialize_scale_order_fields
93
+
94
+ fields.push order.hedge_type
95
+ fields.push order.hedge_param # default is [] --> omitted if left default
96
+ fields.push order.opt_out_smart_routing
97
+
98
+ fields.push order.clearing_account
99
+ fields.push order.clearing_intent
100
+
101
+ fields.push(order.not_held) if server_version >= KNOWN_SERVERS[:min_server_ver_not_held] #44
102
+
103
+ if server_version >= KNOWN_SERVERS[:min_server_ver_delta_neutral] # 40
104
+ fields += contract.serialize_under_comp
105
+ end
106
+
107
+ if server_version >= KNOWN_SERVERS[:min_server_ver_algo_orders] # 41
108
+ fields += order.serialize_algo
109
+ end
110
+ if server_version >= KNOWN_SERVERS[:min_server_ver_algo_id] # 71
111
+ fields.push(order.algo_id)
112
+ end
113
+
114
+ fields.push(order.what_if)
115
+ fields.push(order.serialize_misc_options) if server_version >= KNOWN_SERVERS[:min_server_ver_linking] # 70
116
+ fields.push(order.solicided) if server_version >= KNOWN_SERVERS[:min_server_ver_order_solicited] # 73
117
+ if server_version >= KNOWN_SERVERS[:min_server_ver_randomize_size_and_price] # 76
118
+ fields += [
119
+ order.random_size,
120
+ order.random_price
121
+ ]
122
+ end
123
+
124
+ fields << order.serialize_pegged_order_fields
125
+ fields += order.serialize_conditions
126
+ fields += [
127
+ order.adjusted_order_type,
128
+ order.trigger_price,
129
+ order.limit_price_offset,
130
+ order.adjusted_stop_price,
131
+ order.adjusted_stop_limit_price,
132
+ order.adjusted_trailing_amount,
133
+ order.adjustable_trailing_unit
134
+ ]
135
+
136
+ fields.push(order.ext_operator) if server_version >= KNOWN_SERVERS[:min_server_ver_ext_operator]
137
+
138
+ fields << order.serialize_soft_dollar_tier
139
+
140
+ fields.push(order.cash_qty) if server_version >= KNOWN_SERVERS[:min_server_ver_cash_qty] # 111
141
+
142
+ fields << order.serialize_mifid_order_fields
143
+
144
+ if server_version >= KNOWN_SERVERS[:min_server_ver_auto_price_for_hedge]
145
+ fields.push(order.dont_use_auto_price_for_hedge)
146
+ end
147
+
148
+ fields.push(order.is_O_ms_container) if server_version >= KNOWN_SERVERS[:min_server_ver_order_container]
149
+
150
+ if server_version >= KNOWN_SERVERS[:min_server_ver_d_peg_orders]
151
+ fields.push(order.discretionary_up_to_limit_price)
152
+ end
153
+
154
+ if server_version >= KNOWN_SERVERS[:min_server_ver_price_mgmt_algo]
155
+ fields.push(order.use_price_management_algo)
156
+ end
157
+
158
+ if server_version >= KNOWN_SERVERS[:min_server_ver_duration]
159
+ fields.push(order.duration)
160
+ end
161
+
162
+ if server_version >= KNOWN_SERVERS[:min_server_ver_post_to_ats]
163
+ fields.push(order.post_to_ats)
164
+ end
165
+
166
+ if server_version >= KNOWN_SERVERS[:min_server_ver_auto_cancel_parent]
167
+ fields.push(order.auto_cancel_parent)
168
+ end
169
+
170
+ if server_version >= KNOWN_SERVERS[:min_server_ver_advanced_order_reject]
171
+ fields.push(order.advanced_order_reject)
172
+ end
173
+
174
+ if server_version >= KNOWN_SERVERS[:min_server_ver_manual_order_time]
175
+ fields.push(order.manual_order_time)
176
+ end
177
+
178
+ fields << order.serialize_peg_best_and_mid
179
+
180
+ if server_version >= KNOWN_SERVERS[:min_server_ver_customer_account]
181
+ fields.push(order.customer_account)
182
+ end
183
+
184
+ if server_version >= KNOWN_SERVERS[:min_server_ver_professional_customer]
185
+ fields.push(order.professional_account)
186
+ end
187
+
188
+ fields
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,147 @@
1
+ module IB
2
+ module Messages
3
+ module Outgoing
4
+ extend Messages # def_message macros
5
+
6
+ # Data format is { :id => local_id,
7
+ # :contract => Contract,
8
+ # :order => Order }
9
+ PlaceOrder = def_message [ 3,0 ]
10
+
11
+ class PlaceOrder
12
+ def encode
13
+
14
+ # lamba's to include order fields dependend of the server version provided
15
+ include_model_code = -> (m) { if server_version >= KNOWN_SERVERS[ :min_server_ver_models_support ] then m else [] end }
16
+ include_ext_operator = -> (e) { if server_version >= KNOWN_SERVERS[ :min_server_ver_ext_operator ] then e else [] end }
17
+ include_cash_qty = -> (c) { if server_version >= KNOWN_SERVERS[ :min_server_ver_cash_qty ] then c else [] end }
18
+ include_auto_price_for_hedge = -> (a) { if server_version >= KNOWN_SERVERS[ :min_server_ver_auto_price_for_hedge ] then a else [] end }
19
+ include_order_container = -> (o) { if server_version >= KNOWN_SERVERS[ :min_server_ver_order_container] then o else [] end }
20
+ include_d_peg_order = -> (d) { if server_version >= KNOWN_SERVERS[ :min_server_ver_d_peg_orders ] then d else [] end }
21
+ include_price_mgmt_algo = -> (p) { if server_version >= KNOWN_SERVERS[ :min_server_ver_price_mgmt_algo ]then p else [] end }
22
+ include_duration = -> (d) { if server_version >= KNOWN_SERVERS[ :min_server_ver_duration ]then d else [] end }
23
+ include_ats = -> (a) { if server_version >= KNOWN_SERVERS[ :min_server_ver_post_to_ats ]then a else [] end }
24
+ include_auto_cancel_parent = -> (a) { if server_version >= KNOWN_SERVERS[ :min_server_ver_auto_cancel_parent ] then a else [] end }
25
+ include_manual_order_time = -> (m) { if server_version >= KNOWN_SERVERS[ :min_server_ver_manual_order_time ] then m else [] end }
26
+ include_advanced_reject = -> (a){ if server_version >= KNOWN_SERVERS[ :min_server_ver_advanced_order_reject ] then a else [] end }
27
+ include_customer_account = -> (c) { if server_version >= KNOWN_SERVERS[ :min_server_ver_customer_account ] then c else [] end }
28
+ include_professional_customer = -> (p) { if server_version >= KNOWN_SERVERS[ :min_server_ver_professional_customer ] then p else [] end }
29
+
30
+ order = @data[ :order ]
31
+ contract = @data[ :contract ]
32
+
33
+ error "contract has to be specified" unless contract.is_a? IB::Contract
34
+
35
+ # -------------------------- start here -----------------------------------------
36
+ # build an array of order values ready to be transmitted to the tws ( after flattening )
37
+ #
38
+ [ super,
39
+ contract.serialize_short( :primary_exchange, :sec_id_type ),
40
+ order.serialize_main_order_fields,
41
+ order.serialize_extended_order_fields,
42
+ # legs
43
+ [ contract.serialize_legs( :extended ),
44
+ if contract.bag?
45
+ [
46
+ ## Support for per-leg prices in Order
47
+ [contract.combo_legs.size] + contract.combo_legs.map { |_| nil }, #(&:price) ,
48
+ ## Support for combo routing params in Order
49
+ order.combo_params.empty? ? 0 : [order.combo_params.size] + order.combo_params.to_a
50
+ ]
51
+ else
52
+ [ "do not include" ]
53
+ end ],
54
+ order.serialize_auxilery_order_fields, # incluing advisory order fields
55
+ # regulatory order fields
56
+ [
57
+ include_model_code[ order.model_code ],
58
+ order[:short_sale_slot] , # 0 only for retail, 1 or 2 for institution (Institutional)
59
+ order.designated_location, # only populate when short_sale_slot == 2 (Institutional)
60
+ order.exempt_code,
61
+ order[:oca_type],
62
+ order[:rule_80a], #.to_sup[0..0],
63
+ order.settling_firm ],
64
+ # algo order fields -1- (8)
65
+ [ order.all_or_none,
66
+ order.min_quantity ,
67
+ order.percent_offset,
68
+ false, # was: order.etrade_only || false, desupported in TWS > 981
69
+ false, # was: order.firm_quote_only || false, desupported in TWS > 981
70
+ false, # was order.nbbo_price_cap || "", ## desupported in TWS > 981
71
+ order[:auction_strategy],
72
+ order.starting_price,
73
+ order.stock_ref_price,
74
+ order.delta,
75
+ order.stock_range_lower,
76
+ order.stock_range_upper,
77
+ order.override_percentage_constraints,
78
+ order.serialize_volatility_order_fields
79
+ ],
80
+
81
+ order.serialize_delta_neutral_order_fields, # (9)
82
+
83
+ # Volatility orders (10)
84
+ [
85
+ order.continuous_update,
86
+ order[:reference_price_type],
87
+ ],
88
+ # trailing orders (11)
89
+ #
90
+ [
91
+ order.trail_stop_price,
92
+ order.trailing_percent,
93
+ ],
94
+
95
+ order.serialize_scale_order_fields, # (12)
96
+
97
+ # Support for hedgeType (13)
98
+ [
99
+ order.hedge_type,
100
+ order.hedge_param
101
+ ],
102
+
103
+ order.opt_out_smart_routing,
104
+
105
+ order.clearing_account ,
106
+ order.clearing_intent ,
107
+ order.not_held ,
108
+ contract.serialize_under_comp,
109
+ order.serialize_algo(),
110
+ order.what_if,
111
+ order.serialize_misc_options,
112
+ order.solicided,
113
+ order.random_size,
114
+ order.random_price,
115
+ order.serialize_pegged_order_fields,
116
+ order.serialize_conditions ,
117
+ order.adjusted_order_type ,
118
+ order.trigger_price ,
119
+ order.limit_price_offset ,
120
+ order.adjusted_stop_price ,
121
+ order.adjusted_stop_limit_price ,
122
+ order.adjusted_trailing_amount ,
123
+ order.adjustable_trailing_unit ,
124
+ include_ext_operator[ order.ext_operator ] ,
125
+ order.serialize_soft_dollar_tier,
126
+ include_cash_qty[ order.cash_qty ] ,
127
+ order.serialize_mifid_order_fields,
128
+ include_auto_price_for_hedge[ order.dont_use_auto_price_for_hedge ],
129
+ include_order_container[ order.is_O_ms_container ],
130
+ include_d_peg_order[ order.discretionary_up_to_limit_price ],
131
+ include_price_mgmt_algo[ order.use_price_management_algo ],
132
+ include_duration[ order.duration ],
133
+ include_ats[ order.post_to_ats ],
134
+ include_auto_cancel_parent[ order.auto_cancel_parent ],
135
+ include_advanced_reject[ order.advanced_order_reject ],
136
+ include_manual_order_time[ order.manual_order_time ],
137
+ order.serialize_peg_best_and_mid,
138
+ include_customer_account[ order.customer_account ],
139
+ include_professional_customer[ order.professional_account ]
140
+ ]
141
+ end # encode
142
+ end # PlaceOrder
143
+
144
+
145
+ end # module Outgoing
146
+ end # module Messages
147
+ end # module IB