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.
- checksums.yaml +7 -0
- data/.gitignore +52 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/CLAUDE.md +131 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +120 -0
- data/Guardfile +24 -0
- data/LICENSE +674 -0
- data/LLM_GUIDE.md +388 -0
- data/README.md +114 -0
- data/Rakefile +11 -0
- data/VERSION +1 -0
- data/api.gemspec +50 -0
- data/bin/console +96 -0
- data/bin/console.yml +3 -0
- data/bin/setup +8 -0
- data/bin/simple +91 -0
- data/changelog.md +32 -0
- data/conditions/ib/execution_condition.rb +31 -0
- data/conditions/ib/margin_condition.rb +28 -0
- data/conditions/ib/order_condition.rb +29 -0
- data/conditions/ib/percent_change_condition.rb +34 -0
- data/conditions/ib/price_condition.rb +44 -0
- data/conditions/ib/time_condition.rb +42 -0
- data/conditions/ib/volume_condition.rb +36 -0
- data/lib/class_extensions.rb +167 -0
- data/lib/ib/base.rb +109 -0
- data/lib/ib/base_properties.rb +178 -0
- data/lib/ib/connection.rb +573 -0
- data/lib/ib/constants.rb +402 -0
- data/lib/ib/contract.rb +30 -0
- data/lib/ib/errors.rb +52 -0
- data/lib/ib/messages/abstract_message.rb +68 -0
- data/lib/ib/messages/incoming/abstract_message.rb +116 -0
- data/lib/ib/messages/incoming/abstract_tick.rb +25 -0
- data/lib/ib/messages/incoming/account_message.rb +26 -0
- data/lib/ib/messages/incoming/alert.rb +34 -0
- data/lib/ib/messages/incoming/contract_data.rb +105 -0
- data/lib/ib/messages/incoming/contract_message.rb +13 -0
- data/lib/ib/messages/incoming/delta_neutral_validation.rb +23 -0
- data/lib/ib/messages/incoming/execution_data.rb +50 -0
- data/lib/ib/messages/incoming/histogram_data.rb +30 -0
- data/lib/ib/messages/incoming/historical_data.rb +65 -0
- data/lib/ib/messages/incoming/historical_data_update.rb +50 -0
- data/lib/ib/messages/incoming/managed_accounts.rb +21 -0
- data/lib/ib/messages/incoming/market_depth.rb +34 -0
- data/lib/ib/messages/incoming/market_depth_l2.rb +15 -0
- data/lib/ib/messages/incoming/next_valid_id.rb +19 -0
- data/lib/ib/messages/incoming/open_order.rb +290 -0
- data/lib/ib/messages/incoming/order_status.rb +85 -0
- data/lib/ib/messages/incoming/portfolio_value.rb +47 -0
- data/lib/ib/messages/incoming/position_data.rb +21 -0
- data/lib/ib/messages/incoming/positions_multi.rb +15 -0
- data/lib/ib/messages/incoming/real_time_bar.rb +32 -0
- data/lib/ib/messages/incoming/receive_fa.rb +30 -0
- data/lib/ib/messages/incoming/scanner_data.rb +54 -0
- data/lib/ib/messages/incoming/tick_by_tick.rb +77 -0
- data/lib/ib/messages/incoming/tick_efp.rb +18 -0
- data/lib/ib/messages/incoming/tick_generic.rb +12 -0
- data/lib/ib/messages/incoming/tick_option.rb +60 -0
- data/lib/ib/messages/incoming/tick_price.rb +60 -0
- data/lib/ib/messages/incoming/tick_size.rb +55 -0
- data/lib/ib/messages/incoming/tick_string.rb +13 -0
- data/lib/ib/messages/incoming.rb +292 -0
- data/lib/ib/messages/outgoing/abstract_message.rb +84 -0
- data/lib/ib/messages/outgoing/bar_request_message.rb +247 -0
- data/lib/ib/messages/outgoing/new-place-order.rb +193 -0
- data/lib/ib/messages/outgoing/old-place-order.rb +147 -0
- data/lib/ib/messages/outgoing/place_order.rb +149 -0
- data/lib/ib/messages/outgoing/request_account_summary.rb +79 -0
- data/lib/ib/messages/outgoing/request_historical_data.rb +182 -0
- data/lib/ib/messages/outgoing/request_market_data.rb +102 -0
- data/lib/ib/messages/outgoing/request_market_depth.rb +57 -0
- data/lib/ib/messages/outgoing/request_real_time_bars.rb +48 -0
- data/lib/ib/messages/outgoing/request_scanner_subscription.rb +73 -0
- data/lib/ib/messages/outgoing/request_tick_by_tick_data.rb +21 -0
- data/lib/ib/messages/outgoing.rb +410 -0
- data/lib/ib/messages.rb +139 -0
- data/lib/ib/order_condition.rb +26 -0
- data/lib/ib/plugins.rb +27 -0
- data/lib/ib/prepare_data.rb +61 -0
- data/lib/ib/raw_message_parser.rb +99 -0
- data/lib/ib/socket.rb +83 -0
- data/lib/ib/support.rb +236 -0
- data/lib/ib/version.rb +6 -0
- data/lib/ib-api.rb +44 -0
- data/lib/server_versions.rb +145 -0
- data/lib/support/array_function.rb +28 -0
- data/lib/support/logging.rb +45 -0
- data/models/ib/account.rb +72 -0
- data/models/ib/account_value.rb +33 -0
- data/models/ib/bag.rb +55 -0
- data/models/ib/bar.rb +31 -0
- data/models/ib/combo_leg.rb +127 -0
- data/models/ib/contract.rb +411 -0
- data/models/ib/contract_detail.rb +118 -0
- data/models/ib/execution.rb +67 -0
- data/models/ib/forex.rb +12 -0
- data/models/ib/future.rb +64 -0
- data/models/ib/index.rb +14 -0
- data/models/ib/option.rb +149 -0
- data/models/ib/option_detail.rb +84 -0
- data/models/ib/order.rb +720 -0
- data/models/ib/order_state.rb +155 -0
- data/models/ib/portfolio_value.rb +86 -0
- data/models/ib/spread.rb +176 -0
- data/models/ib/stock.rb +25 -0
- data/models/ib/underlying.rb +32 -0
- data/plugins/ib/advanced-account.rb +442 -0
- data/plugins/ib/alerts/base-alert.rb +125 -0
- data/plugins/ib/alerts/gateway-alerts.rb +15 -0
- data/plugins/ib/alerts/order-alerts.rb +73 -0
- data/plugins/ib/auto-adjust.rb +0 -0
- data/plugins/ib/connection-tools.rb +122 -0
- data/plugins/ib/eod.rb +326 -0
- data/plugins/ib/greeks.rb +102 -0
- data/plugins/ib/managed-accounts.rb +274 -0
- data/plugins/ib/market-price.rb +150 -0
- data/plugins/ib/option-chain.rb +167 -0
- data/plugins/ib/order-flow.rb +157 -0
- data/plugins/ib/order-prototypes/abstract.rb +67 -0
- data/plugins/ib/order-prototypes/adaptive.rb +40 -0
- data/plugins/ib/order-prototypes/all-in-one.rb +46 -0
- data/plugins/ib/order-prototypes/combo.rb +46 -0
- data/plugins/ib/order-prototypes/forex.rb +40 -0
- data/plugins/ib/order-prototypes/limit.rb +193 -0
- data/plugins/ib/order-prototypes/market.rb +116 -0
- data/plugins/ib/order-prototypes/pegged.rb +169 -0
- data/plugins/ib/order-prototypes/premarket.rb +31 -0
- data/plugins/ib/order-prototypes/stop.rb +202 -0
- data/plugins/ib/order-prototypes/volatility.rb +39 -0
- data/plugins/ib/order-prototypes.rb +118 -0
- data/plugins/ib/probability-of-expiring.rb +109 -0
- data/plugins/ib/process-orders.rb +155 -0
- data/plugins/ib/roll.rb +86 -0
- data/plugins/ib/spread-prototypes/butterfly.rb +77 -0
- data/plugins/ib/spread-prototypes/calendar.rb +97 -0
- data/plugins/ib/spread-prototypes/stock-spread.rb +56 -0
- data/plugins/ib/spread-prototypes/straddle.rb +70 -0
- data/plugins/ib/spread-prototypes/strangle.rb +93 -0
- data/plugins/ib/spread-prototypes/vertical.rb +83 -0
- data/plugins/ib/spread-prototypes.rb +70 -0
- data/plugins/ib/symbols/abstract.rb +136 -0
- data/plugins/ib/symbols/bonds.rb +28 -0
- data/plugins/ib/symbols/cfd.rb +19 -0
- data/plugins/ib/symbols/combo.rb +46 -0
- data/plugins/ib/symbols/commodity.rb +17 -0
- data/plugins/ib/symbols/forex.rb +41 -0
- data/plugins/ib/symbols/futures.rb +127 -0
- data/plugins/ib/symbols/index.rb +43 -0
- data/plugins/ib/symbols/options.rb +99 -0
- data/plugins/ib/symbols/stocks.rb +44 -0
- data/plugins/ib/symbols/version.rb +5 -0
- data/plugins/ib/symbols.rb +118 -0
- data/plugins/ib/verify.rb +226 -0
- data/symbols/w20.yml +210 -0
- data/t.txt +20 -0
- data/update.md +71 -0
- 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
|