ib-ruby 0.5.21 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/HISTORY +8 -0
  2. data/README.md +46 -27
  3. data/TODO +13 -2
  4. data/VERSION +1 -1
  5. data/bin/generic_data.rb +26 -0
  6. data/bin/place_order +1 -1
  7. data/lib/ib-ruby/connection.rb +126 -65
  8. data/lib/ib-ruby/messages/incoming.rb +3 -3
  9. data/lib/ib-ruby/models/bar.rb +11 -11
  10. data/lib/ib-ruby/models/combo_leg.rb +23 -29
  11. data/lib/ib-ruby/models/contract/bag.rb +34 -2
  12. data/lib/ib-ruby/models/contract/option.rb +2 -2
  13. data/lib/ib-ruby/models/contract.rb +151 -197
  14. data/lib/ib-ruby/models/execution.rb +27 -45
  15. data/lib/ib-ruby/models/model.rb +10 -4
  16. data/lib/ib-ruby/models/model_properties.rb +63 -0
  17. data/lib/ib-ruby/models/order.rb +274 -320
  18. data/lib/ib-ruby/symbols/stocks.rb +11 -5
  19. data/spec/account_helper.rb +80 -0
  20. data/spec/ib-ruby/connection_spec.rb +195 -52
  21. data/spec/ib-ruby/messages/incoming_spec.rb +4 -4
  22. data/spec/ib-ruby/models/combo_leg_spec.rb +1 -0
  23. data/spec/ib-ruby/models/contract_spec.rb +1 -1
  24. data/spec/ib-ruby/models/execution_spec.rb +73 -0
  25. data/spec/integration/account_info_spec.rb +12 -59
  26. data/spec/integration/contract_info_spec.rb +23 -37
  27. data/spec/integration/depth_data_spec.rb +4 -4
  28. data/spec/integration/historic_data_spec.rb +15 -27
  29. data/spec/integration/market_data_spec.rb +74 -61
  30. data/spec/integration/option_data_spec.rb +5 -48
  31. data/spec/integration/orders/execution_spec.rb +26 -31
  32. data/spec/integration/orders/open_order +2 -0
  33. data/spec/integration/orders/placement_spec.rb +28 -28
  34. data/spec/integration/orders/valid_ids_spec.rb +11 -11
  35. data/spec/integration_helper.rb +46 -32
  36. data/spec/message_helper.rb +4 -38
  37. data/spec/spec_helper.rb +2 -3
  38. metadata +9 -2
@@ -13,11 +13,17 @@ module IB
13
13
  :currency => "USD",
14
14
  :sec_type => SECURITY_TYPES[:stock],
15
15
  :description => "Wells Fargo"),
16
- :wrong => Models::Contract.new(:symbol => "QEEUUE",
17
- :exchange => "NYSE",
18
- :currency => "USD",
19
- :sec_type => SECURITY_TYPES[:stock],
20
- :description => "Non-existent stock"),
16
+
17
+ :aapl => Models::Contract.new(:symbol => "AAPL",
18
+ :currency => "USD",
19
+ :sec_type => SECURITY_TYPES[:stock],
20
+ :description => "Apple Inc."),
21
+
22
+ :wrong => Models::Contract.new(:symbol => "QEEUUE",
23
+ :exchange => "NYSE",
24
+ :currency => "USD",
25
+ :sec_type => SECURITY_TYPES[:stock],
26
+ :description => "Non-existent stock"),
21
27
  }
22
28
  end
23
29
  end
@@ -0,0 +1,80 @@
1
+ # Make sure integration tests are only run against the pre-configured PAPER ACCOUNT
2
+ def verify_account
3
+ return OPTS[:account_verified] if OPTS[:account_verified]
4
+
5
+ puts
6
+ puts 'WARNING: MAKE SURE TO RUN INTEGRATION TESTS AGAINST IB PAPER ACCOUNT ONLY!'
7
+ puts 'WARNING: FINANCIAL LOSSES MAY RESULT IF YOU RUN TESTS WITH REAL IB ACCOUNT!'
8
+ puts 'WARNING: YOU HAVE BEEN WARNED!'
9
+ puts
10
+ puts 'Configure your connection to IB PAPER ACCOUNT in spec/spec_helper.rb'
11
+ puts
12
+
13
+ account = OPTS[:connection][:account] || OPTS[:connection][:account_name]
14
+ raise "Please configure IB PAPER ACCOUNT in spec/spec_helper.rb" unless account
15
+
16
+ @ib = IB::Connection.new OPTS[:connection].merge(:logger => mock_logger)
17
+ @ib.send_message :RequestAccountData, :subscribe => true
18
+
19
+ @ib.wait_for 3, :AccountValue
20
+ raise "Unable to verify IB PAPER ACCOUNT" unless @ib.received?(:AccountValue)
21
+
22
+ received = @ib.received[:AccountValue].first.account_name
23
+ raise "Connected to wrong account #{received}, expected #{account}" if account != received
24
+
25
+ close_connection
26
+ OPTS[:account_verified] = true
27
+ end
28
+
29
+ ### Helpers for placing and verifying orders
30
+
31
+ shared_examples_for 'Valid account data request' do
32
+
33
+ context "received :AccountUpdateTime message" do
34
+ subject { @ib.received[:AccountUpdateTime].first }
35
+
36
+ it { should be_an IB::Messages::Incoming::AccountUpdateTime }
37
+ its(:data) { should be_a Hash }
38
+ its(:time_stamp) { should =~ /\d\d:\d\d/ }
39
+ its(:to_human) { should =~ /AccountUpdateTime/ }
40
+ end
41
+
42
+ context "received :AccountValue message" do
43
+ subject { @ib.received[:AccountValue].first }
44
+
45
+ #ps
46
+ it { should be_an IB::Messages::Incoming::AccountValue }
47
+ its(:data) { should be_a Hash }
48
+ its(:account_name) { should =~ /\w\d/ }
49
+ its(:key) { should be_a String }
50
+ its(:value) { should be_a String }
51
+ its(:currency) { should be_a String }
52
+ its(:to_human) { should =~ /AccountValue/ }
53
+ end
54
+
55
+ context "received :PortfolioValue message" do
56
+ subject { @ib.received[:PortfolioValue].first }
57
+
58
+ it { should be_an IB::Messages::Incoming::PortfolioValue }
59
+ its(:contract) { should be_a IB::Models::Contract }
60
+ its(:data) { should be_a Hash }
61
+ its(:position) { should be_a Integer }
62
+ its(:market_price) { should be_a Float }
63
+ its(:market_value) { should be_a Float }
64
+ its(:average_cost) { should be_a Float }
65
+ its(:unrealized_pnl) { should be_a Float }
66
+ its(:realized_pnl) { should be_a Float }
67
+ its(:account_name) { should =~ /\w\d/ }
68
+ its(:to_human) { should =~ /PortfolioValue/ }
69
+ end
70
+
71
+ context "received :AccountDownloadEnd message" do
72
+ subject { @ib.received[:AccountDownloadEnd].first }
73
+
74
+ it { should be_an IB::Messages::Incoming::AccountDownloadEnd }
75
+ its(:data) { should be_a Hash }
76
+ its(:account_name) { should =~ /\w\d/ }
77
+ its(:to_human) { should =~ /AccountDownloadEnd/ }
78
+ end
79
+ end
80
+
@@ -1,94 +1,237 @@
1
1
  require 'message_helper'
2
+ require 'account_helper'
3
+
4
+ shared_examples_for 'Connected Connection' do
5
+
6
+ subject { @ib }
7
+
8
+ it_behaves_like 'Connected Connection without receiver'
9
+
10
+ it 'keeps received messages in Hash by default' do
11
+ subject.received.should be_a Hash
12
+ subject.received[:NextValidId].should_not be_empty
13
+ subject.received[:NextValidId].should have_exactly(1).message
14
+ end
15
+ end
16
+
17
+ shared_examples_for 'Connected Connection without receiver' do
18
+
19
+ it { should_not be_nil }
20
+ it { should be_connected }
21
+ its(:server) { should be_a Hash }
22
+ its(:server) { should have_key :reader }
23
+ its(:subscribers) { should have_at_least(1).item } # :NextValidId and empty Hashes
24
+ its(:next_order_id) { should be_a Fixnum } # Not before :NextValidId arrives
25
+ end
26
+
27
+ # Need top level method to access instance var (@received) in nested context
28
+ def create_connection opts={}
29
+ # Start disconnected (we need to set up catch-all subscriber first)
30
+ @ib = IB::Connection.new OPTS[:connection].merge(:logger => mock_logger).merge(opts)
31
+
32
+ # Hash of received messages, keyed by message type
33
+ @received = Hash.new { |hash, key| hash[key] = Array.new }
34
+
35
+ @subscriber = proc { |msg| @received[msg.message_type] << msg }
36
+ end
2
37
 
3
38
  describe IB::Connection do
4
39
 
5
- context 'when connected to IB Gateway', :connected => true do
6
- # THIS depends on TWS|Gateway connectivity
40
+ context 'instantiated with default options', :connected => true do
7
41
  before(:all) do
8
- @ib = IB::Connection.new OPTS[:connection].merge(:logger => mock_logger)
9
- @ib.subscribe(:OpenOrderEnd) {}
42
+ create_connection
43
+ @ib.wait_for :NextValidId
10
44
  end
11
45
 
12
46
  after(:all) { close_connection }
13
47
 
14
- context 'instantiation with default options' do
15
- subject { @ib }
16
-
17
- it { should_not be_nil }
18
- it { should be_connected }
19
- its(:server) { should be_a Hash }
20
- its(:server) { should have_key :reader }
21
- its(:subscribers) { should have_at_least(1).item } # :NextValidID and empty Hashes
22
- its(:next_order_id) { should be_a Fixnum } # Not before :NextValidID arrives
23
- end
48
+ it_behaves_like 'Connected Connection'
24
49
 
25
50
  describe '#send_message', 'sending messages' do
26
51
  it 'allows 3 signatures representing IB::Messages::Outgoing' do
27
- expect {
28
- @ib.send_message :RequestOpenOrders, :subscribe => true
29
- }.to_not raise_error
52
+ expect { @ib.send_message :RequestOpenOrders }.to_not raise_error
30
53
 
31
- expect {
32
- @ib.send_message IB::Messages::Outgoing::RequestOpenOrders, :subscribe => true
54
+ expect { @ib.send_message IB::Messages::Outgoing::RequestOpenOrders
33
55
  }.to_not raise_error
34
56
 
35
- expect {
36
- @ib.send_message IB::Messages::Outgoing::RequestOpenOrders.new :subscribe => true
57
+ expect { @ib.send_message IB::Messages::Outgoing::RequestOpenOrders.new
37
58
  }.to_not raise_error
38
59
  end
39
60
 
40
61
  it 'has legacy #dispatch alias' do
41
- expect { @ib.dispatch :RequestOpenOrders, :subscribe => true
42
- }.to_not raise_error
62
+ expect { @ib.dispatch :RequestOpenOrders }.to_not raise_error
43
63
  end
44
64
  end
45
65
 
46
66
  context "subscriptions" do
67
+ before(:all) do
68
+ @id = {} # Moving id between contexts. Feels dirty.
69
+ end
70
+
71
+ describe '#subscribe' do
72
+ after(:all) { clean_connection }
73
+
74
+ it 'adds (multiple) subscribers, returning subscription id' do
75
+ @id[:first] = @ib.subscribe(IB::Messages::Incoming::OrderStatus) do |msg|
76
+ log msg.to_human
77
+ end
78
+
79
+ @id[:second] = @ib.subscribe /Value/, :OpenOrder, @subscriber
80
+
81
+ @id[:third] = @ib.subscribe /Account/, &@subscriber
82
+
83
+ [[@id[:first], IB::Messages::Incoming::OrderStatus],
84
+ [@id[:second], IB::Messages::Incoming::OpenOrder],
85
+ [@id[:second], IB::Messages::Incoming::PortfolioValue],
86
+ [@id[:second], IB::Messages::Incoming::AccountValue], # as /Value/
87
+ [@id[:third], IB::Messages::Incoming::AccountValue], # as /Account/
88
+ [@id[:third], IB::Messages::Incoming::AccountDownloadEnd],
89
+ [@id[:third], IB::Messages::Incoming::AccountUpdateTime],
90
+ ].each do |(subscriber_id, message_class)|
91
+ @ib.subscribers.should have_key(message_class)
92
+ @ib.subscribers[message_class].should have_key(subscriber_id)
93
+ end
94
+ end
47
95
 
48
- it '#subscribe, adds(multiple) subscribers' do
49
- @subscriber_id = @ib.subscribe(IB::Messages::Incoming::Alert, :OpenOrder, /Value/) do
96
+ it 'returns Integer subscription id' do
97
+ @id[:first].should be_an Integer
98
+ @id[:second].should be_an Integer
99
+ @id[:third].should be_an Integer
50
100
  end
51
101
 
52
- @subscriber_id.should be_a Fixnum
102
+ context 'when subscribed' do
53
103
 
54
- [IB::Messages::Incoming::Alert,
55
- IB::Messages::Incoming::OpenOrder,
56
- IB::Messages::Incoming::AccountValue,
57
- IB::Messages::Incoming::PortfolioValue
58
- ].each do |message_class|
59
- @ib.subscribers.should have_key(message_class)
60
- @ib.subscribers[message_class].should have_key(@subscriber_id)
104
+ before(:all) do
105
+ @ib.send_message :RequestAccountData
106
+ @ib.wait_for :AccountDownloadEnd
107
+ end
108
+
109
+ after(:all) { @ib.send_message :RequestAccountData, :subscribe => false }
110
+
111
+ it 'receives subscribed message types and processes them in subscriber callback' do
112
+ @received[:AccountValue].should_not be_empty
113
+ @received[:PortfolioValue].should_not be_empty
114
+ @received[:AccountDownloadEnd].should_not be_empty
115
+ @received[:AccountUpdateTime].should_not be_empty
116
+ end
117
+
118
+ it_behaves_like 'Valid account data request'
119
+ end
120
+ end # subscribe
121
+
122
+ describe '#unsubscribe' do
123
+ before(:all) { @result = @ib.unsubscribe @id[:first], @id[:second] }
124
+
125
+ it 'removes all subscribers at given id or ids' do
126
+ [IB::Messages::Incoming::OrderStatus,
127
+ IB::Messages::Incoming::OpenOrder,
128
+ IB::Messages::Incoming::PortfolioValue,
129
+ IB::Messages::Incoming::AccountValue,
130
+ ].each do |message_class|
131
+ @ib.subscribers[message_class].should_not have_key(@id[:first])
132
+ @ib.subscribers[message_class].should_not have_key(@id[:second])
133
+ end
61
134
  end
62
- end
63
135
 
64
- it '#unsubscribe, removes all subscribers at this id' do
65
- @ib.unsubscribe(@subscriber_id)
136
+ it 'does not remove subscribers at other ids' do
137
+ @ib.subscribers[IB::Messages::Incoming::AccountValue].should have_key(@id[:third])
138
+ @ib.subscribers[IB::Messages::Incoming::AccountDownloadEnd].should have_key(@id[:third])
139
+ @ib.subscribers[IB::Messages::Incoming::AccountUpdateTime].should have_key(@id[:third])
140
+ end
141
+
142
+ it 'returns an Array of removed subscribers' do
143
+ @result.should be_an Array
144
+ @result.should have_exactly(4).deleted_subscribers
145
+ end
66
146
 
67
- [IB::Messages::Incoming::Alert,
68
- IB::Messages::Incoming::OpenOrder,
69
- IB::Messages::Incoming::AccountValue,
70
- IB::Messages::Incoming::PortfolioValue
71
- ].each do |message_class|
72
- @ib.subscribers[message_class].should_not have_key(@subscriber_id)
147
+ it 'raises on nosense id given' do
148
+ expect { @ib.unsubscribe 'nonsense' }.to raise_error /No subscribers with id/
149
+ expect { @ib.unsubscribe rand(9999999) }.to raise_error /No subscribers with id/
73
150
  end
74
151
  end
75
152
 
153
+ context 'when unsubscribed' do
154
+
155
+ before(:all) do
156
+ @ib.send_message :RequestAccountData
157
+ @ib.wait_for { !@received[:AccountDownloadEnd].empty? }
158
+ end
159
+
160
+ after(:all) { @ib.send_message :RequestAccountData, :subscribe => false }
161
+
162
+ it 'receives subscribed message types still subscribed' do
163
+ @received[:AccountValue].should_not be_empty
164
+ @received[:AccountUpdateTime].should_not be_empty
165
+ @received[:AccountDownloadEnd].should_not be_empty
166
+ end
167
+
168
+ it 'does not receive unsubscribed message types' do
169
+ @received[:PortfolioValue].should be_empty
170
+ end
171
+
172
+ it { should_log /No subscribers for message .*:PortfolioValue/ }
173
+ it { should_not_log /No subscribers for message .*:AccountValue/ }
174
+ end # when subscribed
76
175
  end # subscriptions
176
+
177
+ describe '#connect' do
178
+ it 'raises on another connection attempt' do
179
+ expect { @ib.connect }.to raise_error /Already connected/
180
+ end
181
+ end
77
182
  end # connected
78
183
 
79
- context 'when not connected to IB Gateway' do
80
- before(:all) { @ib = IB::Connection.new :connect => false, :reader => false }
184
+ context 'instantiated passing :connect => false' do
185
+ before(:all) { create_connection :connect => false,
186
+ :reader => false }
187
+ subject { @ib }
188
+
189
+ it { should_not be_nil }
190
+ it { should_not be_connected }
191
+ its(:server) { should be_a Hash }
192
+ its(:server) { should_not have_key :reader }
193
+ its(:received) { should be_empty }
194
+ its(:subscribers) { should be_empty }
195
+ its(:next_order_id) { should be_nil }
196
+
197
+ describe 'connecting idle conection' do
198
+ before(:all) do
199
+ @ib.connect
200
+ @ib.start_reader
201
+ @ib.wait_for :NextValidId
202
+ end
203
+ after(:all) { close_connection }
204
+
205
+ it_behaves_like 'Connected Connection'
206
+ end
81
207
 
82
- context 'instantiation passing :connect => false' do
83
- subject { @ib }
208
+ end # not connected
84
209
 
85
- it { should_not be_nil }
86
- it { should_not be_connected }
87
- its(:server) { should be_a Hash }
88
- its(:server) { should_not have_key :reader }
89
- its(:subscribers) { should be_empty }
90
- its(:next_order_id) { should be_nil }
210
+ context 'instantiated passing :received => false' do
211
+ before(:all) { create_connection :connect => false,
212
+ :reader => false,
213
+ :received => false }
214
+ subject { @ib }
215
+
216
+ it { should_not be_nil }
217
+ it { should_not be_connected }
218
+ its(:server) { should be_a Hash }
219
+ its(:server) { should_not have_key :reader }
220
+ its(:received) { should be_empty }
221
+ its(:subscribers) { should be_empty }
222
+ its(:next_order_id) { should be_nil }
223
+
224
+ describe 'connecting idle conection' do
225
+ before(:all) do
226
+ @ib.connect
227
+ @ib.start_reader
228
+ @ib.wait_for 1 # ib.received not supposed to work!
229
+ end
230
+ after(:all) { close_connection }
231
+
232
+ it_behaves_like 'Connected Connection without receiver'
91
233
  end
92
234
 
93
235
  end # not connected
236
+
94
237
  end # describe IB::Connection
@@ -7,7 +7,7 @@ shared_examples_for 'Alert message' do
7
7
  its(:message_type) { should == :Alert }
8
8
  its(:message_id) { should == 4 }
9
9
  its(:version) { should == 2 }
10
- its(:data) { should == {:version=>2, :error_id=>-1, :code=>2104, :message=>"Market data farm connection is OK:cashfarm"}}
10
+ its(:data) { should == {:version=>2, :error_id=>-1, :code=>2104, :message=>"Market data farm connection is OK:cashfarm"} }
11
11
  its(:error_id) { should == -1 }
12
12
  its(:code) { should == 2104 }
13
13
  its(:message) { should =~ /Market data farm connection is OK/ }
@@ -37,13 +37,13 @@ describe IB::Messages::Incoming do
37
37
  context 'Message received from IB', :connected => true do
38
38
 
39
39
  before(:all) do
40
- connect_and_receive :Alert
41
- wait_for(2) { received? :Alert }
40
+ @ib = IB::Connection.new OPTS[:connection].merge(:logger => mock_logger)
41
+ @ib.wait_for :Alert
42
42
  end
43
43
 
44
44
  after(:all) { close_connection }
45
45
 
46
- subject { @received[:Alert].first }
46
+ subject { @ib.received[:Alert].first }
47
47
 
48
48
  it_behaves_like 'Alert message'
49
49
  end #
@@ -22,6 +22,7 @@ describe IB::Models::ComboLeg do
22
22
  its(:ratio) {should == 0}
23
23
  its(:open_close) {should == 0}
24
24
  its(:short_sale_slot) {should == 0}
25
+ its(:designated_location) {should == ''}
25
26
  its(:exempt_code) {should == -1}
26
27
 
27
28
  its(:created_at) {should be_a Time}
@@ -21,7 +21,7 @@ describe IB::Models::Contract do
21
21
  it { should_not be_nil }
22
22
  its(:con_id) { should == 0 }
23
23
  its(:strike) { should == 0 }
24
- its(:sec_type) { should == '' }
24
+ its(:sec_type) { should be_nil }
25
25
  its(:created_at) { should be_a Time }
26
26
  its(:include_expired) { should == false }
27
27
  end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe IB::Models::Execution do
4
+
5
+ let(:properties) do
6
+ {:account_name => "DU111110",
7
+ :average_price => 1.31075,
8
+ :client_id => 1111,
9
+ :cumulative_quantity => 20000,
10
+ :exchange => "IDEALPRO",
11
+ :exec_id => "0001f4e8.4f5d48f1.01.01",
12
+ :liquidation => 0,
13
+ :order_id => 373,
14
+ :perm_id => 1695693613,
15
+ :price => 1.31075,
16
+ :shares => 20000,
17
+ :side => :buy,
18
+ :time => "20120312 15:41:09"
19
+ }
20
+ end
21
+
22
+ context "instantiation" do
23
+ context 'empty without properties' do
24
+ subject { IB::Models::Execution.new }
25
+
26
+ it { should_not be_nil }
27
+ its(:order_id) { should == 0 }
28
+ its(:client_id) { should == 0 }
29
+ its(:perm_id) { should == 0 }
30
+ its(:shares) { should == 0 }
31
+ its(:price) { should == 0 }
32
+ its(:liquidation) { should == 0 }
33
+ its(:created_at) { should be_a Time }
34
+ end
35
+
36
+ context 'with properties' do
37
+ subject { IB::Models::Execution.new properties }
38
+
39
+ it 'sets properties right' do
40
+ properties.each do |name, value|
41
+ subject.send(name).should == value
42
+ end
43
+ end
44
+ end
45
+ end #instantiation
46
+
47
+ context "properties" do
48
+
49
+ it 'allows setting properties' do
50
+ expect {
51
+ x = IB::Models::Execution.new
52
+ properties.each do |name, value|
53
+ subject.send("#{name}=", value)
54
+ subject.send(name).should == value
55
+ end
56
+ }.to_not raise_error
57
+ end
58
+
59
+ it 'sets side as directed by its setter' do
60
+ @x = IB::Models::Execution.new
61
+ ['BOT', 'BUY', 'Buy', 'buy', :BUY, :BOT, :Buy, :buy, 'B', :b].each do |val|
62
+ expect { @x.side = val }.to_not raise_error
63
+ @x.side.should == :buy
64
+ end
65
+
66
+ ['SELL', 'SLD', 'Sel', 'sell', :SELL, :SLD, :Sell, :sell, 'S', :S].each do |val|
67
+ expect { @x.side = val }.to_not raise_error
68
+ @x.side.should == :sell
69
+ end
70
+ end
71
+ end # properties
72
+
73
+ end # describe IB::Models::Contract
@@ -1,66 +1,10 @@
1
1
  require 'integration_helper'
2
2
 
3
- shared_examples_for 'Valid account data request' do
4
-
5
- after(:all) do
6
- @ib.send_message :RequestAccountData, :subscribe => false
7
- clean_connection
8
- end
9
-
10
- context "received :AccountUpdateTime message" do
11
- subject { @received[:AccountUpdateTime].first }
12
-
13
- it { should be_an IB::Messages::Incoming::AccountUpdateTime }
14
- its(:data) { should be_a Hash }
15
- its(:time_stamp) { should =~ /\d\d:\d\d/ }
16
- its(:to_human) { should =~ /AccountUpdateTime/ }
17
- end
18
-
19
- context "received :AccountValue message" do
20
- subject { @received[:AccountValue].first }
21
-
22
- #ps
23
- it { should be_an IB::Messages::Incoming::AccountValue }
24
- its(:data) { should be_a Hash }
25
- its(:account_name) { should =~ /\w\d/ }
26
- its(:key) { should be_a String }
27
- its(:value) { should be_a String }
28
- its(:currency) { should be_a String }
29
- its(:to_human) { should =~ /AccountValue/ }
30
- end
31
-
32
- context "received :PortfolioValue message" do
33
- subject { @received[:PortfolioValue].first }
34
-
35
- it { should be_an IB::Messages::Incoming::PortfolioValue }
36
- its(:contract) { should be_a IB::Models::Contract }
37
- its(:data) { should be_a Hash }
38
- its(:position) { should be_a Integer }
39
- its(:market_price) { should be_a Float }
40
- its(:market_value) { should be_a Float }
41
- its(:average_cost) { should be_a Float }
42
- its(:unrealized_pnl) { should be_a Float }
43
- its(:realized_pnl) { should be_a Float }
44
- its(:account_name) { should =~ /\w\d/ }
45
- its(:to_human) { should =~ /PortfolioValue/ }
46
- end
47
-
48
- context "received :AccountDownloadEnd message" do
49
- subject { @received[:AccountDownloadEnd].first }
50
-
51
- it { should be_an IB::Messages::Incoming::AccountDownloadEnd }
52
- its(:data) { should be_a Hash }
53
- its(:account_name) { should =~ /\w\d/ }
54
- its(:to_human) { should =~ /AccountDownloadEnd/ }
55
- end
56
- end
57
-
58
3
  describe "Request Account Data", :connected => true, :integration => true do
59
4
 
60
5
  before(:all) do
61
6
  verify_account
62
- connect_and_receive(:Alert, :AccountValue, :AccountDownloadEnd,
63
- :PortfolioValue, :AccountUpdateTime)
7
+ @ib = IB::Connection.new OPTS[:connection].merge(:logger => mock_logger)
64
8
  end
65
9
 
66
10
  after(:all) { close_connection }
@@ -68,7 +12,11 @@ describe "Request Account Data", :connected => true, :integration => true do
68
12
  context "with subscribe option set" do
69
13
  before(:all) do
70
14
  @ib.send_message :RequestAccountData, :subscribe => true
71
- wait_for(5) { received? :AccountDownloadEnd }
15
+ @ib.wait_for 5, :AccountDownloadEnd
16
+ end
17
+ after(:all) do
18
+ @ib.send_message :RequestAccountData, :subscribe => false
19
+ clean_connection
72
20
  end
73
21
 
74
22
  it_behaves_like 'Valid account data request'
@@ -77,7 +25,12 @@ describe "Request Account Data", :connected => true, :integration => true do
77
25
  context "without subscribe option" do
78
26
  before(:all) do
79
27
  @ib.send_message :RequestAccountData
80
- wait_for(5) { received? :AccountDownloadEnd }
28
+ @ib.wait_for 5, :AccountDownloadEnd
29
+ end
30
+
31
+ after(:all) do
32
+ @ib.send_message :RequestAccountData, :subscribe => false
33
+ clean_connection
81
34
  end
82
35
 
83
36
  it_behaves_like 'Valid account data request'