ib-ruby 0.7.6 → 0.7.8
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 +8 -0
- data/Rakefile +8 -0
- data/VERSION +1 -1
- data/bin/fundamental_data +6 -9
- data/lib/ib-ruby/connection.rb +16 -19
- data/lib/ib-ruby/constants.rb +3 -1
- data/lib/ib-ruby/extensions.rb +5 -0
- data/lib/ib-ruby/messages/incoming/contract_data.rb +46 -45
- data/lib/ib-ruby/messages/incoming/delta_neutral_validation.rb +8 -5
- data/lib/ib-ruby/messages/incoming/execution_data.rb +2 -2
- data/lib/ib-ruby/messages/incoming/next_valid_id.rb +18 -0
- data/lib/ib-ruby/messages/incoming/open_order.rb +23 -16
- data/lib/ib-ruby/messages/incoming/order_status.rb +5 -3
- data/lib/ib-ruby/messages/incoming/scanner_data.rb +15 -11
- data/lib/ib-ruby/messages/incoming.rb +1 -5
- data/lib/ib-ruby/messages/outgoing/abstract_message.rb +2 -1
- data/lib/ib-ruby/messages/outgoing/place_order.rb +1 -1
- data/lib/ib-ruby/messages/outgoing.rb +1 -1
- data/lib/ib-ruby/models/bag.rb +59 -0
- data/lib/ib-ruby/models/combo_leg.rb +10 -6
- data/lib/ib-ruby/models/contract.rb +278 -0
- data/lib/ib-ruby/models/contract_detail.rb +70 -0
- data/lib/ib-ruby/models/execution.rb +22 -16
- data/lib/ib-ruby/models/model.rb +75 -17
- data/lib/ib-ruby/models/model_properties.rb +40 -26
- data/lib/ib-ruby/models/option.rb +62 -0
- data/lib/ib-ruby/models/order.rb +122 -86
- data/lib/ib-ruby/models/order_state.rb +11 -12
- data/lib/ib-ruby/models/underlying.rb +36 -0
- data/lib/ib-ruby/models.rb +1 -4
- data/spec/account_helper.rb +2 -1
- data/spec/db.rb +1 -1
- data/spec/db_helper.rb +105 -0
- data/spec/ib-ruby/connection_spec.rb +3 -3
- data/spec/ib-ruby/messages/incoming/open_order_spec.rb +5 -5
- data/spec/ib-ruby/messages/incoming/order_status_spec.rb +3 -3
- data/spec/ib-ruby/models/bag_spec.rb +15 -23
- data/spec/ib-ruby/models/bar_spec.rb +0 -5
- data/spec/ib-ruby/models/combo_leg_spec.rb +18 -25
- data/spec/ib-ruby/models/contract_detail_spec.rb +54 -0
- data/spec/ib-ruby/models/contract_spec.rb +25 -37
- data/spec/ib-ruby/models/execution_spec.rb +64 -19
- data/spec/ib-ruby/models/option_spec.rb +12 -34
- data/spec/ib-ruby/models/order_spec.rb +107 -45
- data/spec/ib-ruby/models/order_state_spec.rb +12 -12
- data/spec/ib-ruby/models/underlying_spec.rb +36 -0
- data/spec/integration/contract_info_spec.rb +65 -55
- data/spec/integration/fundamental_data_spec.rb +2 -2
- data/spec/integration/orders/attached_spec.rb +3 -3
- data/spec/integration/orders/combo_spec.rb +3 -3
- data/spec/integration/orders/placement_spec.rb +8 -8
- data/spec/integration/orders/{execution_spec.rb → trades_spec.rb} +8 -12
- data/spec/integration/orders/valid_ids_spec.rb +3 -3
- data/spec/message_helper.rb +1 -1
- data/spec/model_helper.rb +150 -85
- data/spec/order_helper.rb +35 -18
- metadata +18 -10
- data/lib/ib-ruby/models/contracts/bag.rb +0 -62
- data/lib/ib-ruby/models/contracts/contract.rb +0 -320
- data/lib/ib-ruby/models/contracts/option.rb +0 -66
- data/lib/ib-ruby/models/contracts.rb +0 -27
@@ -3,15 +3,15 @@ require 'model_helper'
|
|
3
3
|
describe IB::Models::Order do
|
4
4
|
|
5
5
|
let(:props) do
|
6
|
-
{:
|
6
|
+
{:local_id => 23,
|
7
7
|
:order_ref => 'Test',
|
8
8
|
:client_id => 1111,
|
9
9
|
:perm_id => 173276893,
|
10
10
|
:parent_id => 0,
|
11
11
|
:side => :buy,
|
12
12
|
:order_type => :market_if_touched,
|
13
|
-
:limit_price => 0.
|
14
|
-
:
|
13
|
+
:limit_price => 0.1,
|
14
|
+
:quantity => 100,
|
15
15
|
:tif => :good_till_cancelled,
|
16
16
|
:open_close => :close,
|
17
17
|
:oca_group => '',
|
@@ -20,8 +20,6 @@ describe IB::Models::Order do
|
|
20
20
|
:designated_location => "WHATEVER",
|
21
21
|
:exempt_code => 123,
|
22
22
|
:delta_neutral_order_type => :market,
|
23
|
-
#:commission_currency => "USD",
|
24
|
-
#:status => 'PreSubmitted',
|
25
23
|
:transmit => false,
|
26
24
|
:outside_rth => true,
|
27
25
|
:what_if => true,
|
@@ -30,64 +28,128 @@ describe IB::Models::Order do
|
|
30
28
|
|
31
29
|
# TODO: :presents => { Object => "Formatted"}
|
32
30
|
let(:human) do
|
33
|
-
"<Order: Test MIT GTC buy 100 New 0.
|
34
|
-
end
|
35
|
-
|
36
|
-
let(:defaults) do
|
37
|
-
{:outside_rth => false,
|
38
|
-
:open_close => :open,
|
39
|
-
:short_sale_slot => :default,
|
40
|
-
:tif => :day,
|
41
|
-
:order_type => :limit,
|
42
|
-
:origin => :customer,
|
43
|
-
:transmit => true,
|
44
|
-
:designated_location => '',
|
45
|
-
:exempt_code => -1,
|
46
|
-
:what_if => false,
|
47
|
-
:not_held => false,
|
48
|
-
:status => 'New',
|
49
|
-
:created_at => Time,
|
50
|
-
}
|
31
|
+
"<Order: Test MIT GTC buy 100 New 0.1 #23/173276893 from 1111>"
|
51
32
|
end
|
52
33
|
|
53
34
|
let(:errors) do
|
54
|
-
{:side =>["should be buy/sell/short"]
|
55
|
-
:order_id => ["is not a number"], }
|
35
|
+
{:side =>["should be buy/sell/short"]}
|
56
36
|
end
|
57
37
|
|
58
38
|
let(:assigns) do
|
59
39
|
{[:order_type, :delta_neutral_order_type] => codes_and_values_for(:order_type),
|
40
|
+
|
60
41
|
:open_close =>
|
61
|
-
{[
|
42
|
+
{[42, nil, 'Foo', :bar] => /should be same.open.close.unknown/,
|
43
|
+
['SAME', 'same', 'S', 's', :same, 0, '0'] => :same,
|
62
44
|
['OPEN', 'open', 'O', 'o', :open, 1, '1'] => :open,
|
63
45
|
['CLOSE', 'close', 'C', 'c', :close, 2, '2'] => :close,
|
64
46
|
['UNKNOWN', 'unknown', 'U', 'u', :unknown, 3, '3'] => :unknown,
|
65
|
-
|
66
|
-
|
67
|
-
:
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
47
|
+
},
|
48
|
+
|
49
|
+
[:what_if, :not_held, :outside_rth, :hidden, :transmit, :block_order,
|
50
|
+
:sweep_to_fill, :override_percentage_constraints, :all_or_none,
|
51
|
+
:etrade_only, :firm_quote_only, :opt_out_smart_routing, :scale_auto_reset,
|
52
|
+
:scale_random_percent] => boolean_assigns,
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
let(:aliases) do
|
57
|
+
{[:side, :action] => buy_sell_short_assigns,
|
58
|
+
[:local_id, :order_id] => numeric_or_nil_assigns,
|
59
|
+
[:quantity, :total_quantity] => numeric_or_nil_assigns,
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
let(:associations) do
|
64
|
+
{:order_states => [IB::OrderState.new(:status => :Foo),
|
65
|
+
IB::OrderState.new(:status => 'Bar'),],
|
66
|
+
|
67
|
+
:executions => [IB::Execution.new(:local_id => 23,
|
68
|
+
:client_id => 1111,
|
69
|
+
:perm_id => 173276893,
|
70
|
+
:exchange => "IDEALPRO",
|
71
|
+
:exec_id => "0001f4e8.4f5d48f1.01.01",
|
72
|
+
:price => 0.1,
|
73
|
+
:average_price => 0.1,
|
74
|
+
:shares => 40,
|
75
|
+
:cumulative_quantity => 40,
|
76
|
+
:side => :buy,
|
77
|
+
:time => "20120312 15:41:09"),
|
78
|
+
IB::Execution.new(:local_id => 23,
|
79
|
+
:client_id => 1111,
|
80
|
+
:perm_id => 173276893,
|
81
|
+
:exchange => "IDEALPRO",
|
82
|
+
:exec_id => "0001f4e8.4f5d48f1.01.02",
|
83
|
+
:price => 0.1,
|
84
|
+
:average_price => 0.1,
|
85
|
+
:shares => 60,
|
86
|
+
:cumulative_quantity => 100,
|
87
|
+
:side => :buy,
|
88
|
+
:time => "20120312 15:41:10")]
|
78
89
|
}
|
79
90
|
end
|
80
91
|
|
81
92
|
it_behaves_like 'Model'
|
82
93
|
it_behaves_like 'Self-equal Model'
|
83
94
|
|
95
|
+
context 'Order associations' do
|
96
|
+
after(:all) { DatabaseCleaner.clean }
|
97
|
+
|
98
|
+
subject { IB::Order.new props }
|
99
|
+
|
100
|
+
it 'has order_states collection' do
|
101
|
+
subject.order_states.should_not be_nil
|
102
|
+
subject.order_states.should be_an Array # lies, it's more like association proxy
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'has at least one (initial, New) OrderState' do
|
106
|
+
subject.order_states.should have_exactly(1).state
|
107
|
+
last_state = subject.order_states.last
|
108
|
+
last_state.should be_an IB::OrderState
|
109
|
+
last_state.status.should == 'New'
|
110
|
+
subject.save
|
111
|
+
last_state.order.should == subject if IB::DB
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'has abbreviated accessor to last (current) OrderState' do
|
115
|
+
subject.order_state.should == subject.order_states.last
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'has extra accessors to OrderState properties' do
|
119
|
+
subject.order_state.should_not be_nil
|
120
|
+
subject.status.should == 'New'
|
121
|
+
end
|
122
|
+
|
123
|
+
context 'update Order state by ' do
|
124
|
+
|
125
|
+
it 'either adding new State to order_states ' do
|
126
|
+
subject.order_states << IB::OrderState.new(:status => :Foo)
|
127
|
+
subject.order_states.push IB::OrderState.new :status => :Bar
|
128
|
+
|
129
|
+
subject.status.should == 'Bar'
|
130
|
+
subject.save
|
131
|
+
subject.order_states.should have_exactly(3).states
|
132
|
+
subject.order_states.first.order.should == subject if IB::DB
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'or simply assigning to order_state accessor' do
|
136
|
+
subject.order_state = :Foo
|
137
|
+
subject.order_state = IB::OrderState.new :status => :Bar
|
138
|
+
|
139
|
+
subject.status.should == 'Bar'
|
140
|
+
subject.order_states.should have_exactly(3).states
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
84
146
|
context 'equality' do
|
85
147
|
subject { IB::Order.new props }
|
86
148
|
|
87
149
|
it_behaves_like 'Self-equal Model'
|
88
150
|
|
89
151
|
it 'is not equal for Orders with different limit price' do
|
90
|
-
order1 = IB::Order.new :
|
152
|
+
order1 = IB::Order.new :quantity => 100,
|
91
153
|
:limit_price => 1,
|
92
154
|
:action => 'BUY'
|
93
155
|
|
@@ -99,7 +161,7 @@ describe IB::Models::Order do
|
|
99
161
|
end
|
100
162
|
|
101
163
|
it 'is not equal for Orders with different total_quantity' do
|
102
|
-
order1 = IB::Order.new :
|
164
|
+
order1 = IB::Order.new :quantity => 20000,
|
103
165
|
:limit_price => 1,
|
104
166
|
:action => 'BUY'
|
105
167
|
|
@@ -111,11 +173,11 @@ describe IB::Models::Order do
|
|
111
173
|
end
|
112
174
|
|
113
175
|
it 'is not equal for Orders with different action/side' do
|
114
|
-
order1 = IB::Order.new :
|
176
|
+
order1 = IB::Order.new :quantity => 100,
|
115
177
|
:limit_price => 1,
|
116
178
|
:action => 'SELL'
|
117
179
|
|
118
|
-
order2 = IB::Order.new :
|
180
|
+
order2 = IB::Order.new :quantity => 100,
|
119
181
|
:action => 'BUY',
|
120
182
|
:limit_price => 1
|
121
183
|
order1.should_not == order2
|
@@ -123,12 +185,12 @@ describe IB::Models::Order do
|
|
123
185
|
end
|
124
186
|
|
125
187
|
it 'is not equal for Orders with different order_type' do
|
126
|
-
order1 = IB::Order.new :
|
188
|
+
order1 = IB::Order.new :quantity => 100,
|
127
189
|
:limit_price => 1,
|
128
190
|
:action => 'BUY',
|
129
191
|
:order_type => 'LMT'
|
130
192
|
|
131
|
-
order2 = IB::Order.new :
|
193
|
+
order2 = IB::Order.new :quantity => 100,
|
132
194
|
:action => 'BUY',
|
133
195
|
:limit_price => 1,
|
134
196
|
:order_type => 'MKT'
|
@@ -3,7 +3,7 @@ require 'model_helper'
|
|
3
3
|
describe IB::Models::OrderState do
|
4
4
|
|
5
5
|
let(:props) do
|
6
|
-
{:
|
6
|
+
{:local_id => 23,
|
7
7
|
:perm_id => 173276893,
|
8
8
|
:client_id => 1111,
|
9
9
|
:parent_id => 0,
|
@@ -30,22 +30,22 @@ describe IB::Models::OrderState do
|
|
30
30
|
"<OrderState: PreSubmitted #23/173276893 from 1111 filled 3/2 at 0.5/0.55 margin 500.0/500.0 equity 750.0 fee 1.2 why_held child warning Oh noes!>"
|
31
31
|
end
|
32
32
|
|
33
|
-
let(:
|
34
|
-
{:
|
33
|
+
let(:errors) do
|
34
|
+
{:status => ["must not be empty"],
|
35
35
|
}
|
36
36
|
end
|
37
37
|
|
38
|
-
let(:
|
39
|
-
{:
|
40
|
-
|
41
|
-
|
38
|
+
let(:assigns) do
|
39
|
+
{[:status] =>
|
40
|
+
{[nil, ''] => /must not be empty/,
|
41
|
+
['Zorro', :Zorro] => 'Zorro' }
|
42
|
+
}
|
42
43
|
end
|
43
44
|
|
44
|
-
let(:
|
45
|
-
{
|
46
|
-
|
47
|
-
|
48
|
-
[5.0, 2006.17] => /must be an integer/, }
|
45
|
+
let(:aliases) do
|
46
|
+
{[:local_id, :order_id] => numeric_or_nil_assigns,
|
47
|
+
[:price, :last_fill_price] => float_or_nil_assigns,
|
48
|
+
[:average_price, :average_fill_price] => float_or_nil_assigns,
|
49
49
|
}
|
50
50
|
end
|
51
51
|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'model_helper'
|
2
|
+
|
3
|
+
describe IB::Models::Underlying do # AKA IB::Underlying
|
4
|
+
|
5
|
+
let(:props) do
|
6
|
+
{:con_id => 234567,
|
7
|
+
:delta => 0.55,
|
8
|
+
:price => 20.5,
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:human) do
|
13
|
+
/<Underlying: con_id: 234567 .*delta: 0.55 price: 20.5.*>/
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:errors) do
|
17
|
+
{:delta => ['is not a number'],
|
18
|
+
:price => ['is not a number'],
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
let(:assigns) do
|
23
|
+
{[:con_id, :delta, :price] => numeric_assigns,
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
it_behaves_like 'Model'
|
28
|
+
it_behaves_like 'Self-equal Model'
|
29
|
+
|
30
|
+
context 'using shortest class name without properties' do
|
31
|
+
subject { IB::Underlying.new }
|
32
|
+
it_behaves_like 'Model instantiated empty'
|
33
|
+
it_behaves_like 'Self-equal Model'
|
34
|
+
end
|
35
|
+
|
36
|
+
end # describe IB::Contract
|
@@ -16,6 +16,8 @@ describe "Request Contract Info", :connected => true, :integration => true do
|
|
16
16
|
@contract = IB::Contract.new :symbol => 'AAPL', :sec_type => :stock
|
17
17
|
@ib.send_message :RequestContractData, :id => 111, :contract => @contract
|
18
18
|
@ib.wait_for :ContractDataEnd, 3 # sec
|
19
|
+
# java: 15:33:16:159 <- 9-6-111-0-AAPL-STK--0.0--- ---0-- -
|
20
|
+
# ruby: 15:36:15:736 <- 9-6-111-0-AAPL-STK--0.0---SMART--- --0-
|
19
21
|
end
|
20
22
|
|
21
23
|
after(:all) { clean_connection } # Clear logs and message collector
|
@@ -34,24 +36,26 @@ describe "Request Contract Info", :connected => true, :integration => true do
|
|
34
36
|
|
35
37
|
@ib.received[:ContractData].each do |msg|
|
36
38
|
contract = msg.contract
|
37
|
-
|
39
|
+
detail = msg.contract_detail
|
38
40
|
|
41
|
+
contract.symbol.should == 'AAPL'
|
39
42
|
contract.local_symbol.should =~ /AAPL|APC/
|
40
|
-
contract.market_name.should =~ /NMS|USSTARS/
|
41
|
-
contract.trading_class.should =~ /NMS|USSTARS/
|
42
|
-
contract.long_name.should == 'APPLE INC'
|
43
|
-
contract.industry.should == 'Technology'
|
44
|
-
contract.category.should == 'Computers'
|
45
|
-
contract.subcategory.should == 'Computers'
|
46
|
-
contract.exchange.should == 'SMART'
|
47
43
|
contract.con_id.should be_an Integer
|
48
|
-
contract.trading_hours.should =~ /\d{8}:\d{4}-\d{4}/
|
49
|
-
contract.liquid_hours.should =~ /\d{8}:\d{4}-\d{4}/
|
50
|
-
contract.valid_exchanges.should =~ /ISLAND|IBIS/
|
51
|
-
contract.order_types.should be_a String
|
52
|
-
contract.price_magnifier.should == 1
|
53
|
-
contract.min_tick.should be <= 0.01
|
54
44
|
contract.expiry.should == ''
|
45
|
+
contract.exchange.should == 'SMART'
|
46
|
+
|
47
|
+
detail.market_name.should =~ /NMS|USSTARS/
|
48
|
+
detail.trading_class.should =~ /NMS|USSTARS/
|
49
|
+
detail.long_name.should == 'APPLE INC'
|
50
|
+
detail.industry.should == 'Technology'
|
51
|
+
detail.category.should == 'Computers'
|
52
|
+
detail.subcategory.should == 'Computers'
|
53
|
+
detail.trading_hours.should =~ /\d{8}:\d{4}-\d{4}/
|
54
|
+
detail.liquid_hours.should =~ /\d{8}:\d{4}-\d{4}/
|
55
|
+
detail.valid_exchanges.should =~ /ISLAND|IBIS/
|
56
|
+
detail.order_types.should be_a String
|
57
|
+
detail.price_magnifier.should == 1
|
58
|
+
detail.min_tick.should be <= 0.01
|
55
59
|
end
|
56
60
|
end
|
57
61
|
end # Stock
|
@@ -60,9 +64,9 @@ describe "Request Contract Info", :connected => true, :integration => true do
|
|
60
64
|
|
61
65
|
before(:all) do
|
62
66
|
@contract = IB::Option.new :symbol => "AAPL", :expiry => "201301",
|
63
|
-
:right =>
|
67
|
+
:right => :call, :strike => 500
|
64
68
|
@ib.send_message :RequestContractData, :id => 123, :contract => @contract
|
65
|
-
@ib.wait_for :ContractDataEnd,
|
69
|
+
@ib.wait_for :ContractDataEnd, 5 # sec
|
66
70
|
end
|
67
71
|
|
68
72
|
after(:all) { clean_connection } # Clear logs and message collector
|
@@ -79,24 +83,26 @@ describe "Request Contract Info", :connected => true, :integration => true do
|
|
79
83
|
|
80
84
|
it 'receives Contract Data with extended fields' do
|
81
85
|
contract = subject.contract
|
82
|
-
|
86
|
+
detail = subject.contract_detail
|
83
87
|
|
88
|
+
contract.symbol.should == 'AAPL'
|
84
89
|
contract.local_symbol.should == 'AAPL 130119C00500000'
|
85
|
-
contract.market_name.should == 'AAPL'
|
86
|
-
contract.trading_class.should == 'AAPL'
|
87
|
-
contract.long_name.should == 'APPLE INC'
|
88
|
-
contract.industry.should == 'Technology'
|
89
|
-
contract.category.should == 'Computers'
|
90
|
-
contract.subcategory.should == 'Computers'
|
91
90
|
contract.expiry.should == '20130118'
|
92
91
|
contract.exchange.should == 'SMART'
|
93
92
|
contract.con_id.should be_an Integer
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
93
|
+
|
94
|
+
detail.market_name.should == 'AAPL'
|
95
|
+
detail.trading_class.should == 'AAPL'
|
96
|
+
detail.long_name.should == 'APPLE INC'
|
97
|
+
detail.industry.should == 'Technology'
|
98
|
+
detail.category.should == 'Computers'
|
99
|
+
detail.subcategory.should == 'Computers'
|
100
|
+
detail.trading_hours.should =~ /\d{8}:\d{4}-\d{4}/
|
101
|
+
detail.liquid_hours.should =~ /\d{8}:\d{4}-\d{4}/
|
102
|
+
detail.valid_exchanges.should =~ /CBOE/
|
103
|
+
detail.order_types.should be_a String
|
104
|
+
detail.price_magnifier.should == 1
|
105
|
+
detail.min_tick.should == 0.01
|
100
106
|
end
|
101
107
|
end # Request Option data
|
102
108
|
|
@@ -125,24 +131,26 @@ describe "Request Contract Info", :connected => true, :integration => true do
|
|
125
131
|
|
126
132
|
it 'receives Contract Data with extended fields' do
|
127
133
|
contract = subject.contract
|
128
|
-
|
134
|
+
detail = subject.contract_detail
|
129
135
|
|
136
|
+
contract.symbol.should == 'EUR'
|
130
137
|
contract.local_symbol.should == 'EUR.USD'
|
131
|
-
contract.market_name.should == 'EUR.USD'
|
132
|
-
contract.trading_class.should == 'EUR.USD'
|
133
|
-
contract.long_name.should == 'European Monetary Union euro'
|
134
|
-
contract.industry.should == ''
|
135
|
-
contract.category.should == ''
|
136
|
-
contract.subcategory.should == ''
|
137
138
|
contract.expiry.should == ''
|
138
139
|
contract.exchange.should == 'IDEALPRO'
|
139
140
|
contract.con_id.should be_an Integer
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
141
|
+
|
142
|
+
detail.market_name.should == 'EUR.USD'
|
143
|
+
detail.trading_class.should == 'EUR.USD'
|
144
|
+
detail.long_name.should == 'European Monetary Union euro'
|
145
|
+
detail.industry.should == ''
|
146
|
+
detail.category.should == ''
|
147
|
+
detail.subcategory.should == ''
|
148
|
+
detail.trading_hours.should =~ /\d{8}:\d{4}-\d{4}/
|
149
|
+
detail.liquid_hours.should =~ /\d{8}:\d{4}-\d{4}/
|
150
|
+
detail.valid_exchanges.should =~ /IDEALPRO/
|
151
|
+
detail.order_types.should be_a String
|
152
|
+
detail.price_magnifier.should == 1
|
153
|
+
detail.min_tick.should be <= 0.0001
|
146
154
|
end
|
147
155
|
end # Request Forex data
|
148
156
|
|
@@ -168,24 +176,26 @@ describe "Request Contract Info", :connected => true, :integration => true do
|
|
168
176
|
|
169
177
|
it 'receives Contract Data with extended fields' do
|
170
178
|
contract = subject.contract
|
171
|
-
|
179
|
+
detail = subject.contract_detail
|
172
180
|
|
181
|
+
contract.symbol.should == 'YM'
|
173
182
|
contract.local_symbol.should =~ /YM/
|
174
|
-
contract.market_name.should == 'YM'
|
175
|
-
contract.trading_class.should == 'YM'
|
176
|
-
contract.long_name.should == 'Mini Sized Dow Jones Industrial Average $5'
|
177
|
-
contract.industry.should == ''
|
178
|
-
contract.category.should == ''
|
179
|
-
contract.subcategory.should == ''
|
180
183
|
contract.expiry.should =~ Regexp.new(IB::Symbols.next_expiry)
|
181
184
|
contract.exchange.should == 'ECBOT'
|
182
185
|
contract.con_id.should be_an Integer
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
186
|
+
|
187
|
+
detail.market_name.should == 'YM'
|
188
|
+
detail.trading_class.should == 'YM'
|
189
|
+
detail.long_name.should == 'Mini Sized Dow Jones Industrial Average $5'
|
190
|
+
detail.industry.should == ''
|
191
|
+
detail.category.should == ''
|
192
|
+
detail.subcategory.should == ''
|
193
|
+
detail.trading_hours.should =~ /\d{8}:\d{4}-\d{4}/
|
194
|
+
detail.liquid_hours.should =~ /\d{8}:\d{4}-\d{4}/
|
195
|
+
detail.valid_exchanges.should =~ /ECBOT/
|
196
|
+
detail.order_types.should be_a String
|
197
|
+
detail.price_magnifier.should == 1
|
198
|
+
detail.min_tick.should == 1
|
189
199
|
end
|
190
200
|
end # Request Forex data
|
191
201
|
end # Contract Data
|
@@ -17,7 +17,7 @@ describe 'Request Fundamental Data',
|
|
17
17
|
:contract => @contract,
|
18
18
|
:report_type => 'snapshot' # 'estimates', 'finstat'
|
19
19
|
|
20
|
-
@ib.wait_for :FundamentalData,
|
20
|
+
@ib.wait_for :FundamentalData, 10 # sec
|
21
21
|
end
|
22
22
|
|
23
23
|
after(:all) do
|
@@ -32,7 +32,7 @@ describe 'Request Fundamental Data',
|
|
32
32
|
its(:request_id) { should == 456 }
|
33
33
|
its(:data) { should be_a String }
|
34
34
|
|
35
|
-
it 'responds with XML with
|
35
|
+
it 'responds with XML with relevant data' do
|
36
36
|
require 'xmlsimple'
|
37
37
|
data_xml = XmlSimple.xml_in(subject.data, 'ForceArray' => false) #, 'ContentKey' => 'content')
|
38
38
|
name = data_xml["CoIDs"]["CoID"].find {|tag| tag['Type'] == 'CompanyName'}['content']
|
@@ -61,10 +61,10 @@ describe 'Attached Orders', :connected => true, :integration => true do
|
|
61
61
|
:side => :sell,
|
62
62
|
:tif => tif,
|
63
63
|
:order_type => attach_type,
|
64
|
-
:parent_id => @
|
64
|
+
:parent_id => @local_id_placed
|
65
65
|
|
66
|
-
@
|
67
|
-
@
|
66
|
+
@local_id_attached = @ib.place_order @attached_order, @contract
|
67
|
+
@local_id_after = @ib.next_local_id
|
68
68
|
@ib.wait_for [:OpenOrder, 3], [:OrderStatus, 3], 4
|
69
69
|
end
|
70
70
|
|
@@ -25,9 +25,9 @@ describe "Combo Order", :connected => true, :integration => true, :slow => true
|
|
25
25
|
|
26
26
|
after(:all) { close_connection }
|
27
27
|
|
28
|
-
it 'changes client`s
|
29
|
-
@
|
30
|
-
@ib.
|
28
|
+
it 'changes client`s next_local_id' do
|
29
|
+
@local_id_placed.should == @local_id_before
|
30
|
+
@ib.next_local_id.should == @local_id_before + 1
|
31
31
|
end
|
32
32
|
|
33
33
|
it { @ib.received[:OpenOrder].should have_at_least(1).open_order_message }
|
@@ -23,9 +23,9 @@ describe 'Orders', :connected => true, :integration => true do
|
|
23
23
|
@ib.received[:OrderStatus].should be_empty
|
24
24
|
end
|
25
25
|
|
26
|
-
it 'still changes client`s
|
27
|
-
@
|
28
|
-
@ib.
|
26
|
+
it 'still changes client`s next_local_id' do
|
27
|
+
@local_id_placed.should == @local_id_before
|
28
|
+
@ib.next_local_id.should == @local_id_before + 1
|
29
29
|
end
|
30
30
|
|
31
31
|
context 'received :Alert message' do
|
@@ -52,9 +52,9 @@ describe 'Orders', :connected => true, :integration => true do
|
|
52
52
|
|
53
53
|
after(:all) { close_connection }
|
54
54
|
|
55
|
-
it 'changes client`s
|
56
|
-
@
|
57
|
-
@ib.
|
55
|
+
it 'changes client`s next_local_id' do
|
56
|
+
@local_id_placed.should == @local_id_before
|
57
|
+
@ib.next_local_id.should == @local_id_before + 1
|
58
58
|
end
|
59
59
|
|
60
60
|
it { @ib.received[:OpenOrder].should have_at_least(1).open_order_message }
|
@@ -103,8 +103,8 @@ describe 'Orders', :connected => true, :integration => true do
|
|
103
103
|
|
104
104
|
it { @ib.received[:Alert].should have_exactly(1).alert_message }
|
105
105
|
|
106
|
-
it 'does not increase client`s
|
107
|
-
@ib.
|
106
|
+
it 'does not increase client`s next_local_id further' do
|
107
|
+
@ib.next_local_id.should == @local_id_after
|
108
108
|
end
|
109
109
|
|
110
110
|
it 'does not receive Order messages' do
|
@@ -21,10 +21,6 @@ describe "Trades", :connected => true, :integration => true, :slow => true do
|
|
21
21
|
:total_quantity => 20000,
|
22
22
|
:limit_price => 2,
|
23
23
|
:action => 'BUY'
|
24
|
-
#:all_or_none => 1,
|
25
|
-
#:fa_profile => 2,
|
26
|
-
#:percent_offset => 3,
|
27
|
-
#:clearing_account => 'z',
|
28
24
|
#:what_if => true
|
29
25
|
|
30
26
|
@ib.wait_for(5, :ExecutionData, :OpenOrder) do
|
@@ -35,12 +31,12 @@ describe "Trades", :connected => true, :integration => true, :slow => true do
|
|
35
31
|
|
36
32
|
after(:all) do
|
37
33
|
clean_connection # Clear logs and message collector
|
38
|
-
@ib.cancel_order @
|
34
|
+
@ib.cancel_order @local_id_placed # Just in case...
|
39
35
|
end
|
40
36
|
|
41
|
-
it 'changes client`s
|
42
|
-
@
|
43
|
-
@ib.
|
37
|
+
it 'changes client`s next_local_id' do
|
38
|
+
@local_id_placed = @local_id_before
|
39
|
+
@ib.next_local_id.should == @local_id_before + 1
|
44
40
|
end
|
45
41
|
|
46
42
|
it { @ib.received[:OpenOrder].should have_at_least(1).open_order_message }
|
@@ -78,12 +74,12 @@ describe "Trades", :connected => true, :integration => true, :slow => true do
|
|
78
74
|
|
79
75
|
after(:all) do
|
80
76
|
clean_connection # Clear logs and message collector
|
81
|
-
@ib.cancel_order @
|
77
|
+
@ib.cancel_order @local_id_placed # Just in case...
|
82
78
|
end
|
83
79
|
|
84
|
-
it 'changes client`s
|
85
|
-
@
|
86
|
-
@ib.
|
80
|
+
it 'changes client`s next_local_id' do
|
81
|
+
@local_id_placed = @local_id_before
|
82
|
+
@ib.next_local_id.should == @local_id_before + 1
|
87
83
|
end
|
88
84
|
|
89
85
|
it { @ib.received[:OpenOrder].should have_at_least(1).open_order_message }
|
@@ -9,8 +9,8 @@ shared_examples_for 'Received single id' do
|
|
9
9
|
|
10
10
|
it 'receives next valid for Order placement' do
|
11
11
|
subject.should be_an IB::Messages::Incoming::NextValidId
|
12
|
-
subject.
|
13
|
-
@id[:at_connect] ||= subject.
|
12
|
+
subject.local_id.should be_an Integer
|
13
|
+
@id[:at_connect] ||= subject.local_id # just assign once
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'logs next valid order id' do
|
@@ -24,7 +24,7 @@ shared_examples_for 'Received single id after request' do
|
|
24
24
|
it_behaves_like 'Received single id'
|
25
25
|
|
26
26
|
it 'no new id is generated by this request' do
|
27
|
-
subject.
|
27
|
+
subject.local_id.should == @id[:at_connect]
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'does not receive :OpenOrderEnd message' do
|
data/spec/message_helper.rb
CHANGED