ib-api 972.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +50 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +105 -0
- data/Guardfile +24 -0
- data/LICENSE +674 -0
- data/README.md +65 -0
- data/Rakefile +11 -0
- data/VERSION +1 -0
- data/api.gemspec +43 -0
- data/bin/console +95 -0
- data/bin/console.yml +3 -0
- data/bin/setup +8 -0
- data/changelog.md +7 -0
- data/example/README.md +76 -0
- data/example/account_info +54 -0
- data/example/account_positions +30 -0
- data/example/account_summary +88 -0
- data/example/cancel_orders +74 -0
- data/example/fa_accounts +25 -0
- data/example/fundamental_data +40 -0
- data/example/historic_data_cli +186 -0
- data/example/list_orders +45 -0
- data/example/portfolio_csv +81 -0
- data/example/scanner_data +62 -0
- data/example/template +19 -0
- data/example/tick_data +28 -0
- data/lib/extensions/class-extensions.rb +87 -0
- data/lib/ib-api.rb +7 -0
- data/lib/ib/base.rb +103 -0
- data/lib/ib/base_properties.rb +160 -0
- data/lib/ib/connection.rb +450 -0
- data/lib/ib/constants.rb +393 -0
- data/lib/ib/errors.rb +44 -0
- data/lib/ib/logger.rb +26 -0
- data/lib/ib/messages.rb +99 -0
- data/lib/ib/messages/abstract_message.rb +101 -0
- data/lib/ib/messages/incoming.rb +251 -0
- data/lib/ib/messages/incoming/abstract_message.rb +116 -0
- data/lib/ib/messages/incoming/account_value.rb +78 -0
- data/lib/ib/messages/incoming/alert.rb +34 -0
- data/lib/ib/messages/incoming/contract_data.rb +102 -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/historical_data.rb +84 -0
- data/lib/ib/messages/incoming/market_depths.rb +44 -0
- data/lib/ib/messages/incoming/next_valid_id.rb +18 -0
- data/lib/ib/messages/incoming/open_order.rb +277 -0
- data/lib/ib/messages/incoming/order_status.rb +85 -0
- data/lib/ib/messages/incoming/portfolio_value.rb +78 -0
- data/lib/ib/messages/incoming/real_time_bar.rb +32 -0
- data/lib/ib/messages/incoming/scanner_data.rb +54 -0
- data/lib/ib/messages/incoming/ticks.rb +268 -0
- data/lib/ib/messages/outgoing.rb +437 -0
- data/lib/ib/messages/outgoing/abstract_message.rb +88 -0
- data/lib/ib/messages/outgoing/account_requests.rb +112 -0
- data/lib/ib/messages/outgoing/bar_requests.rb +250 -0
- data/lib/ib/messages/outgoing/place_order.rb +209 -0
- data/lib/ib/messages/outgoing/request_marketdata.rb +99 -0
- data/lib/ib/messages/outgoing/request_tick_data.rb +21 -0
- data/lib/ib/model.rb +4 -0
- data/lib/ib/models.rb +14 -0
- data/lib/ib/server_versions.rb +114 -0
- data/lib/ib/socket.rb +185 -0
- data/lib/ib/support.rb +160 -0
- data/lib/ib/version.rb +6 -0
- data/lib/models/ib/account.rb +85 -0
- data/lib/models/ib/account_value.rb +33 -0
- data/lib/models/ib/bag.rb +55 -0
- data/lib/models/ib/bar.rb +31 -0
- data/lib/models/ib/combo_leg.rb +105 -0
- data/lib/models/ib/condition.rb +245 -0
- data/lib/models/ib/contract.rb +415 -0
- data/lib/models/ib/contract_detail.rb +108 -0
- data/lib/models/ib/execution.rb +67 -0
- data/lib/models/ib/forex.rb +13 -0
- data/lib/models/ib/future.rb +15 -0
- data/lib/models/ib/index.rb +15 -0
- data/lib/models/ib/option.rb +78 -0
- data/lib/models/ib/option_detail.rb +55 -0
- data/lib/models/ib/order.rb +519 -0
- data/lib/models/ib/order_state.rb +152 -0
- data/lib/models/ib/portfolio_value.rb +64 -0
- data/lib/models/ib/stock.rb +16 -0
- data/lib/models/ib/underlying.rb +34 -0
- data/lib/models/ib/vertical.rb +96 -0
- data/lib/requires.rb +12 -0
- metadata +203 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
|
5
|
+
MarketDepth =
|
6
|
+
def_message 12, [:request_id, :int],
|
7
|
+
[:position, :int], # The row Id of this market depth entry.
|
8
|
+
[:operation, :int], # How it should be applied to the market depth:
|
9
|
+
# 0 = insert this new order into the row identified by :position
|
10
|
+
# 1 = update the existing order in the row identified by :position
|
11
|
+
# 2 = delete the existing order at the row identified by :position
|
12
|
+
[:side, :int], # side of the book: 0 = ask, 1 = bid
|
13
|
+
[:price, :decimal],
|
14
|
+
[:size, :int]
|
15
|
+
|
16
|
+
class MarketDepth
|
17
|
+
def side
|
18
|
+
@data[:side] == 0 ? :ask : :bid
|
19
|
+
end
|
20
|
+
|
21
|
+
def operation
|
22
|
+
@data[:operation] == 0 ? :insert : @data[:operation] == 1 ? :update : :delete
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_human
|
26
|
+
"<#{self.message_type}: #{operation} #{side} @ "+
|
27
|
+
"#{position} = #{price} x #{size}>"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
MarketDepthL2 =
|
32
|
+
def_message 13, MarketDepth, # Fields descriptions - see above
|
33
|
+
[:request_id, :int],
|
34
|
+
[:position, :int],
|
35
|
+
[:market_maker, :string], # The exchange hosting this order.
|
36
|
+
[:operation, :int],
|
37
|
+
[:side, :int],
|
38
|
+
[:price, :decimal],
|
39
|
+
[:size, :int]
|
40
|
+
|
41
|
+
|
42
|
+
end # module Incoming
|
43
|
+
end # module Messages
|
44
|
+
end # module IB
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
|
5
|
+
# This message is always sent by TWS automatically at connect.
|
6
|
+
# The IB::Connection class subscribes to it automatically and stores
|
7
|
+
# the order id in its @next_local_id attribute.
|
8
|
+
NextValidID = NextValidId = def_message(9, [:local_id, :int])
|
9
|
+
|
10
|
+
class NextValidId
|
11
|
+
|
12
|
+
# Legacy accessor
|
13
|
+
alias order_id local_id
|
14
|
+
|
15
|
+
end # class NextValidId
|
16
|
+
end # module Incoming
|
17
|
+
end # module Messages
|
18
|
+
end # module IB
|
@@ -0,0 +1,277 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
using IBSupport
|
5
|
+
# OpenOrder is the longest message with complex processing logics
|
6
|
+
OpenOrder =
|
7
|
+
def_message [5, 34], # updated to v. 34 according to python (decoder.py processOpenOrder)
|
8
|
+
[:order, :local_id, :int],
|
9
|
+
|
10
|
+
[:contract, :contract], # read standard-contract
|
11
|
+
# [ con_id, symbol,. sec_type, expiry, strike, right, multiplier,
|
12
|
+
# exchange, currency, local_symbol, trading_class ]
|
13
|
+
|
14
|
+
[:order, :action, :string],
|
15
|
+
[:order, :total_quantity, :decimal],
|
16
|
+
[:order, :order_type, :string],
|
17
|
+
[:order, :limit_price, :decimal],
|
18
|
+
[:order, :aux_price, :decimal],
|
19
|
+
[:order, :tif, :string],
|
20
|
+
[:order, :oca_group, :string],
|
21
|
+
[:order, :account, :string],
|
22
|
+
[:order, :open_close, :string],
|
23
|
+
[:order, :origin, :int],
|
24
|
+
[:order, :order_ref, :string],
|
25
|
+
[:order, :client_id, :int],
|
26
|
+
[:order, :perm_id, :int],
|
27
|
+
[:order, :outside_rth, :boolean], # (@socket.read_int == 1)
|
28
|
+
[:order, :hidden, :boolean], # (@socket.read_int == 1)
|
29
|
+
[:order, :discretionary_amount, :decimal],
|
30
|
+
[:order, :good_after_time, :string],
|
31
|
+
[:shares_allocation, :string], # deprecated! field
|
32
|
+
|
33
|
+
[:order, :fa_group, :string],
|
34
|
+
[:order, :fa_method, :string],
|
35
|
+
[:order, :fa_percentage, :string],
|
36
|
+
[:order, :fa_profile, :string],
|
37
|
+
[:order, :model_code, :string],
|
38
|
+
[:order, :good_till_date, :string],
|
39
|
+
[:order, :rule_80a, :string],
|
40
|
+
[:order, :percent_offset, :decimal],
|
41
|
+
[:order, :settling_firm, :string],
|
42
|
+
[:order, :short_sale_slot, :int],
|
43
|
+
[:order, :designated_location, :string],
|
44
|
+
[:order, :exempt_code, :int],
|
45
|
+
[:order, :auction_strategy, :int],
|
46
|
+
[:order, :starting_price, :decimal],
|
47
|
+
[:order, :stock_ref_price, :decimal],
|
48
|
+
[:order, :delta, :decimal],
|
49
|
+
[:order, :stock_range_lower, :decimal],
|
50
|
+
[:order, :stock_range_upper, :decimal],
|
51
|
+
[:order, :display_size, :int],
|
52
|
+
#@order.rth_only = @socket.read_boolean
|
53
|
+
[:order, :block_order, :boolean],
|
54
|
+
[:order, :sweep_to_fill, :boolean],
|
55
|
+
[:order, :all_or_none, :boolean],
|
56
|
+
[:order, :min_quantity, :int],
|
57
|
+
[:order, :oca_type, :int],
|
58
|
+
[:order, :etrade_only, :boolean],
|
59
|
+
[:order, :firm_quote_only, :boolean],
|
60
|
+
[:order, :nbbo_price_cap, :decimal],
|
61
|
+
[:order, :parent_id, :int],
|
62
|
+
[:order, :trigger_method, :int],
|
63
|
+
[:order, :volatility, :decimal],
|
64
|
+
[:order, :volatility_type, :int],
|
65
|
+
[:order, :delta_neutral_order_type, :string],
|
66
|
+
[:order, :delta_neutral_aux_price, :decimal]
|
67
|
+
|
68
|
+
class OpenOrder
|
69
|
+
|
70
|
+
# Accessors to make OpenOrder API-compatible with OrderStatus message
|
71
|
+
|
72
|
+
def client_id
|
73
|
+
order.client_id
|
74
|
+
end
|
75
|
+
|
76
|
+
def parent_id
|
77
|
+
order.parent_id
|
78
|
+
end
|
79
|
+
|
80
|
+
def perm_id
|
81
|
+
order.perm_id
|
82
|
+
end
|
83
|
+
|
84
|
+
def local_id
|
85
|
+
order.local_id
|
86
|
+
end
|
87
|
+
|
88
|
+
alias order_id local_id
|
89
|
+
|
90
|
+
def status
|
91
|
+
order.status
|
92
|
+
end
|
93
|
+
|
94
|
+
def conditions
|
95
|
+
order.conditions
|
96
|
+
end
|
97
|
+
|
98
|
+
# Object accessors
|
99
|
+
|
100
|
+
def order
|
101
|
+
@order ||= IB::Order.new @data[:order].merge(:order_state => order_state)
|
102
|
+
end
|
103
|
+
|
104
|
+
def order_state
|
105
|
+
@order_state ||= IB::OrderState.new(
|
106
|
+
@data[:order_state].merge(
|
107
|
+
:local_id => @data[:order][:local_id],
|
108
|
+
:perm_id => @data[:order][:perm_id],
|
109
|
+
:parent_id => @data[:order][:parent_id],
|
110
|
+
:client_id => @data[:order][:client_id]))
|
111
|
+
end
|
112
|
+
|
113
|
+
def contract
|
114
|
+
@contract ||= IB::Contract.build(
|
115
|
+
@data[:contract].merge(:underlying => underlying)
|
116
|
+
)
|
117
|
+
end
|
118
|
+
|
119
|
+
def underlying
|
120
|
+
@underlying = @data[:underlying_present] ? IB::Underlying.new(@data[:underlying]) : nil
|
121
|
+
end
|
122
|
+
|
123
|
+
alias under_comp underlying
|
124
|
+
|
125
|
+
def load
|
126
|
+
super
|
127
|
+
|
128
|
+
# load_map [proc { | | (@data[:order][:delta_neutral_order_type] != 'None') },
|
129
|
+
load_map [proc { | | filled?(@data[:order][:delta_neutral_order_type]) }, # todo Testcase!
|
130
|
+
# As of client v.52, we may receive delta... params in openOrder
|
131
|
+
[:order, :delta_neutral_con_id, :int],
|
132
|
+
[:order, :delta_neutral_settling_firm, :string],
|
133
|
+
[:order, :delta_neutral_clearing_account, :string],
|
134
|
+
[:order, :delta_neutral_clearing_intent, :string],
|
135
|
+
[:order, :delta_neutral_open_close, :string],
|
136
|
+
[:order, :delta_neutral_short_sale, :bool],
|
137
|
+
[:order, :delta_neutral_short_sale_slot, :int],
|
138
|
+
[:order, :delta_neutral_designated_location, :string] ], # end proc
|
139
|
+
[:order, :continuous_update, :int],
|
140
|
+
[:order, :reference_price_type, :int],
|
141
|
+
[:order, :trail_stop_price, :decimal], # not trail-orders. see below
|
142
|
+
[:order, :trailing_percent, :decimal],
|
143
|
+
[:order, :basis_points, :decimal],
|
144
|
+
[:order, :basis_points_type, :int],
|
145
|
+
|
146
|
+
[:contract, :legs_description, :string],
|
147
|
+
|
148
|
+
# As of client v.55, we receive in OpenOrder for Combos:
|
149
|
+
# Contract.orderComboLegs Array
|
150
|
+
# Order.leg_prices Array
|
151
|
+
[:contract, :combo_legs, :array, proc do |_|
|
152
|
+
IB::ComboLeg.new :con_id => @buffer.read_int,
|
153
|
+
:ratio => @buffer.read_int,
|
154
|
+
:action => @buffer.read_string,
|
155
|
+
:exchange => @buffer.read_string,
|
156
|
+
:open_close => @buffer.read_int,
|
157
|
+
:short_sale_slot => @buffer.read_int,
|
158
|
+
:designated_location => @buffer.read_string,
|
159
|
+
:exempt_code => @buffer.read_int
|
160
|
+
end],
|
161
|
+
[:order, :leg_prices, :array, proc { |_| buffer.read_decimal }], # needs testing
|
162
|
+
[:order, :combo_params, :hash ],
|
163
|
+
#, proc do |_|
|
164
|
+
# { tag: buffer.read_string, value: buffer.read_string } # needs testing
|
165
|
+
# end],
|
166
|
+
|
167
|
+
[:order, :scale_init_level_size, :int],
|
168
|
+
[:order, :scale_subs_level_size, :int],
|
169
|
+
|
170
|
+
[:order, :scale_price_increment, :decimal],
|
171
|
+
[proc { | | filled?(@data[:order][:scale_price_increment]) },
|
172
|
+
# As of client v.54, we may receive scale order fields
|
173
|
+
[:order, :scale_price_adjust_value, :decimal],
|
174
|
+
[:order, :scale_price_adjust_interval, :int],
|
175
|
+
[:order, :scale_profit_offset, :decimal],
|
176
|
+
[:order, :scale_auto_reset, :boolean],
|
177
|
+
[:order, :scale_init_position, :int],
|
178
|
+
[:order, :scale_init_fill_qty, :decimal],
|
179
|
+
[:order, :scale_random_percent, :boolean]
|
180
|
+
],
|
181
|
+
|
182
|
+
[:order, :hedge_type, :string],
|
183
|
+
[proc { | | filled?(@data[:order][:hedge_type]) },
|
184
|
+
# As of client v.49/50, we can receive hedgeType, hedgeParam
|
185
|
+
[:order, :hedge_param, :string]
|
186
|
+
],
|
187
|
+
|
188
|
+
[:order, :opt_out_smart_routing, :boolean],
|
189
|
+
[:order, :clearing_account, :string],
|
190
|
+
[:order, :clearing_intent, :string],
|
191
|
+
[:order, :not_held, :boolean],
|
192
|
+
|
193
|
+
[:underlying_present, :boolean],
|
194
|
+
[proc { | | filled?(@data[:underlying_present]) },
|
195
|
+
[:underlying, :con_id, :int],
|
196
|
+
[:underlying, :delta, :decimal],
|
197
|
+
[:underlying, :price, :decimal]
|
198
|
+
],
|
199
|
+
|
200
|
+
# TODO: Test Order with algo_params, scale and legs!
|
201
|
+
[:order, :algo_strategy, :string],
|
202
|
+
[proc { | | filled?(@data[:order][:algo_strategy]) },
|
203
|
+
[:order, :algo_params, :hash]
|
204
|
+
],
|
205
|
+
[:order, :solicided, :boolean],
|
206
|
+
[:order, :what_if, :boolean],
|
207
|
+
[:order_state, :status, :string],
|
208
|
+
# IB uses weird String with Java Double.MAX_VALUE to indicate no value here
|
209
|
+
[:order_state, :init_margin, :decimal], # :string],
|
210
|
+
[:order_state, :maint_margin, :decimal], # :string],
|
211
|
+
[:order_state, :equity_with_loan, :decimal], # :string],
|
212
|
+
[:order_state, :commission, :decimal], # May be nil!
|
213
|
+
[:order_state, :min_commission, :decimal], # May be nil!
|
214
|
+
[:order_state, :max_commission, :decimal], # May be nil!
|
215
|
+
[:order_state, :commission_currency, :string],
|
216
|
+
[:order_state, :warning_text, :string],
|
217
|
+
|
218
|
+
|
219
|
+
[:order, :random_size, :boolean],
|
220
|
+
[:order, :random_price, :boolean],
|
221
|
+
|
222
|
+
## todo: ordertype = PEG BENCH -- -> test!
|
223
|
+
[proc{ @data[:order][:order_type] == 'PEG BENCH' },
|
224
|
+
[:order, :reference_contract_id, :int ],
|
225
|
+
[:order, :is_pegged_change_amount_decrease, :bool ],
|
226
|
+
[:order, :pegged_change_amount, :decimal ],
|
227
|
+
[:order, :reference_change_amount, :decimal ],
|
228
|
+
[:order, :reference_exchange_id, :string ]
|
229
|
+
],
|
230
|
+
[:order , :conditions, :array, proc { IB::OrderCondition.make_from( @buffer ) } ],
|
231
|
+
[proc { !@data[:order][:conditions].blank? },
|
232
|
+
[:order, :conditions_ignore_rth, :bool],
|
233
|
+
[:order, :conditions_cancel_order,:bool]
|
234
|
+
],
|
235
|
+
[:order, :adjusted_order_type, :string],
|
236
|
+
[:order, :trigger_price, :decimal],
|
237
|
+
[:order, :trail_stop_price, :decimal], # cpp -source: Traillimit orders
|
238
|
+
[:order, :adjusted_stop_limit_price, :decimal],
|
239
|
+
[:order, :adjusted_trailing_amount, :decimal],
|
240
|
+
[:order, :adjustable_trailing_unit, :int],
|
241
|
+
|
242
|
+
[:order, :soft_dollar_tier_name, :string_not_null],
|
243
|
+
[:order, :soft_dollar_tier_value, :string_not_null],
|
244
|
+
[:order, :soft_dollar_tier_display_name, :string_not_null],
|
245
|
+
[:order, :cash_qty, :decimal],
|
246
|
+
[:order, :mifid_2_decision_maker, :string_not_null ], ## correct appearance of fields below
|
247
|
+
[:order, :mifid_2_decision_algo, :string_not_null ], ## is not tested yet
|
248
|
+
[:order, :mifid_2_execution_maker, :string ],
|
249
|
+
[:order, :mifid_2_execution_algo, :string_not_null ],
|
250
|
+
[:order, :dont_use_auto_price_for_hedge, :string ],
|
251
|
+
[:order, :is_O_ms_container, :bool ],
|
252
|
+
[ :order, :discretionary_up_to_limit_price, :decimal ]
|
253
|
+
|
254
|
+
|
255
|
+
end
|
256
|
+
|
257
|
+
# Check if given value was set by TWS to something vaguely "positive"
|
258
|
+
def filled? value
|
259
|
+
# puts "filled: #{value.class} --> #{value.to_s}"
|
260
|
+
case value
|
261
|
+
when String
|
262
|
+
(!value.empty?)# && (value != :none) && (value !='None')
|
263
|
+
when Float, Integer, BigDecimal
|
264
|
+
value > 0
|
265
|
+
else
|
266
|
+
!!value # to_bool
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
def to_human
|
271
|
+
"<OpenOrder: #{contract.to_human} #{order.to_human}>"
|
272
|
+
end
|
273
|
+
|
274
|
+
end # class OpenOrder
|
275
|
+
end # module Incoming
|
276
|
+
end # module Messages
|
277
|
+
end # module IB
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
|
5
|
+
# :status - Displays the order status. Possible values include:
|
6
|
+
# - PendingSubmit - indicates that you have transmitted the order, but
|
7
|
+
# have not yet received confirmation that it has been accepted by the
|
8
|
+
# order destination. NOTE: This order status is NOT sent back by TWS
|
9
|
+
# and should be explicitly set by YOU when an order is submitted.
|
10
|
+
# - PendingCancel - indicates that you have sent a request to cancel
|
11
|
+
# the order but have not yet received cancel confirmation from the
|
12
|
+
# order destination. At this point, your order cancel is not confirmed.
|
13
|
+
# You may still receive an execution while your cancellation request
|
14
|
+
# is pending. NOTE: This order status is not sent back by TWS and
|
15
|
+
# should be explicitly set by YOU when an order is canceled.
|
16
|
+
# - PreSubmitted - indicates that a simulated order type has been
|
17
|
+
# accepted by the IB system and that this order has yet to be elected.
|
18
|
+
# The order is held in the IB system until the election criteria are
|
19
|
+
# met. At that time the order is transmitted to the order destination
|
20
|
+
# as specified.
|
21
|
+
# - Submitted - indicates that your order has been accepted at the order
|
22
|
+
# destination and is working.
|
23
|
+
# - Cancelled - indicates that the balance of your order has been
|
24
|
+
# confirmed canceled by the IB system. This could occur unexpectedly
|
25
|
+
# when IB or the destination has rejected your order.
|
26
|
+
# - ApiCancelled - canceled via API
|
27
|
+
# - Filled - indicates that the order has been completely filled.
|
28
|
+
# - Inactive - indicates that the order has been accepted by the system
|
29
|
+
# (simulated orders) or an exchange (native orders) but that currently
|
30
|
+
# the order is inactive due to system, exchange or other issues.
|
31
|
+
# :why_held - This property contains the comma-separated list of reasons for
|
32
|
+
# order to be held. For example, when TWS is trying to locate shares for
|
33
|
+
# a short sell, the value used to indicate this is 'locate'.
|
34
|
+
# As of Api 9.72, no version is given anymore
|
35
|
+
#
|
36
|
+
OrderStatus = def_message [3, 0],
|
37
|
+
[:order_state, :local_id, :int],
|
38
|
+
[:order_state, :status, :string],
|
39
|
+
[:order_state, :filled, :decimal],
|
40
|
+
[:order_state, :remaining, :decimal],
|
41
|
+
[:order_state, :average_fill_price, :decimal],
|
42
|
+
[:order_state, :perm_id, :int],
|
43
|
+
[:order_state, :parent_id, :int],
|
44
|
+
[:order_state, :last_fill_price, :decimal],
|
45
|
+
[:order_state, :client_id, :int],
|
46
|
+
[:order_state, :why_held, :string],
|
47
|
+
[:order_state, :market_cap_price, :decimal]
|
48
|
+
class OrderStatus
|
49
|
+
|
50
|
+
|
51
|
+
def order_state
|
52
|
+
@order_state ||= IB::OrderState.new @data[:order_state]
|
53
|
+
end
|
54
|
+
|
55
|
+
# Accessors to make OpenOrder and OrderStatus messages API-compatible
|
56
|
+
def client_id
|
57
|
+
order_state.client_id
|
58
|
+
end
|
59
|
+
|
60
|
+
def parent_id
|
61
|
+
order_state.parent_id
|
62
|
+
end
|
63
|
+
|
64
|
+
def perm_id
|
65
|
+
order_state.perm_id
|
66
|
+
end
|
67
|
+
|
68
|
+
def local_id
|
69
|
+
order_state.local_id
|
70
|
+
end
|
71
|
+
|
72
|
+
alias order_id local_id
|
73
|
+
|
74
|
+
def status
|
75
|
+
order_state.status
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_human
|
79
|
+
order_state.to_human
|
80
|
+
end
|
81
|
+
|
82
|
+
end # class OrderStatus
|
83
|
+
end # module Incoming
|
84
|
+
end # module Messages
|
85
|
+
end # module IB
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
|
5
|
+
class ContractMessage < AbstractMessage
|
6
|
+
def contract
|
7
|
+
@contract = IB::Contract.build @data[:contract]
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
PortfolioValue = def_message [7, 8], ContractMessage,
|
12
|
+
[:contract, :contract], # read standard-contract
|
13
|
+
[:portfolio_value, :position, :decimal],
|
14
|
+
[:portfolio_value,:market_price, :decimal],
|
15
|
+
[:portfolio_value,:market_value, :decimal],
|
16
|
+
[:portfolio_value,:average_cost, :decimal],
|
17
|
+
[:portfolio_value,:unrealized_pnl, :decimal], # May be nil!
|
18
|
+
[:portfolio_value,:realized_pnl, :decimal], # May be nil!
|
19
|
+
[:account, :string]
|
20
|
+
|
21
|
+
|
22
|
+
class PortfolioValue
|
23
|
+
|
24
|
+
|
25
|
+
def to_human
|
26
|
+
# "<PortfolioValue: #{contract.to_human} #{portfolio_value}>"
|
27
|
+
portfolio_value.to_human
|
28
|
+
end
|
29
|
+
|
30
|
+
def portfolio_value
|
31
|
+
unless @portfolio_value.present?
|
32
|
+
@portfolio_value = IB::PortfolioValue.new @data[:portfolio_value]
|
33
|
+
@portfolio_value.contract = contract
|
34
|
+
@portfolio_value.account = account
|
35
|
+
end
|
36
|
+
@portfolio_value # return_value
|
37
|
+
end
|
38
|
+
|
39
|
+
def account_name
|
40
|
+
@account_name = @data[:account]
|
41
|
+
end
|
42
|
+
|
43
|
+
# alias :to_human :portfolio_value
|
44
|
+
end # PortfolioValue
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
PositionData =
|
49
|
+
def_message( [61,3] , ContractMessage,
|
50
|
+
[:account, :string],
|
51
|
+
[:contract, :contract], # read standard-contract
|
52
|
+
# [ con_id, symbol,. sec_type, expiry, strike, right, multiplier,
|
53
|
+
# primary_exchange, currency, local_symbol, trading_class ]
|
54
|
+
[:position, :decimal], # changed from int after Server Vers. MIN_SERVER_VER_FRACTIONAL_POSITIONS
|
55
|
+
[:price, :decimal]
|
56
|
+
) do
|
57
|
+
# def to_human
|
58
|
+
"<PositionValue: #{account} -> #{contract.to_human} ( Amount #{position}) : Market-Price #{price} >"
|
59
|
+
end
|
60
|
+
|
61
|
+
PositionDataEnd = def_message( 62 )
|
62
|
+
PositionsMulti = def_message( 71, ContractMessage,
|
63
|
+
[ :request_id, :int ],
|
64
|
+
[ :account, :string ],
|
65
|
+
[:contract, :contract], # read standard-contract
|
66
|
+
[ :position, :decimal], # changed from int after Server Vers. MIN_SERVER_VER_FRACTIONAL_POSITIONS
|
67
|
+
[ :average_cost, :decimal],
|
68
|
+
[ :model_code, :string ])
|
69
|
+
|
70
|
+
PositionsMultiEnd = def_message 72
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
end # module Incoming
|
77
|
+
end # module Messages
|
78
|
+
end # module IB
|