ib-ruby 0.4.3 → 0.4.20

Sign up to get free protection for your applications and to get access to all the features.
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;