ib-api 972.0
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 +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
|