ib-ruby 0.5.19 → 0.5.21

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.
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