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.
- data/.gitignore +32 -0
- data/HISTORY +68 -0
- data/README.rdoc +9 -6
- data/VERSION +1 -1
- data/bin/account_info +29 -0
- data/bin/contract_details +37 -0
- data/bin/depth_of_market +43 -0
- data/bin/historic_data +62 -0
- data/bin/{RequestHistoricData → historic_data_cli} +46 -91
- data/bin/market_data +49 -0
- data/bin/option_data +45 -0
- data/bin/template +21 -0
- data/bin/time_and_sales +63 -0
- data/lib/ib-ruby/connection.rb +166 -0
- data/lib/ib-ruby/constants.rb +91 -0
- data/lib/ib-ruby/messages/incoming.rb +807 -0
- data/lib/ib-ruby/messages/outgoing.rb +573 -0
- data/lib/ib-ruby/messages.rb +8 -1445
- data/lib/ib-ruby/models/bar.rb +26 -0
- data/lib/ib-ruby/models/contract.rb +335 -0
- data/lib/ib-ruby/models/execution.rb +55 -0
- data/lib/ib-ruby/models/model.rb +20 -0
- data/lib/ib-ruby/models/order.rb +262 -0
- data/lib/ib-ruby/models.rb +11 -0
- data/lib/ib-ruby/socket.rb +50 -0
- data/lib/ib-ruby/symbols/forex.rb +32 -72
- data/lib/ib-ruby/symbols/futures.rb +47 -68
- data/lib/ib-ruby/symbols/options.rb +30 -0
- data/lib/ib-ruby/symbols/stocks.rb +23 -0
- data/lib/ib-ruby/symbols.rb +9 -0
- data/lib/ib-ruby.rb +7 -8
- data/lib/legacy/bin/account_info_old +36 -0
- data/lib/legacy/bin/historic_data_old +81 -0
- data/lib/legacy/bin/market_data_old +68 -0
- data/lib/legacy/datatypes.rb +485 -0
- data/lib/legacy/ib-ruby.rb +10 -0
- data/lib/legacy/ib.rb +226 -0
- data/lib/legacy/messages.rb +1458 -0
- data/lib/version.rb +2 -3
- data/spec/ib-ruby/models/contract_spec.rb +261 -0
- data/spec/ib-ruby/models/order_spec.rb +64 -0
- data/spec/ib-ruby_spec.rb +0 -131
- metadata +106 -76
- data/bin/AccountInfo +0 -67
- data/bin/HistoricToCSV +0 -111
- data/bin/RequestMarketData +0 -78
- data/bin/SimpleTimeAndSales +0 -98
- data/bin/ib-ruby +0 -8
- data/lib/ib-ruby/datatypes.rb +0 -400
- 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;
|