ib-ruby 0.4.3 → 0.4.20

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 (50) hide show
  1. data/.gitignore +32 -0
  2. data/HISTORY +68 -0
  3. data/README.rdoc +9 -6
  4. data/VERSION +1 -1
  5. data/bin/account_info +29 -0
  6. data/bin/contract_details +37 -0
  7. data/bin/depth_of_market +43 -0
  8. data/bin/historic_data +62 -0
  9. data/bin/{RequestHistoricData → historic_data_cli} +46 -91
  10. data/bin/market_data +49 -0
  11. data/bin/option_data +45 -0
  12. data/bin/template +21 -0
  13. data/bin/time_and_sales +63 -0
  14. data/lib/ib-ruby/connection.rb +166 -0
  15. data/lib/ib-ruby/constants.rb +91 -0
  16. data/lib/ib-ruby/messages/incoming.rb +807 -0
  17. data/lib/ib-ruby/messages/outgoing.rb +573 -0
  18. data/lib/ib-ruby/messages.rb +8 -1445
  19. data/lib/ib-ruby/models/bar.rb +26 -0
  20. data/lib/ib-ruby/models/contract.rb +335 -0
  21. data/lib/ib-ruby/models/execution.rb +55 -0
  22. data/lib/ib-ruby/models/model.rb +20 -0
  23. data/lib/ib-ruby/models/order.rb +262 -0
  24. data/lib/ib-ruby/models.rb +11 -0
  25. data/lib/ib-ruby/socket.rb +50 -0
  26. data/lib/ib-ruby/symbols/forex.rb +32 -72
  27. data/lib/ib-ruby/symbols/futures.rb +47 -68
  28. data/lib/ib-ruby/symbols/options.rb +30 -0
  29. data/lib/ib-ruby/symbols/stocks.rb +23 -0
  30. data/lib/ib-ruby/symbols.rb +9 -0
  31. data/lib/ib-ruby.rb +7 -8
  32. data/lib/legacy/bin/account_info_old +36 -0
  33. data/lib/legacy/bin/historic_data_old +81 -0
  34. data/lib/legacy/bin/market_data_old +68 -0
  35. data/lib/legacy/datatypes.rb +485 -0
  36. data/lib/legacy/ib-ruby.rb +10 -0
  37. data/lib/legacy/ib.rb +226 -0
  38. data/lib/legacy/messages.rb +1458 -0
  39. data/lib/version.rb +2 -3
  40. data/spec/ib-ruby/models/contract_spec.rb +261 -0
  41. data/spec/ib-ruby/models/order_spec.rb +64 -0
  42. data/spec/ib-ruby_spec.rb +0 -131
  43. metadata +106 -76
  44. data/bin/AccountInfo +0 -67
  45. data/bin/HistoricToCSV +0 -111
  46. data/bin/RequestMarketData +0 -78
  47. data/bin/SimpleTimeAndSales +0 -98
  48. data/bin/ib-ruby +0 -8
  49. data/lib/ib-ruby/datatypes.rb +0 -400
  50. data/lib/ib-ruby/ib.rb +0 -242
@@ -0,0 +1,573 @@
1
+ # EClientSocket.java uses sendMax() rather than send() for a number of these.
2
+ # It sends an EOL rather than a number if the value == Integer.MAX_VALUE (or Double.MAX_VALUE).
3
+ # These fields are initialized to this MAX_VALUE.
4
+ # This has been implemented with nils in Ruby to represent the case where an EOL should be sent.
5
+
6
+ # TODO: Don't instantiate messages, use their classes as just namespace for .encode/decode
7
+
8
+ module IB
9
+ module Messages
10
+ module Outgoing
11
+
12
+ class AbstractMessage
13
+ # Class methods
14
+ def self.message_id
15
+ @message_id
16
+ end
17
+
18
+ def self.version
19
+ @version
20
+ end
21
+
22
+ attr_reader :created_at, :data
23
+
24
+ # data is a Hash
25
+ def initialize(data = {})
26
+ @data = data
27
+ @created_at = Time.now
28
+ end
29
+
30
+ def to_human
31
+ self.inspect
32
+ end
33
+
34
+ # This causes the message to send itself over the server socket in server[:socket].
35
+ # "server" is the @server instance variable from the IB object.
36
+ # You can also use this to e.g. get the server version number.
37
+ #
38
+ # Subclasses can either override this method for precise control over how
39
+ # stuff gets sent to the server, or else define a method encode() that returns
40
+ # an Array of elements that ought to be sent to the server by calling to_s on
41
+ # each one and postpending a '\0'.
42
+ #
43
+ def send(server)
44
+ self.encode.flatten.each do |datum|
45
+ # TWS wants to receive booleans as 1 or 0... rewrite as necessary.
46
+ datum = "1" if datum == true
47
+ datum = "0" if datum == false
48
+
49
+ #print 'SENDING: '
50
+ #p datum
51
+ server[:socket].syswrite(datum.to_s + EOL)
52
+ end
53
+ end
54
+
55
+ # At minimum, Outgoing message contains message_id and version.
56
+ # Most messages also contain (ticker, request or order) :id.
57
+ def encode
58
+ [self.class.message_id,
59
+ self.class.version,
60
+ @data[:id] || []]
61
+ end
62
+ end # AbstractMessage
63
+
64
+ # Macro that defines short message classes using a one-liner
65
+ def self.def_message message_id, version=1, *keys
66
+ Class.new(AbstractMessage) do
67
+ @message_id = message_id
68
+ @version = version
69
+
70
+ define_method :encode do
71
+ [super(), keys.map { |key| @data[key] }]
72
+ end unless keys.empty?
73
+ end
74
+ end
75
+
76
+ ### Defining (short) Outgoing Message classes for IB:
77
+
78
+ # Empty messages (no data)
79
+ RequestOpenOrders = def_message 5
80
+ CancelNewsBulletins = def_message 13
81
+ RequestAllOpenOrders = def_message 16
82
+ RequestManagedAccounts = def_message 17
83
+ RequestScannerParameters = def_message 24
84
+ RequestCurrentTime = def_message 49
85
+ RequestGlobalCancel = def_message 58
86
+
87
+ # Data format is: @data = { :id => ticker_id}
88
+ CancelScannerSubscription = def_message 23
89
+ CancelMarketData = def_message 2
90
+ CancelHistoricalData = def_message 25
91
+ CancelRealTimeBars = def_message 51
92
+ CancelMarketDepth = def_message 11
93
+
94
+ # Data format is: @data = { :id => request_id }
95
+ CancelFundamentalData = def_message 53
96
+ CancelImpliedVolatility = def_message 56
97
+ CancelCalculateImpliedVolatility = CancelImpliedVolatility
98
+ CancelOptionPrice = def_message 57
99
+ CancelCalculateOptionPrice = CancelOptionPrice
100
+
101
+ # Data format is: @data ={ :id => order-id-to-cancel }
102
+ CancelOrder = def_message 4
103
+
104
+ # These messages contain just one or two keys, shown in the end of definition
105
+ # @data = { :number_of_ids => int }
106
+ RequestIds = def_message 8, 1, :number_of_ids
107
+ # data = { :all_messages => boolean }
108
+ RequestNewsBulletins = def_message 12, 1, :all_messages
109
+ # data = { :log_level => int }
110
+ SetServerLoglevel = def_message 14, 1, :log_level
111
+ # data = { :auto_bind => boolean }
112
+ RequestAutoOpenOrders = def_message 15, 1, :auto_bind
113
+ # data = { :fa_data_type => int }
114
+ RequestFA = def_message 18, 1, :fa_data_type
115
+ # data = { :fa_data_type => int, :xml => String }
116
+ ReplaceFA = def_message 19, 1, :fa_data_type, :xml
117
+
118
+ # Data is { :subscribe => boolean,
119
+ # :account_code => String: only necessary for advisor accounts. Set it
120
+ # to empty ('') for a standard account. }
121
+ class RequestAccountData < AbstractMessage
122
+ @message_id = 6
123
+ @version = 2
124
+
125
+ def encode
126
+ [super,
127
+ @data[:subscribe],
128
+ @data[:account_code] || '']
129
+ end
130
+ end
131
+ RequestAccountUpdates = RequestAccountData
132
+
133
+
134
+ ### Defining (complex) Outgoing Message classes for IB:
135
+
136
+ # data = { :id => ticker_id (int), :subscription => ScannerSubscription}
137
+ class RequestScannerSubscription < AbstractMessage
138
+ @message_id = 22
139
+ @version = 3
140
+
141
+ def encode
142
+ [super,
143
+ @data[:subscription].number_of_rows || EOL,
144
+ @data[:subscription].instrument,
145
+ @data[:subscription].location_code,
146
+ @data[:subscription].scan_code,
147
+ @data[:subscription].above_price || EOL,
148
+ @data[:subscription].below_price || EOL,
149
+ @data[:subscription].above_volume || EOL,
150
+ @data[:subscription].market_cap_above || EOL,
151
+ @data[:subscription].market_cap_below || EOL,
152
+ @data[:subscription].moody_rating_above,
153
+ @data[:subscription].moody_rating_below,
154
+ @data[:subscription].sp_rating_above,
155
+ @data[:subscription].sp_rating_below,
156
+ @data[:subscription].maturity_date_above,
157
+ @data[:subscription].maturity_date_below,
158
+ @data[:subscription].coupon_rate_above || EOL,
159
+ @data[:subscription].coupon_rate_below || EOL,
160
+ @data[:subscription].exclude_convertible,
161
+ @data[:subscription].average_option_volume_above,
162
+ @data[:subscription].scanner_setting_pairs,
163
+ @data[:subscription].stock_type_filter
164
+ ]
165
+ end
166
+ end # RequestScannerSubscription
167
+
168
+ # @data={:id => int: ticker_id - Must be a unique value. When the market data
169
+ # returns, it will be identified by this tag,
170
+ # :contract => Datatypes::Contract, requested contract.
171
+ # :tick_list => String: comma delimited list of requested tick groups:
172
+ # Group ID - Description - Requested Tick Types
173
+ # 100 - Option Volume (currently for stocks) - 29, 30
174
+ # 101 - Option Open Interest (currently for stocks) - 27, 28
175
+ # 104 - Historical Volatility (currently for stocks) - 23
176
+ # 106 - Option Implied Volatility (currently for stocks) - 24
177
+ # 162 - Index Future Premium - 31
178
+ # 165 - Miscellaneous Stats - 15, 16, 17, 18, 19, 20, 21
179
+ # 221 - Mark Price (used in TWS P&L computations) - 37
180
+ # 225 - Auction values (volume, price and imbalance) - 34, 35, 36
181
+ # 233 - RTVolume - 48
182
+ # 236 - Shortable - 46
183
+ # 256 - Inventory - ?
184
+ # 258 - Fundamental Ratios - 47
185
+ # 411 - Realtime Historical Volatility - 58
186
+ # :snapshot => bool: Check to return a single snapshot of market data and
187
+ # have the market data subscription canceled. Do not enter any
188
+ # :tick_list values if you use snapshot. }
189
+ class RequestMarketData < AbstractMessage
190
+ @message_id = 1
191
+ @version = 9 # message version number
192
+
193
+ def encode
194
+ tick_list = case @data[:tick_list]
195
+ when nil
196
+ ''
197
+ when Array
198
+ @data[:tick_list].join ','
199
+ when String
200
+ @data[:tick_list]
201
+ end
202
+ [super,
203
+ @data[:contract].con_id, # part of serialize?
204
+ @data[:contract].serialize,
205
+ @data[:contract].serialize_combo_legs,
206
+ @data[:contract].serialize_under_comp,
207
+ tick_list,
208
+ @data[:snapshot] || false]
209
+ end
210
+ end # RequestMarketData
211
+
212
+ # data = { :id => int: Ticker id, needs to be different than the reqMktData ticker
213
+ # id. If you use the same ticker ID you used for the symbol when
214
+ # you did ReqMktData, nothing comes back for the historical data call
215
+ # :contract => Contract: requested ticker description
216
+ # :end_date_time => String: "yyyymmdd HH:mm:ss", with optional time zone
217
+ # allowed after a space: "20050701 18:26:44 GMT"
218
+ # :duration => String, time span the request will cover, and is specified
219
+ # using the format: <integer> <unit>, eg: '1 D', valid units are:
220
+ # '1 S' (seconds, default if no unit is specified)
221
+ # '1 D' (days)
222
+ # '1 W' (weeks)
223
+ # '1 M' (months)
224
+ # '1 Y' (years, currently limited to one)
225
+ # :bar_size => String: Specifies the size of the bars that will be returned
226
+ # (within IB/TWS limits). Valid values include:
227
+ # '1 sec'
228
+ # '5 secs'
229
+ # '15 secs'
230
+ # '30 secs'
231
+ # '1 min'
232
+ # '2 mins'
233
+ # '3 mins'
234
+ # '5 mins'
235
+ # '15 mins'
236
+ # '30 min'
237
+ # '1 hour'
238
+ # '1 day'
239
+ # :what_to_show => Symbol: one of :trades, :midpoint, :bid, or :ask -
240
+ # converts to "TRADES," "MIDPOINT," "BID," or "ASK."
241
+ # :use_rth => int: 0 - all data available during the time span requested
242
+ # is returned, even data bars covering time intervals where the
243
+ # market in question was illiquid. 1 - only data within the
244
+ # "Regular Trading Hours" of the product in question is returned,
245
+ # even if the time span requested falls partially or completely
246
+ # outside of them.
247
+ # :format_date => int: 1 - text format, like "20050307 11:32:16".
248
+ # 2 - offset in seconds from the beginning of 1970,
249
+ # which is the same format as the UNIX epoch time.
250
+ # }
251
+ #
252
+ # Note that as of 4/07 there is no historical data available for forex spot.
253
+ #
254
+ # data[:contract] may either be a Contract object or a String. A String should be
255
+ # in serialize_ib_ruby format; that is, it should be a colon-delimited string in
256
+ # the format (e.g. for Globex British pound futures contract expiring in Sep-2008):
257
+ #
258
+ # symbol:security_type:expiry:strike:right:multiplier:exchange:primary_exchange:currency:local_symbol
259
+ # GBP:FUT:200809:::62500:GLOBEX::USD:
260
+ #
261
+ # Fields not needed for a particular security should be left blank (e.g. strike
262
+ # and right are only relevant for options.)
263
+ #
264
+ # A Contract object will be automatically serialized into the required format.
265
+ #
266
+ # See also http://chuckcaplan.com/twsapi/index.php/void%20reqIntradayData%28%29
267
+ # for general information about how TWS handles historic data requests, whence
268
+ # the following has been adapted:
269
+ #
270
+ # The server providing historical prices appears to not always be
271
+ # available outside of market hours. If you call it outside of its
272
+ # supported time period, or if there is otherwise a problem with
273
+ # it, you will receive error #162 "Historical Market Data Service
274
+ # query failed.:HMDS query returned no data."
275
+ #
276
+ # For backfill on futures data, you may need to leave the Primary
277
+ # Exchange field of the Contract structure blank; see
278
+ # http://www.interactivebrokers.com/discus/messages/2/28477.html?1114646754
279
+ class RequestHistoricalData < AbstractMessage
280
+ @message_id = 20
281
+ @version = 4
282
+
283
+ def encode
284
+ if @data.has_key?(:what_to_show) && @data[:what_to_show].is_a?(String)
285
+ @data[:what_to_show] = @data[:what_to_show].downcase.to_sym
286
+ end
287
+
288
+ raise ArgumentError(":what_to_show must be one of #{DATA_TYPES}.") unless DATA_TYPES.include?(@data[:what_to_show])
289
+ raise ArgumentError(":bar_size must be one of #{BAR_SIZES}.") unless BAR_SIZES.include?(@data[:bar_size])
290
+
291
+ contract = @data[:contract].is_a?(Models::Contract) ?
292
+ @data[:contract] : Models::Contract.from_ib_ruby(@data[:contract])
293
+
294
+ [super,
295
+ contract.serialize,
296
+ contract.include_expired,
297
+ @data[:end_date_time],
298
+ @data[:bar_size],
299
+ @data[:duration],
300
+ @data[:use_rth],
301
+ @data[:what_to_show].to_s.upcase,
302
+ @data[:format_date],
303
+ contract.serialize_combo_legs]
304
+ end
305
+ end # RequestHistoricalData
306
+
307
+ # data = { :id => ticker_id (int),
308
+ # :contract => Contract ,
309
+ # :bar_size => int/Symbol? Currently only 5 second bars (2?) are supported,
310
+ # if any other value is used, an exception will be thrown.,
311
+ # :what_to_show => Symbol: one of :trades, :midpoint, :bid, or :ask -
312
+ # converts to "TRADES," "MIDPOINT," "BID," or "ASK."
313
+ # :use_rth => int: 0 - all data available during the time span requested
314
+ # is returned, even data bars covering time intervals where the
315
+ # market in question was illiquid. 1 - only data within the
316
+ # "Regular Trading Hours" of the product in question is returned,
317
+ # even if the time span requested falls partially or completely
318
+ # outside of them.
319
+ class RequestRealTimeBars < AbstractMessage
320
+ @message_id = 50
321
+
322
+ def encode
323
+ if @data.has_key?(:what_to_show) && @data[:what_to_show].is_a?(String)
324
+ @data[:what_to_show] = @data[:what_to_show].downcase.to_sym
325
+ end
326
+
327
+ raise ArgumentError(":what_to_show must be one of #{DATA_TYPES}.") unless DATA_TYPES.include?(@data[:what_to_show])
328
+ raise ArgumentError(":bar_size must be one of #{BAR_SIZES}.") unless BAR_SIZES.include?(@data[:bar_size])
329
+
330
+ contract = @data[:contract].is_a?(Models::Contract) ?
331
+ @data[:contract] : Models::Contract.from_ib_ruby(@data[:contract])
332
+
333
+ [super,
334
+ contract.serialize,
335
+ @data[:bar_size],
336
+ @data[:what_to_show].to_s.upcase,
337
+ @data[:use_rth]]
338
+ end
339
+ end # RequestRealTimeBars
340
+
341
+ # data => { :id => request_id (int), :contract => Contract }
342
+ class RequestContractData < AbstractMessage
343
+ @message_id = 9
344
+ @version = 6
345
+
346
+ def encode
347
+ [super,
348
+ @data[:contract].con_id, # part of serialize?
349
+ @data[:contract].serialize(:short),
350
+ @data[:contract].include_expired,
351
+ @data[:contract].sec_id_type,
352
+ @data[:contract].sec_id]
353
+ end
354
+ end # RequestContractData
355
+ RequestContractDetails = RequestContractData # alias
356
+
357
+ # data = { :id => ticker_id (int), :contract => Contract, :num_rows => int }
358
+ class RequestMarketDepth < AbstractMessage
359
+ @message_id = 10
360
+ @version = 3
361
+
362
+ def encode
363
+ [super,
364
+ @data[:contract].serialize(:short),
365
+ @data[:num_rows]]
366
+ end
367
+ end # RequestMarketDepth
368
+
369
+ # data = { :id => ticker_id (int),
370
+ # :contract => Contract,
371
+ # :exercise_action => int,
372
+ # :exercise_quantity => int,
373
+ # :account => string,
374
+ # :override => int } ## override? override what?
375
+ class ExerciseOptions < AbstractMessage
376
+ @message_id = 21
377
+
378
+ def encode
379
+ [super,
380
+ @data[:contract].serialize(:short),
381
+ @data[:exercise_action],
382
+ @data[:exercise_quantity],
383
+ @data[:account],
384
+ @data[:override]]
385
+ end
386
+ end # ExerciseOptions
387
+
388
+ # Data format is { :id => order_id (int), :contract => Contract, :order => Order }
389
+ class PlaceOrder < AbstractMessage
390
+ @message_id = 3
391
+ @version = 31
392
+ # int VERSION = (m_serverVersion < MIN_SERVER_VER_NOT_HELD) ? 27 : 31;
393
+
394
+ def encode
395
+ [super,
396
+ @data[:contract].serialize,
397
+ @data[:contract].sec_id_type, # Unimplemented?
398
+ @data[:contract].sec_id, # Unimplemented?
399
+ @data[:order].action, # send main order fields
400
+ @data[:order].total_quantity,
401
+ @data[:order].order_type,
402
+ @data[:order].limit_price,
403
+ @data[:order].aux_price,
404
+ @data[:order].tif, # send extended order fields
405
+ @data[:order].oca_group,
406
+ @data[:order].account,
407
+ @data[:order].open_close,
408
+ @data[:order].origin,
409
+ @data[:order].order_ref,
410
+ @data[:order].transmit,
411
+ @data[:order].parent_id,
412
+ @data[:order].block_order,
413
+ @data[:order].sweep_to_fill,
414
+ @data[:order].display_size,
415
+ @data[:order].trigger_method,
416
+ @data[:order].outside_rth, # was: ignore_rth
417
+ @data[:order].hidden,
418
+ @data[:contract].serialize_combo_legs(:long),
419
+ '', # send deprecated shares_allocation field
420
+ @data[:order].discretionary_amount,
421
+ @data[:order].good_after_time,
422
+ @data[:order].good_till_date,
423
+ @data[:order].fa_group,
424
+ @data[:order].fa_method,
425
+ @data[:order].fa_percentage,
426
+ @data[:order].fa_profile,
427
+ # Institutional short sale slot fields:
428
+ @data[:order].short_sale_slot, # 0 only for retail, 1 or 2 for institution
429
+ @data[:order].designated_location, # only populate when short_sale_slot == 2
430
+ @data[:order].oca_type,
431
+ @data[:order].rule_80a,
432
+ @data[:order].settling_firm,
433
+ @data[:order].all_or_none,
434
+ @data[:order].min_quantity || EOL,
435
+ @data[:order].percent_offset || EOL,
436
+ @data[:order].etrade_only,
437
+ @data[:order].firm_quote_only,
438
+ @data[:order].nbbo_price_cap || EOL,
439
+ @data[:order].auction_strategy || EOL,
440
+ @data[:order].starting_price || EOL,
441
+ @data[:order].stock_ref_price || EOL,
442
+ @data[:order].delta || EOL,
443
+ @data[:order].stock_range_lower || EOL,
444
+ @data[:order].stock_range_upper || EOL,
445
+ @data[:order].override_percentage_constraints,
446
+ @data[:order].volatility || EOL, # Volatility orders
447
+ @data[:order].volatility_type || EOL, # Volatility orders
448
+ @data[:order].delta_neutral_order_type, # Volatility orders
449
+ @data[:order].delta_neutral_aux_price || EOL, # Volatility orders
450
+ @data[:order].continuous_update, # Volatility orders
451
+ @data[:order].reference_price_type || EOL, # Volatility orders
452
+ @data[:order].trail_stop_price || EOL, # TRAIL_STOP_LIMIT stop price
453
+ @data[:order].scale_init_level_size || EOL, # Scale Orders
454
+ @data[:order].scale_subs_level_size || EOL, # Scale Orders
455
+ @data[:order].scale_price_increment || EOL, # Scale Orders
456
+ @data[:order].clearing_account,
457
+ @data[:order].clearing_intent,
458
+ @data[:order].not_held,
459
+ @data[:contract].serialize_under_comp,
460
+ @data[:contract].serialize_algo,
461
+ @data[:order].what_if]
462
+ end
463
+ end # PlaceOrder
464
+
465
+ # data = { :filter => ExecutionFilter ]
466
+ class RequestExecutions < AbstractMessage
467
+ @message_id = 7
468
+ @version = 3
469
+
470
+ def encode
471
+ [super,
472
+ @data[:filter].client_id,
473
+ @data[:filter].acct_code,
474
+ @data[:filter].time, # Valid format for time is "yyyymmdd-hh:mm:ss"
475
+ @data[:filter].symbol,
476
+ @data[:filter].sec_type,
477
+ @data[:filter].exchange,
478
+ @data[:filter].side]
479
+ end # encode
480
+ end # RequestExecutions
481
+
482
+ # data = { :request_id => int, :contract => Contract, :report_type => String }
483
+ class RequestFundamentalData < AbstractMessage
484
+ @message_id = 52
485
+
486
+ def encode
487
+ [super,
488
+ @data[:request_id],
489
+ @data[:contract].symbol, # Yet another Contract serialization!
490
+ @data[:contract].sec_type,
491
+ @data[:contract].exchange,
492
+ @data[:contract].primary_exchange,
493
+ @data[:contract].currency,
494
+ @data[:contract].local_symbol,
495
+ @data[:report_type]]
496
+ end
497
+ end # RequestFundamentalData
498
+
499
+ # data = { :request_id => int, :contract => Contract,
500
+ # :option_price => double, :under_price => double }
501
+ class RequestImpliedVolatility < AbstractMessage
502
+ @message_id = 54
503
+
504
+ def encode
505
+ [super,
506
+ @data[:request_id],
507
+ @data[:contract].con_id, # part of serialize?
508
+ @data[:contract].serialize,
509
+ @data[:option_price],
510
+ @data[:under_price]]
511
+ end
512
+ end # RequestImpliedVolatility
513
+ CalculateImpliedVolatility = RequestImpliedVolatility
514
+ RequestCalculateImpliedVolatility = RequestImpliedVolatility
515
+
516
+ # data = { :request_id => int, :contract => Contract,
517
+ # :volatility => double, :under_price => double }
518
+ class RequestOptionPrice < AbstractMessage
519
+ @message_id = 55
520
+
521
+ def encode
522
+ [super,
523
+ @data[:request_id],
524
+ @data[:contract].con_id, # part of serialize?
525
+ @data[:contract].serialize,
526
+ @data[:volatility],
527
+ @data[:under_price]]
528
+ end
529
+ end # RequestOptionPrice
530
+ CalculateOptionPrice = RequestOptionPrice
531
+ RequestCalculateOptionPrice = RequestOptionPrice
532
+
533
+ end # module Outgoing
534
+ end # module Messages
535
+ end # module IB
536
+
537
+ __END__
538
+ // outgoing msg id's
539
+ private static final int REQ_MKT_DATA = 1;
540
+ private static final int CANCEL_MKT_DATA = 2;
541
+ private static final int PLACE_ORDER = 3;
542
+ private static final int CANCEL_ORDER = 4;
543
+ private static final int REQ_OPEN_ORDERS = 5;
544
+ private static final int REQ_ACCOUNT_DATA = 6;
545
+ private static final int REQ_EXECUTIONS = 7;
546
+ private static final int REQ_IDS = 8;
547
+ private static final int REQ_CONTRACT_DATA = 9;
548
+ private static final int REQ_MKT_DEPTH = 10;
549
+ private static final int CANCEL_MKT_DEPTH = 11;
550
+ private static final int REQ_NEWS_BULLETINS = 12;
551
+ private static final int CANCEL_NEWS_BULLETINS = 13;
552
+ private static final int SET_SERVER_LOGLEVEL = 14;
553
+ private static final int REQ_AUTO_OPEN_ORDERS = 15;
554
+ private static final int REQ_ALL_OPEN_ORDERS = 16;
555
+ private static final int REQ_MANAGED_ACCTS = 17;
556
+ private static final int REQ_FA = 18;
557
+ private static final int REPLACE_FA = 19;
558
+ private static final int REQ_HISTORICAL_DATA = 20;
559
+ private static final int EXERCISE_OPTIONS = 21;
560
+ private static final int REQ_SCANNER_SUBSCRIPTION = 22;
561
+ private static final int CANCEL_SCANNER_SUBSCRIPTION = 23;
562
+ private static final int REQ_SCANNER_PARAMETERS = 24;
563
+ private static final int CANCEL_HISTORICAL_DATA = 25;
564
+ private static final int REQ_CURRENT_TIME = 49;
565
+ private static final int REQ_REAL_TIME_BARS = 50;
566
+ private static final int CANCEL_REAL_TIME_BARS = 51;
567
+ private static final int REQ_FUNDAMENTAL_DATA = 52;
568
+ private static final int CANCEL_FUNDAMENTAL_DATA = 53;
569
+ private static final int REQ_CALC_IMPLIED_VOLAT = 54;
570
+ private static final int REQ_CALC_OPTION_PRICE = 55;
571
+ private static final int CANCEL_CALC_IMPLIED_VOLAT = 56;
572
+ private static final int CANCEL_CALC_OPTION_PRICE = 57;
573
+ private static final int REQ_GLOBAL_CANCEL = 58;