ib-ruby 0.5.19 → 0.5.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/HISTORY +4 -0
  2. data/TODO +0 -3
  3. data/VERSION +1 -1
  4. data/bin/contract_details +3 -3
  5. data/bin/depth_of_market +1 -1
  6. data/bin/historic_data +5 -8
  7. data/bin/market_data +2 -2
  8. data/bin/option_data +2 -2
  9. data/lib/ib-ruby/connection.rb +1 -9
  10. data/lib/ib-ruby/extensions.rb +8 -0
  11. data/lib/ib-ruby/messages/abstract_message.rb +89 -0
  12. data/lib/ib-ruby/messages/incoming.rb +415 -487
  13. data/lib/ib-ruby/messages/outgoing.rb +241 -305
  14. data/lib/ib-ruby/models/bar.rb +3 -3
  15. data/lib/ib-ruby/models/contract/bag.rb +1 -5
  16. data/lib/ib-ruby/models/contract.rb +50 -33
  17. data/lib/ib-ruby/models/execution.rb +6 -3
  18. data/lib/ib-ruby/models/order.rb +7 -5
  19. data/lib/ib-ruby/socket.rb +13 -0
  20. data/lib/ib-ruby/symbols/forex.rb +7 -14
  21. data/lib/ib-ruby/symbols/futures.rb +16 -20
  22. data/lib/ib-ruby/symbols/options.rb +6 -4
  23. data/lib/ib-ruby/symbols/stocks.rb +1 -1
  24. data/lib/ib-ruby.rb +1 -0
  25. data/spec/README.md +34 -0
  26. data/spec/ib-ruby/connection_spec.rb +4 -4
  27. data/spec/ib-ruby/messages/incoming_spec.rb +50 -0
  28. data/spec/ib-ruby/messages/outgoing_spec.rb +32 -0
  29. data/spec/ib-ruby/models/contract_spec.rb +27 -25
  30. data/spec/ib-ruby/models/order_spec.rb +56 -23
  31. data/spec/integration/account_info_spec.rb +85 -0
  32. data/spec/integration/contract_info_spec.rb +209 -0
  33. data/spec/integration/depth_data_spec.rb +46 -0
  34. data/spec/integration/historic_data_spec.rb +82 -0
  35. data/spec/integration/market_data_spec.rb +97 -0
  36. data/spec/integration/option_data_spec.rb +96 -0
  37. data/spec/integration/orders/execution_spec.rb +135 -0
  38. data/spec/{ib-ruby/messages → integration/orders}/open_order +9 -205
  39. data/spec/integration/orders/placement_spec.rb +150 -0
  40. data/spec/integration/orders/valid_ids_spec.rb +84 -0
  41. data/spec/integration_helper.rb +110 -0
  42. data/spec/message_helper.rb +13 -18
  43. data/spec/spec_helper.rb +35 -26
  44. metadata +33 -17
  45. data/spec/ib-ruby/messages/README.md +0 -16
  46. data/spec/ib-ruby/messages/account_info_spec.rb +0 -84
  47. data/spec/ib-ruby/messages/just_connect_spec.rb +0 -33
  48. data/spec/ib-ruby/messages/market_data_spec.rb +0 -92
  49. data/spec/ib-ruby/messages/orders_spec.rb +0 -219
  50. data/spec/ib-ruby_spec.rb +0 -0
@@ -0,0 +1,110 @@
1
+ require 'message_helper'
2
+
3
+ # Make sure integration tests are only run against the pre-configured PAPER ACCOUNT
4
+ def verify_account
5
+ return OPTS[:account_verified] if OPTS[:account_verified]
6
+
7
+ puts
8
+ puts 'WARNING: MAKE SURE TO RUN INTEGRATION TESTS AGAINST IB PAPER ACCOUNT ONLY!'
9
+ puts 'WARNING: FINANCIAL LOSSES MAY RESULT IF YOU RUN TESTS WITH REAL IB ACCOUNT!'
10
+ puts 'WARNING: YOU HAVE BEEN WARNED!'
11
+ puts
12
+ puts 'Configure your connection to IB PAPER ACCOUNT in spec/spec_helper.rb'
13
+ puts
14
+
15
+ account = OPTS[:connection][:account] || OPTS[:connection][:account_name]
16
+ raise "Please configure IB PAPER ACCOUNT in spec/spec_helper.rb" unless account
17
+
18
+ connect_and_receive :AccountValue
19
+ @ib.send_message :RequestAccountData, :subscribe => true
20
+
21
+ wait_for { received? :AccountValue }
22
+ raise "Unable to verify IB PAPER ACCOUNT" unless received? :AccountValue
23
+
24
+ received = @received[:AccountValue].first.account_name
25
+ raise "Connected to wrong account #{received}, expected #{account}" if account != received
26
+
27
+ close_connection
28
+ OPTS[:account_verified] = true
29
+ end
30
+
31
+ ### Helpers for placing and verifying orders
32
+
33
+ def place_order contract, opts
34
+ @contract = contract
35
+ @order = IB::Models::Order.new({:total_quantity => 100,
36
+ :limit_price => 9.13,
37
+ :action => 'BUY',
38
+ :order_type => 'LMT'}.merge(opts))
39
+ @order_id_before = @ib.next_order_id
40
+ @order_id_placed = @ib.place_order @order, @contract
41
+ @order_id_after = @ib.next_order_id
42
+ end
43
+
44
+ def check_status item, status
45
+ case status
46
+ when Regexp
47
+ item.status.should =~ status
48
+ when String
49
+ item.status.should == status
50
+ end
51
+ end
52
+
53
+ def order_status_should_be status, index=0
54
+ msg = @received[:OrderStatus][index]
55
+ msg.should be_an IB::Messages::Incoming::OrderStatus
56
+ msg.order_id.should == @order_id_placed
57
+ msg.perm_id.should be_an Integer
58
+ msg.client_id.should == OPTS[:connection][:client_id]
59
+ msg.parent_id.should == 0
60
+ msg.why_held.should == ''
61
+ check_status msg, status
62
+
63
+ if @contract == IB::Symbols::Forex[:eurusd]
64
+ msg.filled.should == 20000
65
+ msg.remaining.should == 0
66
+ msg.average_fill_price.should be > 1
67
+ msg.average_fill_price.should be < 2
68
+ msg.last_fill_price.should == msg.average_fill_price
69
+ else
70
+ msg.filled.should == 0
71
+ msg.remaining.should == @order.total_quantity
72
+ msg.average_fill_price.should == 0
73
+ msg.last_fill_price.should == 0
74
+ end
75
+ end
76
+
77
+ def open_order_should_be status, index=0
78
+ msg = @received[:OpenOrder][index]
79
+ msg.should be_an IB::Messages::Incoming::OpenOrder
80
+ msg.order.should == @order
81
+ msg.contract.should == @contract
82
+ msg.order.order_id.should == @order_id_placed
83
+ check_status msg.order, status
84
+ end
85
+
86
+ def execution_should_be side, opts={}
87
+ msg = @received[:ExecutionData][opts[:index] || -1]
88
+ msg.request_id.should == (opts[:request_id] || -1)
89
+ msg.contract.should == @contract
90
+
91
+ exec = msg.execution
92
+ exec.perm_id.should be_an Integer
93
+ exec.perm_id.should == @received[:OpenOrder].last.order.perm_id if @received[:OpenOrder].last
94
+ exec.client_id.should == OPTS[:connection][:client_id]
95
+ exec.order_id.should be_an Integer
96
+ exec.order_id.should == @order.order_id if @order
97
+ exec.exec_id.should be_a String
98
+ exec.time.should =~ /\d\d:\d\d:\d\d/
99
+ exec.account_name.should == OPTS[:connection][:account_name]
100
+ exec.exchange.should == 'IDEALPRO'
101
+ exec.side.to_s.should == side
102
+ exec.shares.should == 20000
103
+ exec.cumulative_quantity.should == 20000
104
+ exec.price.should be > 1
105
+ exec.price.should be < 2
106
+ exec.price.should == exec.average_price
107
+ exec.liquidation.should == 0
108
+ end
109
+
110
+
@@ -2,11 +2,6 @@ require 'spec_helper'
2
2
  require 'thread'
3
3
  require 'stringio'
4
4
 
5
- # Given an IB message, retuns its type Symbol (e.g. :OpenOrderEnd)
6
- def message_type msg
7
- msg.class.to_s.split(/::/).last.to_sym
8
- end
9
-
10
5
  def print_subject
11
6
  it 'prints out message' do
12
7
  p subject
@@ -50,42 +45,42 @@ end
50
45
  def connect_and_receive *message_types
51
46
 
52
47
  # Start disconnected (we need to set up catch-all subscriber first)
53
- @ib = IB::Connection.new CONNECTION_OPTS.merge(:connect => false,
54
- :reader => false,
55
- :logger => mock_logger)
48
+ @ib = IB::Connection.new OPTS[:connection].merge(:connect => false,
49
+ :reader => false,
50
+ :logger => mock_logger)
56
51
 
57
52
  # Hash of received messages, keyed by message type
58
53
  @received = Hash.new { |hash, key| hash[key] = Array.new }
59
54
 
60
55
  # Catch all messages of given types and put them inside @received Hash
61
- @ib.subscribe(*message_types) { |msg| @received[message_type(msg)] << msg }
56
+ @ib.subscribe(*message_types) { |msg| @received[msg.message_type] << msg }
62
57
 
63
- @ib.connect
58
+ @ib.connect # We only connect after everything is subscribed
64
59
  @ib.start_reader
65
60
  end
66
61
 
67
- # Clear logs and message collector. Output may be silenced
62
+ # Clear logs and message collector. Output may be silenced.
68
63
  def clean_connection
69
- unless SILENT
70
- puts @received.map { |type, msg| [" #{type}:", msg.map(&:to_human)] }
71
- puts " Logs:"
72
- puts log_entries
64
+ unless OPTS[:silent]
65
+ puts @received.map { |type, msg| [" #{type}:", msg.map(&:to_human)] } if @received
66
+ puts " Logs:", log_entries if @stdout
73
67
  end
74
68
  @stdout.string = '' if @stdout
75
69
  @received.clear if @received
76
70
  end
77
71
 
78
72
  def close_connection
73
+ @ib.cancel_order @order_id_placed if @ib && @order_id_placed
79
74
  @ib.close if @ib
80
75
  clean_connection
81
76
  end
82
77
 
83
78
  #noinspection RubyArgCount
84
- def wait_for time = 1, &condition
79
+ def wait_for time = 2, &condition
85
80
  timeout = Time.now + time
86
81
  sleep 0.1 until timeout < Time.now || condition && condition.call
87
82
  end
88
83
 
89
- def received? symbol
90
- not @received[symbol].empty?
84
+ def received? symbol, times=1
85
+ @received[symbol].size >= times
91
86
  end
data/spec/spec_helper.rb CHANGED
@@ -2,7 +2,20 @@ require 'rspec'
2
2
  require 'ib-ruby'
3
3
 
4
4
  RSpec.configure do |config|
5
- # config.exclusion_filter = { :slow => true }
5
+ config.exclusion_filter = {
6
+ :if => proc do |condition|
7
+ t = Time.now.utc
8
+ case condition # NB: excludes if condition is false!
9
+ when :us_trading_hours
10
+ # 09:30 - 16:00 (ET) Mon-Fri 14:30 - 21:00 (UTC)
11
+ !(t.wday >= 1 && t.wday <= 5 && t.hour >= 15 && t.hour <= 21)
12
+ when :forex_trading_hours
13
+ # 17:15 - 17:00 (ET) Sunday-Friday Forex 22:15 - 22:00 (UTC)
14
+ !(t.wday > 0 && t.wday < 5 || t.wday == 5 && t.hour < 22)
15
+ end
16
+
17
+ end # :slow => true
18
+ }
6
19
  # config.filter = { :focus => true }
7
20
  # config.include(UserExampleHelpers)
8
21
  # config.mock_with :mocha
@@ -10,29 +23,25 @@ RSpec.configure do |config|
10
23
  # config.mock_with :rr
11
24
  end
12
25
 
13
- puts
14
- puts 'WARNING: MAKE SURE TO RUN ALL YOUR TESTS AGAINST IB PAPER ACCOUNT ONLY!'
15
- puts 'WARNING: FINANCIAL LOSSES MAY RESULT IF YOU RUN TESTS WITH REAL IB ACCOUNT!'
16
- puts 'WARNING: YOU HAVE BEEN WARNED!'
17
- puts
18
- puts 'Configure your connection to IB PAPER ACCOUNT in spec/spec_helper.rb'
19
- puts
20
-
21
- # Please uncomment next line if you are REALLY sure you have properly configured
22
- # Connection to IB PAPER ACCOUNT or mock (Brokertron) account
23
- #exit
24
-
25
- SILENT = false #true
26
-
27
- BROKERTRON = false
28
-
29
- CONNECTION_OPTS = BROKERTRON ?
30
- {:client_id => 1111,
31
- :host => 'free.brokertron.com',
32
- :port=> 10501
33
- } :
34
- {:client_id => 1111,
35
- :host => '10.211.55.2', # localhost?
36
- :port=> 4001
37
- }
26
+ # Top level metadata for test suite level hacking
27
+ OPTS = {
28
+ :silent => false, #true, # Verbosity of test outputs
29
+ :brokertron => false, # Use mock (Brokertron) instead of paper account
30
+ }
38
31
 
32
+ if OPTS[:brokertron]
33
+ # Connection to mock (Brokertron) account
34
+ OPTS[:connection] =
35
+ {:client_id => 1111, # Just an arbitrary id
36
+ :host => 'free.brokertron.com',
37
+ :port=> 10501
38
+ }
39
+ else
40
+ # Connection to IB PAPER ACCOUNT
41
+ OPTS[:connection] =
42
+ {:account_name => 'DU118180', # Your IB PAPER ACCOUNT, tests will only run against it
43
+ :client_id => 1111, # Just an arbitrary id
44
+ :host => '10.211.55.2', # Where your TWS/gateway is located, likely 'localhost'
45
+ :port=> 4001 # 4001 for Gateway, 7496 for TWS GUI
46
+ }
47
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: ib-ruby
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.5.19
5
+ version: 0.5.21
6
6
  platform: ruby
7
7
  authors:
8
8
  - Paul Legato
@@ -11,7 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2012-02-23 00:00:00 Z
14
+ date: 2012-03-06 00:00:00 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -32,7 +32,7 @@ dependencies:
32
32
  requirements:
33
33
  - - ">="
34
34
  - !ruby/object:Gem::Version
35
- version: 2.7.0
35
+ version: 2.8.0
36
36
  type: :development
37
37
  version_requirements: *id002
38
38
  - !ruby/object:Gem::Dependency
@@ -83,12 +83,14 @@ files:
83
83
  - lib/ib-ruby.rb
84
84
  - lib/ib-ruby/connection.rb
85
85
  - lib/ib-ruby/constants.rb
86
+ - lib/ib-ruby/extensions.rb
86
87
  - lib/ib-ruby/logger.rb
87
88
  - lib/ib-ruby/messages.rb
88
89
  - lib/ib-ruby/models.rb
89
90
  - lib/ib-ruby/socket.rb
90
91
  - lib/ib-ruby/symbols.rb
91
92
  - lib/ib-ruby/version.rb
93
+ - lib/ib-ruby/messages/abstract_message.rb
92
94
  - lib/ib-ruby/messages/incoming.rb
93
95
  - lib/ib-ruby/messages/outgoing.rb
94
96
  - lib/ib-ruby/models/bar.rb
@@ -103,19 +105,26 @@ files:
103
105
  - lib/ib-ruby/symbols/futures.rb
104
106
  - lib/ib-ruby/symbols/options.rb
105
107
  - lib/ib-ruby/symbols/stocks.rb
106
- - spec/ib-ruby_spec.rb
108
+ - spec/integration_helper.rb
107
109
  - spec/message_helper.rb
110
+ - spec/README.md
108
111
  - spec/spec_helper.rb
109
112
  - spec/ib-ruby/connection_spec.rb
110
- - spec/ib-ruby/messages/account_info_spec.rb
111
- - spec/ib-ruby/messages/just_connect_spec.rb
112
- - spec/ib-ruby/messages/market_data_spec.rb
113
- - spec/ib-ruby/messages/open_order
114
- - spec/ib-ruby/messages/orders_spec.rb
115
- - spec/ib-ruby/messages/README.md
113
+ - spec/ib-ruby/messages/incoming_spec.rb
114
+ - spec/ib-ruby/messages/outgoing_spec.rb
116
115
  - spec/ib-ruby/models/combo_leg_spec.rb
117
116
  - spec/ib-ruby/models/contract_spec.rb
118
117
  - spec/ib-ruby/models/order_spec.rb
118
+ - spec/integration/account_info_spec.rb
119
+ - spec/integration/contract_info_spec.rb
120
+ - spec/integration/depth_data_spec.rb
121
+ - spec/integration/historic_data_spec.rb
122
+ - spec/integration/market_data_spec.rb
123
+ - spec/integration/option_data_spec.rb
124
+ - spec/integration/orders/execution_spec.rb
125
+ - spec/integration/orders/open_order
126
+ - spec/integration/orders/placement_spec.rb
127
+ - spec/integration/orders/valid_ids_spec.rb
119
128
  - tasks/common.rake
120
129
  - tasks/doc.rake
121
130
  - tasks/gem.rake
@@ -157,17 +166,24 @@ signing_key:
157
166
  specification_version: 3
158
167
  summary: Ruby Implementation of the Interactive Brokers TWS API
159
168
  test_files:
160
- - spec/ib-ruby_spec.rb
169
+ - spec/integration_helper.rb
161
170
  - spec/message_helper.rb
171
+ - spec/README.md
162
172
  - spec/spec_helper.rb
163
173
  - spec/ib-ruby/connection_spec.rb
164
- - spec/ib-ruby/messages/account_info_spec.rb
165
- - spec/ib-ruby/messages/just_connect_spec.rb
166
- - spec/ib-ruby/messages/market_data_spec.rb
167
- - spec/ib-ruby/messages/open_order
168
- - spec/ib-ruby/messages/orders_spec.rb
169
- - spec/ib-ruby/messages/README.md
174
+ - spec/ib-ruby/messages/incoming_spec.rb
175
+ - spec/ib-ruby/messages/outgoing_spec.rb
170
176
  - spec/ib-ruby/models/combo_leg_spec.rb
171
177
  - spec/ib-ruby/models/contract_spec.rb
172
178
  - spec/ib-ruby/models/order_spec.rb
179
+ - spec/integration/account_info_spec.rb
180
+ - spec/integration/contract_info_spec.rb
181
+ - spec/integration/depth_data_spec.rb
182
+ - spec/integration/historic_data_spec.rb
183
+ - spec/integration/market_data_spec.rb
184
+ - spec/integration/option_data_spec.rb
185
+ - spec/integration/orders/execution_spec.rb
186
+ - spec/integration/orders/open_order
187
+ - spec/integration/orders/placement_spec.rb
188
+ - spec/integration/orders/valid_ids_spec.rb
173
189
  has_rdoc:
@@ -1,16 +0,0 @@
1
- # WRITING MESSAGE SPECS
2
-
3
- Pattern for writing message specs is like this:
4
-
5
- 1. You indicate your interest in some message types by calling 'connect_and_receive'
6
- in a top-level before(:all) block. All messages of given types will be caught
7
- and placed into @received Hash, keyed by message type
8
-
9
- 2. You send request messages to IB and then wait for specific conditions (or timeout)
10
- by calling 'wait_for' in a context before(:all) block.
11
-
12
- 3. Once the condition is satisfied, you can test the content of @received Hash
13
- to see what messages were received, or log_entries Array to see what was logged
14
-
15
- 4. When done, you call 'close_connection' in a top-level after(:all) block.
16
-
@@ -1,84 +0,0 @@
1
- require 'message_helper'
2
-
3
- describe IB::Messages do
4
-
5
- # Pattern for writing message specs is like this:
6
- #
7
- # 1. You indicate your interest in some message types by calling 'connect_and_receive'
8
- # in a top-level before(:all) block. All messages of given types will be caught
9
- # and placed into @received Hash, keyed by message type
10
- #
11
- # 2. You send request messages to IB and then wait for specific conditions (or timeout)
12
- # by calling 'wait_for' in a context before(:all) block.
13
- #
14
- # 3. Once the condition is satisfied, you can test the content of @received Hash
15
- # to see what messages were received, or log_entries Array to see what was logged
16
- #
17
- # 4. When done, you call 'close_connection' in a top-level after(:all) block.
18
-
19
- context "Request Account Data", :connected => true do
20
-
21
- before(:all) do
22
- connect_and_receive(:Alert, :AccountValue, :AccountDownloadEnd,
23
- :PortfolioValue, :AccountUpdateTime)
24
-
25
- @ib.send_message :RequestAccountData, :subscribe => true
26
-
27
- wait_for(5) { received? :AccountDownloadEnd }
28
- end
29
-
30
- after(:all) do
31
- @ib.send_message :RequestAccountData, :subscribe => false
32
- close_connection
33
- end
34
-
35
- context "received :Alert message " do
36
- subject { @received[:Alert].first }
37
-
38
- it { should be_an IB::Messages::Incoming::Alert }
39
- it { should be_warning }
40
- it { should_not be_error }
41
- its(:code) { should be_a Integer }
42
- its(:message) { should =~ /Market data farm connection is OK/ }
43
- its(:to_human) { should =~ /TWS Warning Message/ }
44
- end
45
-
46
- context "received :AccountValue message" do
47
- subject { @received[:AccountValue].first }
48
-
49
- #ps
50
- it { should be_an IB::Messages::Incoming::AccountValue }
51
- its(:data) { should be_a Hash }
52
- its(:account_name) { should =~ /\w\d/ }
53
- its(:key) { should be_a String }
54
- its(:value) { should be_a String }
55
- its(:currency) { should be_a String }
56
- its(:to_human) { should =~ /AccountValue/ }
57
- end
58
-
59
- context "received :AccountDownloadEnd message" do
60
- subject { @received[:AccountDownloadEnd].first }
61
-
62
- it { should be_an IB::Messages::Incoming::AccountDownloadEnd }
63
- its(:data) { should be_a Hash }
64
- its(:account_name) { should =~ /\w\d/ }
65
- its(:to_human) { should =~ /AccountDownloadEnd/ }
66
- end
67
-
68
- context "received :PortfolioValue message" do
69
- subject { @received[:PortfolioValue].first }
70
-
71
- it { should be_an IB::Messages::Incoming::PortfolioValue }
72
- its(:contract) { should be_a IB::Models::Contract }
73
- its(:data) { should be_a Hash }
74
- its(:position) { should be_a Integer }
75
- its(:market_price) { should be_a Float }
76
- its(:market_value) { should be_a Float }
77
- its(:average_cost) { should be_a Float }
78
- its(:unrealized_pnl) { should be_a Float }
79
- its(:realized_pnl) { should be_a Float }
80
- its(:account_name) { should =~ /\w\d/ }
81
- its(:to_human) { should =~ /PortfolioValue/ }
82
- end
83
- end # Request Account Data
84
- end # describe IB::Messages::Incomming
@@ -1,33 +0,0 @@
1
- require 'message_helper'
2
-
3
- describe IB::Messages do
4
-
5
- context 'Normal message exchange at any connection', :connected => true do
6
-
7
- before(:all) do
8
- connect_and_receive :NextValidID, :OpenOrderEnd, :Alert
9
- wait_for(2) { received? :OpenOrderEnd }
10
- end
11
-
12
- after(:all) { close_connection }
13
-
14
- it 'receives :NextValidID message' do
15
- @received[:NextValidID].should_not be_empty
16
- @received[:NextValidID].first.should be_an IB::Messages::Incoming::NextValidID
17
- end
18
-
19
- it 'receives :OpenOrderEnd message' do
20
- @received[:OpenOrderEnd].should_not be_empty
21
- @received[:OpenOrderEnd].first.should be_an IB::Messages::Incoming::OpenOrderEnd
22
- end
23
-
24
- it 'logs connection notification' do
25
- should_log /Connected to server, version: 53, connection time/
26
- end
27
-
28
- it 'logs next valid order id' do
29
- should_log /Got next valid order id/
30
- end
31
-
32
- end # Normal message exchange at any connection
33
- end # describe IB::Messages
@@ -1,92 +0,0 @@
1
- require 'message_helper'
2
-
3
- describe IB::Messages do
4
-
5
- context 'Request Market Data', :connected => true do
6
-
7
- context 'when subscribed to :Tick... messages' do
8
-
9
- before(:all) do
10
- connect_and_receive :Alert, :TickPrice, :TickSize
11
-
12
- ##TODO consider a follow the sun market lookup for windening the types tested
13
- @ib.send_message :RequestMarketData, :id => 456,
14
- :contract => IB::Symbols::Forex[:eurusd]
15
- wait_for(5) { @received[:TickPrice].size > 3 && @received[:TickSize].size > 1 }
16
- end
17
-
18
- after(:all) do
19
- @ib.send_message :CancelMarketData, :id => 456
20
- close_connection
21
- end
22
-
23
- context "received :Alert message " do
24
- subject { @received[:Alert].first }
25
-
26
- it { should be_an IB::Messages::Incoming::Alert }
27
- it { should be_warning }
28
- it { should_not be_error }
29
- its(:code) { should be_an Integer }
30
- its(:message) { should =~ /Market data farm connection is OK/ }
31
- its(:to_human) { should =~ /TWS Warning Message/ }
32
- end
33
-
34
- context "received :TickPrice message" do
35
- subject { @received[:TickPrice].first }
36
-
37
- it { should be_an IB::Messages::Incoming::TickPrice}
38
- its(:tick_type) { should be_an Integer }
39
- its(:type) { should be_a Symbol }
40
- its(:price) { should be_a Float }
41
- its(:size) { should be_an Integer }
42
- its(:data) { should be_a Hash }
43
- its(:id) { should == 456 } # ticker_id
44
- its(:to_human) { should =~ /TickPrice/ }
45
- end
46
-
47
- context "received :TickSize message" do
48
- subject { @received[:TickSize].first }
49
-
50
- it { should be_an IB::Messages::Incoming::TickSize }
51
- its(:type) { should_not be_nil }
52
- its(:data) { should be_a Hash }
53
- its(:tick_type) { should be_an Integer }
54
- its(:type) { should be_a Symbol }
55
- its(:size) { should be_an Integer }
56
- its(:id) { should == 456 }
57
- its(:to_human) { should =~ /TickSize/ }
58
- end
59
- end # when subscribed to :Tick... messages
60
-
61
- context 'when NOT subscribed to :Tick... messages' do
62
-
63
- before(:all) do
64
- connect_and_receive :NextValidID
65
-
66
- @ib.send_message :RequestMarketData, :id => 456,
67
- :contract => IB::Symbols::Forex[:eurusd]
68
- wait_for(2)
69
- end
70
-
71
- after(:all) do
72
- @ib.send_message :CancelMarketData, :id => 456
73
- close_connection
74
- end
75
-
76
- it "logs warning about unhandled :OpenOrderEnd message" do
77
- should_log /No subscribers for message IB::Messages::Incoming::OpenOrderEnd/
78
- end
79
-
80
- it "logs warning about unhandled :Alert message" do
81
- should_log /No subscribers for message IB::Messages::Incoming::Alert/
82
- end
83
-
84
- it "logs warning about unhandled :Tick... messages" do
85
- should_log /No subscribers for message IB::Messages::Incoming::TickPrice/,
86
- /No subscribers for message IB::Messages::Incoming::TickSize/
87
- end
88
-
89
- end # NOT subscribed to :Tick... messages
90
-
91
- end # Request Market Data
92
- end # describe IB::Messages