ib-ruby 0.7.12 → 0.8.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.
- data/HISTORY +4 -0
- data/README.md +44 -21
- data/VERSION +1 -1
- data/lib/ib-ruby/messages/incoming/contract_data.rb +1 -1
- data/lib/ib-ruby/messages/incoming/execution_data.rb +1 -1
- data/lib/ib-ruby/messages/incoming/open_order.rb +1 -2
- data/lib/ib-ruby/messages/incoming.rb +5 -5
- data/lib/ib-ruby/messages/outgoing/place_order.rb +137 -3
- data/lib/ib-ruby/models/order.rb +19 -153
- data/spec/README.md +47 -12
- data/spec/account_helper.rb +12 -3
- data/spec/ib-ruby/messages/incoming/open_order_spec.rb +15 -4
- data/spec/integration/contract_info_spec.rb +6 -0
- data/spec/integration/orders/attached_spec.rb +18 -19
- data/spec/integration/orders/combo_spec.rb +1 -0
- data/spec/integration/orders/trades_spec.rb +81 -1
- data/spec/order_helper.rb +0 -23
- data/spec/spec_helper.rb +4 -2
- data/spec/tws.rb +4 -0
- metadata +523 -299
data/HISTORY
CHANGED
data/README.md
CHANGED
@@ -69,7 +69,8 @@ other API implementations. The choice is yours.
|
|
69
69
|
|:------------|------------:|:------------:|
|
70
70
|
| 0.5.21 | 918-920 | 965 |
|
71
71
|
| 0.6.1 | 921-923 | 966 |
|
72
|
-
| 0.7.1+ |
|
72
|
+
| 0.7.1+ | 924-925 | 966 |
|
73
|
+
| 0.8.0+ | 926+ | 967 |
|
73
74
|
|
74
75
|
4. Start Interactive Broker's Trader Work Station or Gateway before your code
|
75
76
|
attempts to connect to it. Note that TWS and Gateway listen to different ports,
|
@@ -122,26 +123,6 @@ The sample scripts in `bin` directory provide examples of how common tasks
|
|
122
123
|
can be achieved using ib-ruby. You may also want to look into `spec/integration`
|
123
124
|
directory for more scenarios and examples of handling IB messages.
|
124
125
|
|
125
|
-
## RUNNING TESTS:
|
126
|
-
|
127
|
-
The gem comes with a spec suit that may be used to test ib-ruby compatibility
|
128
|
-
with your specific TWS/Gateway installation. The test suit should be run ONLY
|
129
|
-
against your IB paper trading account. Running it against live account may result
|
130
|
-
in financial losses.
|
131
|
-
|
132
|
-
In order to run tests, you should set up your IB paper trading connection parameters
|
133
|
-
in 'spec/spec_helper' file. Modify account_name, host and port under section
|
134
|
-
'Your IB PAPER ACCOUNT'. Do not change the client_id.
|
135
|
-
|
136
|
-
Before running tests, you need to start your TWS/Gateway and allow API connection.
|
137
|
-
You should not have any open/pending orders on your IB paper trading account prior
|
138
|
-
to running tests, otherwise some tests will fail. Use 'bin/cancel_orders' script for
|
139
|
-
bulk cancelling of open orders before running tests as needed.
|
140
|
-
|
141
|
-
You can easily create your own tests following the guide in 'spec/README'.
|
142
|
-
Help the development! See 'spec/TODO' for the list of use cases/scenarios
|
143
|
-
that still need to be tested.
|
144
|
-
|
145
126
|
## DB BACKEND:
|
146
127
|
|
147
128
|
Latest versions of the gem added (optional and experimental) support for data
|
@@ -168,6 +149,48 @@ you don't need IB::DB.connect part, Rails will take care of it for you. So, just
|
|
168
149
|
Now, all your IB Models are just ActiveRecords and you can do whatever you want with them:
|
169
150
|
persist to DB, use in Rails applications, develop controllers and views.
|
170
151
|
|
152
|
+
|
153
|
+
## RUNNING TESTS:
|
154
|
+
|
155
|
+
The gem comes with a spec suit that may be used to test ib-ruby compatibility
|
156
|
+
with your specific TWS/Gateway installation. The test suit should be run ONLY
|
157
|
+
against your IB paper trading account. Running it against live account may result
|
158
|
+
in financial losses.
|
159
|
+
|
160
|
+
In order to run tests, you should set up your IB paper trading connection parameters
|
161
|
+
in 'spec/spec_helper' file. Modify account_name, host and port under section
|
162
|
+
'Your IB PAPER ACCOUNT'. Do not change the client_id.
|
163
|
+
|
164
|
+
Before running tests, you need to start your TWS/Gateway and allow API connection.
|
165
|
+
You should not have any open/pending orders on your IB paper trading account prior
|
166
|
+
to running tests, otherwise some tests will fail. Use 'bin/cancel_orders' script for
|
167
|
+
bulk cancelling of open orders before running tests as needed.
|
168
|
+
|
169
|
+
By default, specs are run without database support (tableless). In order to run them
|
170
|
+
with database backend, use:
|
171
|
+
|
172
|
+
$ rspec -rdb [spec/specific_spec.rb]
|
173
|
+
|
174
|
+
Also, by default, specs suppress logging output that is normally produced by IB::Connection.
|
175
|
+
This may make it difficult to debug a failing spec. Following option will switch on verbose
|
176
|
+
output (both logger output and content of all received IB messages is dumped). Do not use
|
177
|
+
this mode to run a whole spec - you will be swamped! Use it to debug specific failing specs
|
178
|
+
only:
|
179
|
+
|
180
|
+
$ rspec -rv [spec/specific_spec.rb]
|
181
|
+
|
182
|
+
You can easily create your own tests following the guide in 'spec/README'.
|
183
|
+
Help the development! See 'spec/TODO' for the list of use cases/scenarios
|
184
|
+
that still need to be tested.
|
185
|
+
|
186
|
+
## CONTRIBUTING:
|
187
|
+
|
188
|
+
1. Fork it
|
189
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
190
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
191
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
192
|
+
5. Create new Pull Request
|
193
|
+
|
171
194
|
## LICENSE:
|
172
195
|
|
173
196
|
This software is available under the LGPL.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.8.0
|
@@ -4,7 +4,7 @@ module IB
|
|
4
4
|
|
5
5
|
# OpenOrder is the longest message with complex processing logics
|
6
6
|
OpenOrder =
|
7
|
-
def_message [5, [23, 28]],
|
7
|
+
def_message [5, [23, 28, 30]],
|
8
8
|
[:order, :local_id, :int],
|
9
9
|
|
10
10
|
[:contract, :con_id, :int],
|
@@ -130,7 +130,6 @@ module IB
|
|
130
130
|
[:order, :basis_points_type, :int_max],
|
131
131
|
[:contract, :legs_description, :string],
|
132
132
|
|
133
|
-
# Never happens! 28 is the max supported version currently
|
134
133
|
# As of client v.55, we receive orderComboLegs (price) in openOrder
|
135
134
|
[29, [:contract, :legs, :array, proc do |_|
|
136
135
|
IB::ComboLeg.new :con_id => socket.read_int,
|
@@ -67,12 +67,12 @@ module IB
|
|
67
67
|
MarketDataType = def_message 58, [:request_id, :int], [:market_data_type, :int]
|
68
68
|
|
69
69
|
CommissionReport =
|
70
|
-
def_message 59, [:exec_id, :
|
70
|
+
def_message 59, [:exec_id, :string],
|
71
71
|
[:commission, :decimal], # Commission amount.
|
72
|
-
[:currency, :
|
73
|
-
[:realized_pnl, :
|
74
|
-
[:yield, :
|
75
|
-
[:yield_redemption_date, :int]
|
72
|
+
[:currency, :string], # Commission currency
|
73
|
+
[:realized_pnl, :decimal_max],
|
74
|
+
[:yield, :decimal_max],
|
75
|
+
[:yield_redemption_date, :int] # YYYYMMDD format
|
76
76
|
|
77
77
|
### Require standalone source files for more complex message classes:
|
78
78
|
|
@@ -5,16 +5,150 @@ module IB
|
|
5
5
|
# Data format is { :id => int: local_id,
|
6
6
|
# :contract => Contract,
|
7
7
|
# :order => Order }
|
8
|
-
PlaceOrder = def_message [3,
|
8
|
+
PlaceOrder = def_message [3, 38] # v.38 is NOT properly supported by API yet ?!
|
9
9
|
|
10
10
|
class PlaceOrder
|
11
11
|
|
12
12
|
def encode server
|
13
13
|
# Old server version supports no enhancements
|
14
|
-
|
14
|
+
#@version = 31 if server[:server_version] <= 60
|
15
|
+
|
16
|
+
order = @data[:order]
|
17
|
+
contract = @data[:contract]
|
15
18
|
|
16
19
|
[super,
|
17
|
-
|
20
|
+
|
21
|
+
contract.serialize_long(:con_id, :sec_id),
|
22
|
+
|
23
|
+
# main order fields
|
24
|
+
case order.side
|
25
|
+
when :short
|
26
|
+
'SSHORT'
|
27
|
+
when :short_exempt
|
28
|
+
'SSHORTX'
|
29
|
+
else
|
30
|
+
order.side.to_sup
|
31
|
+
end,
|
32
|
+
order.quantity,
|
33
|
+
order[:order_type], # Internal code, 'LMT' instead of :limit
|
34
|
+
order.limit_price,
|
35
|
+
order.aux_price,
|
36
|
+
order[:tif],
|
37
|
+
order.oca_group,
|
38
|
+
order.account,
|
39
|
+
order.open_close.to_sup[0..0],
|
40
|
+
order[:origin],
|
41
|
+
order.order_ref,
|
42
|
+
order.transmit,
|
43
|
+
order.parent_id,
|
44
|
+
order.block_order || false,
|
45
|
+
order.sweep_to_fill || false,
|
46
|
+
order.display_size,
|
47
|
+
order[:trigger_method],
|
48
|
+
order.outside_rth || false, # was: ignore_rth
|
49
|
+
order.hidden || false,
|
50
|
+
contract.serialize_legs(:extended),
|
51
|
+
|
52
|
+
# This is specific to PlaceOrder v.38, NOT supported by API yet!
|
53
|
+
## Support for per-leg prices in Order
|
54
|
+
if server[:server_version] >= 61 && contract.bag?
|
55
|
+
#order.leg_prices.empty? ? 0 : [order.leg_prices.size] + order.leg_prices
|
56
|
+
[contract.legs.size] + contract.legs.map { |_| nil }
|
57
|
+
else
|
58
|
+
[]
|
59
|
+
end,
|
60
|
+
|
61
|
+
## Support for combo routing params in Order
|
62
|
+
if server[:server_version] >= 57 && contract.bag?
|
63
|
+
order.combo_params.empty? ? 0 : [order.combo_params.size] + order.combo_params.to_a
|
64
|
+
else
|
65
|
+
[]
|
66
|
+
end,
|
67
|
+
|
68
|
+
'', # deprecated shares_allocation field
|
69
|
+
order.discretionary_amount,
|
70
|
+
order.good_after_time,
|
71
|
+
order.good_till_date,
|
72
|
+
order.fa_group,
|
73
|
+
order.fa_method,
|
74
|
+
order.fa_percentage,
|
75
|
+
order.fa_profile,
|
76
|
+
order[:short_sale_slot], # 0 only for retail, 1 or 2 for institution (Institutional)
|
77
|
+
order.designated_location, # only populate when short_sale_slot == 2 (Institutional)
|
78
|
+
order.exempt_code,
|
79
|
+
order[:oca_type],
|
80
|
+
order.rule_80a,
|
81
|
+
order.settling_firm,
|
82
|
+
order.all_or_none || false,
|
83
|
+
order.min_quantity,
|
84
|
+
order.percent_offset,
|
85
|
+
order.etrade_only || false,
|
86
|
+
order.firm_quote_only || false,
|
87
|
+
order.nbbo_price_cap,
|
88
|
+
order[:auction_strategy],
|
89
|
+
order.starting_price,
|
90
|
+
order.stock_ref_price,
|
91
|
+
order.delta,
|
92
|
+
order.stock_range_lower,
|
93
|
+
order.stock_range_upper,
|
94
|
+
order.override_percentage_constraints || false,
|
95
|
+
order.volatility, # Volatility orders
|
96
|
+
order[:volatility_type], #
|
97
|
+
order[:delta_neutral_order_type],
|
98
|
+
order.delta_neutral_aux_price, #
|
99
|
+
|
100
|
+
# Support for delta neutral orders with parameters
|
101
|
+
if server[:server_version] >= 58 && order.delta_neutral_order_type
|
102
|
+
[order.delta_neutral_con_id,
|
103
|
+
order.delta_neutral_settling_firm,
|
104
|
+
order.delta_neutral_clearing_account,
|
105
|
+
order[:delta_neutral_clearing_intent]
|
106
|
+
]
|
107
|
+
else
|
108
|
+
[]
|
109
|
+
end,
|
110
|
+
|
111
|
+
order.continuous_update, # Volatility orders
|
112
|
+
order[:reference_price_type], # Volatility orders
|
113
|
+
|
114
|
+
order.trail_stop_price, # TRAIL_STOP_LIMIT stop price
|
115
|
+
|
116
|
+
# Support for trailing percent
|
117
|
+
server[:server_version] >= 62 ? order.trailing_percent : [],
|
118
|
+
|
119
|
+
order.scale_init_level_size, # Scale Orders
|
120
|
+
order.scale_subs_level_size, # Scale Orders
|
121
|
+
order.scale_price_increment, # Scale Orders
|
122
|
+
|
123
|
+
# Support extended scale orders parameters
|
124
|
+
if server[:server_version] >= 60 && # MIN_SERVER_VER_SCALE_ORDERS3
|
125
|
+
order.scale_price_increment && order.scale_price_increment > 0
|
126
|
+
[order.scale_price_adjust_value,
|
127
|
+
order.scale_price_adjust_interval,
|
128
|
+
order.scale_profit_offset,
|
129
|
+
order.scale_auto_reset || false,
|
130
|
+
order.scale_init_position,
|
131
|
+
order.scale_init_fill_qty,
|
132
|
+
order.scale_random_percent || false
|
133
|
+
]
|
134
|
+
else
|
135
|
+
[]
|
136
|
+
end,
|
137
|
+
|
138
|
+
# TODO: Need to add support for hedgeType, not working ATM - beta only
|
139
|
+
# MIN_SERVER_VER_HEDGE_ORDERS
|
140
|
+
server[:server_version] >= 54 ? [order.hedge_type, order.hedge_param || []] : [],
|
141
|
+
|
142
|
+
#MIN_SERVER_VER_OPT_OUT_SMART_ROUTING
|
143
|
+
server[:server_version] >= 56 ? (order.opt_out_smart_routing || false) : [],
|
144
|
+
|
145
|
+
order.clearing_account,
|
146
|
+
order.clearing_intent,
|
147
|
+
order.not_held || false,
|
148
|
+
contract.serialize_under_comp,
|
149
|
+
order.serialize_algo(),
|
150
|
+
order.what_if]
|
151
|
+
|
18
152
|
end
|
19
153
|
end # PlaceOrder
|
20
154
|
|
data/lib/ib-ruby/models/order.rb
CHANGED
@@ -213,19 +213,18 @@ module IB
|
|
213
213
|
# for ComboLeg compatibility: SAME = 0; OPEN = 1; CLOSE = 2; UNKNOWN = 3;
|
214
214
|
[:side, :action] => PROPS[:side] # String: Action/side: BUY/SELL/SSHORT/SSHORTX
|
215
215
|
|
216
|
-
prop :placed_at,
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
#
|
226
|
-
|
227
|
-
|
228
|
-
##serialize :combo_params
|
216
|
+
prop :placed_at,
|
217
|
+
:modified_at,
|
218
|
+
:leg_prices,
|
219
|
+
:algo_params,
|
220
|
+
:combo_params
|
221
|
+
|
222
|
+
alias order_combo_legs leg_prices
|
223
|
+
alias smart_combo_routing_params combo_params
|
224
|
+
|
225
|
+
#serialize :leg_prices
|
226
|
+
#serialize :algo_params
|
227
|
+
#serialize :combo_params
|
229
228
|
|
230
229
|
# Order is always placed for a contract. Here, we explicitly set this link.
|
231
230
|
belongs_to :contract
|
@@ -242,10 +241,10 @@ module IB
|
|
242
241
|
|
243
242
|
def order_state= state
|
244
243
|
self.order_states.push case state
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
244
|
+
when IB::OrderState
|
245
|
+
state
|
246
|
+
when Symbol, String
|
247
|
+
IB::OrderState.new :status => state
|
249
248
|
end
|
250
249
|
end
|
251
250
|
|
@@ -306,6 +305,9 @@ module IB
|
|
306
305
|
:algo_strategy => '',
|
307
306
|
:transmit => true,
|
308
307
|
:what_if => false,
|
308
|
+
:leg_prices => [],
|
309
|
+
:algo_params => [],
|
310
|
+
:combo_params => [],
|
309
311
|
:order_state => IB::OrderState.new(:status => 'New',
|
310
312
|
:filled => 0,
|
311
313
|
:remaining => 0,
|
@@ -320,142 +322,6 @@ module IB
|
|
320
322
|
# #self.order_state ||= IB::OrderState.new :status => 'New'
|
321
323
|
#end
|
322
324
|
|
323
|
-
# This returns an Array of data from the given order,
|
324
|
-
# mixed with data from associated contract. Ugly mix, indeed.
|
325
|
-
def serialize_with server, contract
|
326
|
-
[contract.serialize_long(:con_id, :sec_id),
|
327
|
-
# main order fields
|
328
|
-
case side
|
329
|
-
when :short
|
330
|
-
'SSHORT'
|
331
|
-
when :short_exempt
|
332
|
-
'SSHORTX'
|
333
|
-
else
|
334
|
-
side.to_sup
|
335
|
-
end,
|
336
|
-
quantity,
|
337
|
-
self[:order_type], # Internal code, 'LMT' instead of :limit
|
338
|
-
limit_price,
|
339
|
-
aux_price,
|
340
|
-
self[:tif],
|
341
|
-
oca_group,
|
342
|
-
account,
|
343
|
-
open_close.to_sup[0..0],
|
344
|
-
self[:origin],
|
345
|
-
order_ref,
|
346
|
-
transmit,
|
347
|
-
parent_id,
|
348
|
-
block_order || false,
|
349
|
-
sweep_to_fill || false,
|
350
|
-
display_size,
|
351
|
-
self[:trigger_method],
|
352
|
-
outside_rth || false, # was: ignore_rth
|
353
|
-
hidden || false,
|
354
|
-
contract.serialize_legs(:extended),
|
355
|
-
|
356
|
-
# This is specific to PlaceOrder v.38, NOT supported by API yet!
|
357
|
-
#
|
358
|
-
## Support for per-leg prices in Order
|
359
|
-
#if server[:server_version] >= 61 && contract.bag?
|
360
|
-
# leg_prices.empty? ? 0 : [leg_prices.size] + leg_prices
|
361
|
-
#else
|
362
|
-
# []
|
363
|
-
#end,
|
364
|
-
#
|
365
|
-
## Support for combo routing params in Order
|
366
|
-
#if server[:server_version] >= 57 && contract.bag?
|
367
|
-
# p 'Here!'
|
368
|
-
# combo_params.empty? ? 0 : [combo_params.size] + combo_params.to_a
|
369
|
-
#else
|
370
|
-
# []
|
371
|
-
#end,
|
372
|
-
|
373
|
-
'', # deprecated shares_allocation field
|
374
|
-
discretionary_amount,
|
375
|
-
good_after_time,
|
376
|
-
good_till_date,
|
377
|
-
fa_group,
|
378
|
-
fa_method,
|
379
|
-
fa_percentage,
|
380
|
-
fa_profile,
|
381
|
-
self[:short_sale_slot], # 0 only for retail, 1 or 2 for institution (Institutional)
|
382
|
-
designated_location, # only populate when short_sale_slot == 2 (Institutional)
|
383
|
-
exempt_code,
|
384
|
-
self[:oca_type],
|
385
|
-
rule_80a,
|
386
|
-
settling_firm,
|
387
|
-
all_or_none || false,
|
388
|
-
min_quantity,
|
389
|
-
percent_offset,
|
390
|
-
etrade_only || false,
|
391
|
-
firm_quote_only || false,
|
392
|
-
nbbo_price_cap,
|
393
|
-
self[:auction_strategy],
|
394
|
-
starting_price,
|
395
|
-
stock_ref_price,
|
396
|
-
delta,
|
397
|
-
stock_range_lower,
|
398
|
-
stock_range_upper,
|
399
|
-
override_percentage_constraints || false,
|
400
|
-
volatility, # Volatility orders
|
401
|
-
self[:volatility_type], #
|
402
|
-
self[:delta_neutral_order_type],
|
403
|
-
delta_neutral_aux_price, #
|
404
|
-
|
405
|
-
# Support for delta neutral orders with parameters
|
406
|
-
if server[:server_version] >= 58 && delta_neutral_order_type
|
407
|
-
[delta_neutral_con_id,
|
408
|
-
delta_neutral_settling_firm,
|
409
|
-
delta_neutral_clearing_account,
|
410
|
-
self[:delta_neutral_clearing_intent]
|
411
|
-
]
|
412
|
-
else
|
413
|
-
[]
|
414
|
-
end,
|
415
|
-
|
416
|
-
continuous_update, # Volatility orders
|
417
|
-
self[:reference_price_type], # Volatility orders
|
418
|
-
|
419
|
-
trail_stop_price, # TRAIL_STOP_LIMIT stop price
|
420
|
-
|
421
|
-
# Support for trailing percent
|
422
|
-
server[:server_version] >= 62 ? trailing_percent : [],
|
423
|
-
|
424
|
-
scale_init_level_size, # Scale Orders
|
425
|
-
scale_subs_level_size, # Scale Orders
|
426
|
-
scale_price_increment, # Scale Orders
|
427
|
-
|
428
|
-
# Support extended scale orders parameters
|
429
|
-
if server[:server_version] >= 60 &&
|
430
|
-
scale_price_increment && scale_price_increment > 0
|
431
|
-
[scale_price_adjust_value,
|
432
|
-
scale_price_adjust_interval,
|
433
|
-
scale_profit_offset,
|
434
|
-
scale_auto_reset || false,
|
435
|
-
scale_init_position,
|
436
|
-
scale_init_fill_qty,
|
437
|
-
scale_random_percent || false
|
438
|
-
]
|
439
|
-
else
|
440
|
-
[]
|
441
|
-
end,
|
442
|
-
|
443
|
-
# TODO: Need to add support for hedgeType, not working ATM - beta only
|
444
|
-
# if (m_serverVersion >= MIN_SERVER_VER_HEDGE_ORDERS) {
|
445
|
-
# send (order.m_hedgeType);
|
446
|
-
# if (!IsEmpty(order.m_hedgeType)) send (order.m_hedgeParam); }
|
447
|
-
#
|
448
|
-
# if (m_serverVersion >= MIN_SERVER_VER_OPT_OUT_SMART_ROUTING) {
|
449
|
-
# send (order.m_optOutSmartRouting) ; || false }
|
450
|
-
|
451
|
-
clearing_account,
|
452
|
-
clearing_intent,
|
453
|
-
not_held || false,
|
454
|
-
contract.serialize_under_comp,
|
455
|
-
serialize_algo(),
|
456
|
-
what_if]
|
457
|
-
end
|
458
|
-
|
459
325
|
def serialize_algo
|
460
326
|
if algo_strategy.nil? || algo_strategy.empty?
|
461
327
|
''
|
data/spec/README.md
CHANGED
@@ -1,11 +1,45 @@
|
|
1
|
-
|
1
|
+
## RUNNING TESTS:
|
2
2
|
|
3
|
-
|
3
|
+
The gem comes with a spec suit that may be used to test ib-ruby compatibility
|
4
|
+
with your specific TWS/Gateway installation. The test suit should be run ONLY
|
5
|
+
against your IB paper trading account. Running it against live account may result
|
6
|
+
in financial losses.
|
4
7
|
|
5
|
-
|
8
|
+
In order to run tests, you should set up your IB paper trading connection parameters
|
9
|
+
in 'spec/spec_helper' file. Modify account_name, host and port under section
|
10
|
+
'Your IB PAPER ACCOUNT'. Do not change the client_id.
|
6
11
|
|
7
|
-
|
8
|
-
|
12
|
+
Before running tests, you need to start your TWS/Gateway and allow API connection.
|
13
|
+
You should not have any open/pending orders on your IB paper trading account prior
|
14
|
+
to running tests, otherwise some tests will fail. Use 'bin/cancel_orders' script for
|
15
|
+
bulk cancelling of open orders before running tests as needed.
|
16
|
+
|
17
|
+
By default, specs suppress logging output that is normally produced by IB::Connection.
|
18
|
+
This may make it difficult to debug a failing spec. Following option will switch on verbose
|
19
|
+
output (both logger output and content of all received IB messages is dumped). Do not use
|
20
|
+
this mode to run a whole spec - you will be swamped! Use it to debug specific failing specs
|
21
|
+
only:
|
22
|
+
|
23
|
+
$ rspec -rv [spec/specific_spec.rb]
|
24
|
+
|
25
|
+
By default, specs are run without database support (tableless). In order to run them
|
26
|
+
with database backend, use:
|
27
|
+
|
28
|
+
$ rspec -rdb [spec/specific_spec.rb]
|
29
|
+
|
30
|
+
If you run your specs against both Gateway and TWS, you may want to use the following
|
31
|
+
switch to run specs against TWS port (as opposed to default Gateway port):
|
32
|
+
|
33
|
+
$ rspec -rtws [spec/specific_spec.rb]
|
34
|
+
|
35
|
+
# WRITING YOUR OWN INTEGRATION SPECS
|
36
|
+
|
37
|
+
You can easily create your own integration specs. Pattern for writing specs is like this:
|
38
|
+
|
39
|
+
1. You define your user scenario (such as: subscribe to FUTURES market data).
|
40
|
+
|
41
|
+
2. You find out from documentation or experimentally, what messages should be sent to
|
42
|
+
IB to accomplish it, and what messages are sent by IB in return.
|
9
43
|
|
10
44
|
3. You start writing spec, requiring 'integration_helper'. Don't forget to
|
11
45
|
'verify_account'! Running tests against live IB account can be pretty painful.
|
@@ -25,10 +59,10 @@ Pattern for writing integration specs is like this:
|
|
25
59
|
@ib.received Hash, keyed by message type. The Hash has following structure:
|
26
60
|
{:MessageType1 => [msg1, msg2, msg3...], :MessageType2 => [msg1, msg2, msg3...] }.
|
27
61
|
|
28
|
-
7. If you created @ib Connection with mock_logger, all log entries produced by IB
|
62
|
+
7. If you created @ib Connection with a mock_logger, all log entries produced by IB
|
29
63
|
will be also caught and placed into log_entries Array.
|
30
64
|
|
31
|
-
8. Your examples can thus
|
65
|
+
8. Your examples can thus check the content of @ib.received Hash to see what messages
|
32
66
|
were received, or log_entries Array to see what was logged.
|
33
67
|
|
34
68
|
9. When done with this context, you call 'close_connection' helper in a top-level
|
@@ -36,13 +70,14 @@ Pattern for writing integration specs is like this:
|
|
36
70
|
|
37
71
|
10. If you reuse the connection between contexts and requests, it is recommended to
|
38
72
|
call 'clean_connection' in after block to remove old content from @ib.received Hash,
|
39
|
-
or otherwise manually clean
|
73
|
+
and log_entries Array or otherwise manually clean them to remove old/not needed
|
74
|
+
messages from and log entries. If your do not do this, your examples become coupled.
|
40
75
|
|
41
76
|
11. If you want to see exactly what's going on inside ib-ruby while your examples are
|
42
|
-
running,
|
43
|
-
messages received and log entries made as as result of
|
44
|
-
output is very verbose, so don't
|
45
|
-
you
|
77
|
+
running, run your specs with '-rv' option to switch on verbose outpset mode.
|
78
|
+
Now you will see all the messages received and log entries made as as result of
|
79
|
+
your examples running. Be warned, output is very verbose, so don't run big chunk of
|
80
|
+
specs with -rv option or you will be swamped!.
|
46
81
|
|
47
82
|
Help the development!
|
48
83
|
See 'spec/TODO' file for list of scenarios that still need to be tested.
|
data/spec/account_helper.rb
CHANGED
@@ -17,10 +17,19 @@ def verify_account
|
|
17
17
|
|
18
18
|
@ib = IB::Connection.new OPTS[:connection].merge(:logger => mock_logger)
|
19
19
|
|
20
|
-
|
21
|
-
|
20
|
+
received =
|
21
|
+
if @ib.server[:server_version] <= 60
|
22
|
+
@ib.send_message :RequestAccountData, :subscribe => true
|
23
|
+
@ib.wait_for :AccountValue, 5
|
24
|
+
raise "Unable to verify IB PAPER ACCOUNT" unless @ib.received? :AccountValue
|
25
|
+
p @ib.received[:AccountValue].first
|
26
|
+
@ib.received[:AccountValue].first.account_name
|
27
|
+
else
|
28
|
+
@ib.wait_for :ManagedAccounts, 5
|
29
|
+
raise "Unable to verify IB PAPER ACCOUNT" unless @ib.received?(:ManagedAccounts)
|
30
|
+
@ib.received[:ManagedAccounts].first.accounts_list
|
31
|
+
end
|
22
32
|
|
23
|
-
received = @ib.received[:ManagedAccounts].first.accounts_list
|
24
33
|
raise "Connected to wrong account #{received}, expected #{account}" if account != received
|
25
34
|
|
26
35
|
close_connection
|
@@ -4,7 +4,7 @@ shared_examples_for 'OpenOrder message' do
|
|
4
4
|
it { should be_an IB::Messages::Incoming::OpenOrder }
|
5
5
|
its(:message_type) { should == :OpenOrder }
|
6
6
|
its(:message_id) { should == 5 }
|
7
|
-
its(:version) { should ==
|
7
|
+
its(:version) { should == 30}
|
8
8
|
its(:data) { should_not be_empty }
|
9
9
|
its(:local_id) { should be_an Integer }
|
10
10
|
its(:status) { should =~ /Submit/ }
|
@@ -41,7 +41,7 @@ shared_examples_for 'OpenOrder message' do
|
|
41
41
|
|
42
42
|
it 'has class accessors as well' do
|
43
43
|
subject.class.message_id.should == 5
|
44
|
-
subject.class.version.should == [23, 28] #
|
44
|
+
subject.class.version.should == [23, 28, 30] # Message versions supported
|
45
45
|
subject.class.message_type.should == :OpenOrder
|
46
46
|
end
|
47
47
|
|
@@ -51,7 +51,7 @@ describe IB::Messages::Incoming::OpenOrder do
|
|
51
51
|
|
52
52
|
context 'Instantiated with data Hash' do
|
53
53
|
subject do
|
54
|
-
IB::Messages::Incoming::OpenOrder.new :version =>
|
54
|
+
IB::Messages::Incoming::OpenOrder.new :version => 30,
|
55
55
|
:order =>
|
56
56
|
{:local_id => 1313,
|
57
57
|
:perm_id => 172323928,
|
@@ -86,7 +86,8 @@ describe IB::Messages::Incoming::OpenOrder do
|
|
86
86
|
@ib = IB::Connection.new OPTS[:connection].merge(:logger => mock_logger)
|
87
87
|
@ib.wait_for :NextValidId
|
88
88
|
place_order IB::Symbols::Stocks[:wfc]
|
89
|
-
@ib.wait_for :OpenOrder
|
89
|
+
@ib.wait_for :OpenOrder, 3
|
90
|
+
@ib.received?(:OpenOrder).should be_true
|
90
91
|
end
|
91
92
|
|
92
93
|
after(:all) { close_connection } # implicitly cancels order
|
@@ -98,3 +99,13 @@ describe IB::Messages::Incoming::OpenOrder do
|
|
98
99
|
#it 'has extended order_state attributes' do
|
99
100
|
end
|
100
101
|
end # describe IB::Messages:Incoming
|
102
|
+
|
103
|
+
__END__
|
104
|
+
11:55:04:543 <- 3-38-22 -0-USD -BAG--0.0---SMART--USD----BUY-1 -MKT------O-0--1-0-0-0-0-0-0-0-2-101360836-1-SELL-SMART-0-0---1-81032967-1-BUY-SMART-0-0---1-0-0--0.0-------0---1-0---0---0-0--0------0-----0--------0---0-0--0-
|
105
|
+
12:20:02:859 <- 3-38-22 -0-GOOG-BAG--0.0---SMART--USD----BUY-10-LMT-0.01- - ---O-0-Original-1-0-0-0-0-0-0-0-2-101360836-1-SELL-SMART-0-0---1-81032967-1-BUY-SMART-0-0---1-0-0--0.0-------0---1-0---0---0-0--0------0-----0--------0---0-0--0-
|
106
|
+
11:58:07:100 <- 3-38-304-0-GOOG-BAG--0.0---SMART--USD----BUY-10-LMT-0.01-0.0-DAY---O-0-Original-1-0-0-0-0-0-0-0-3-81032967-1-BUY-SMART-0-0---1-81032968-2-SELL-SMART-0-0---1-81032973-1-BUY-SMART-0-0---1-3----0--0.0-------0---1-0---0---0-0--0------0-----0--------0---0-0--0-
|
107
|
+
|
108
|
+
22:34:23:993 <- 3-38-17- 0-WFC-STK--0.0---NYSE--USD----BUY-100-LMT-9.13-0.0-DAY---O-0--1-0-0-0-0-0-0-0--0.0-------0---1-0---0---0-0--0------0-----0--------0---0-0--1-
|
109
|
+
22:34:25:203 <- 3-38-18 -0-WFC-STK--0.0---NYSE--USD----BUY-100-LMT-9.13-0.0-DAY---O-0--1-0-0-0-0-0-0-0--0.0-------0---1-0---0---0-0--0------0-----0--------0---0-0--0-
|
110
|
+
00:11:37:820 <- 3-38-180-0-WFC-STK--0.0---NYSE--USD----BUY-100-LMT-9.13- - ---O-0--1-0-0-0-0-0-0-0--0.0-------0---1-0---0---0-0--0------0-----0--------0---0-0--0-
|
111
|
+
|