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.
- data/HISTORY +4 -0
- data/TODO +0 -3
- data/VERSION +1 -1
- data/bin/contract_details +3 -3
- data/bin/depth_of_market +1 -1
- data/bin/historic_data +5 -8
- data/bin/market_data +2 -2
- data/bin/option_data +2 -2
- data/lib/ib-ruby/connection.rb +1 -9
- data/lib/ib-ruby/extensions.rb +8 -0
- data/lib/ib-ruby/messages/abstract_message.rb +89 -0
- data/lib/ib-ruby/messages/incoming.rb +415 -487
- data/lib/ib-ruby/messages/outgoing.rb +241 -305
- data/lib/ib-ruby/models/bar.rb +3 -3
- data/lib/ib-ruby/models/contract/bag.rb +1 -5
- data/lib/ib-ruby/models/contract.rb +50 -33
- data/lib/ib-ruby/models/execution.rb +6 -3
- data/lib/ib-ruby/models/order.rb +7 -5
- data/lib/ib-ruby/socket.rb +13 -0
- data/lib/ib-ruby/symbols/forex.rb +7 -14
- data/lib/ib-ruby/symbols/futures.rb +16 -20
- data/lib/ib-ruby/symbols/options.rb +6 -4
- data/lib/ib-ruby/symbols/stocks.rb +1 -1
- data/lib/ib-ruby.rb +1 -0
- data/spec/README.md +34 -0
- data/spec/ib-ruby/connection_spec.rb +4 -4
- data/spec/ib-ruby/messages/incoming_spec.rb +50 -0
- data/spec/ib-ruby/messages/outgoing_spec.rb +32 -0
- data/spec/ib-ruby/models/contract_spec.rb +27 -25
- data/spec/ib-ruby/models/order_spec.rb +56 -23
- data/spec/integration/account_info_spec.rb +85 -0
- data/spec/integration/contract_info_spec.rb +209 -0
- data/spec/integration/depth_data_spec.rb +46 -0
- data/spec/integration/historic_data_spec.rb +82 -0
- data/spec/integration/market_data_spec.rb +97 -0
- data/spec/integration/option_data_spec.rb +96 -0
- data/spec/integration/orders/execution_spec.rb +135 -0
- data/spec/{ib-ruby/messages → integration/orders}/open_order +9 -205
- data/spec/integration/orders/placement_spec.rb +150 -0
- data/spec/integration/orders/valid_ids_spec.rb +84 -0
- data/spec/integration_helper.rb +110 -0
- data/spec/message_helper.rb +13 -18
- data/spec/spec_helper.rb +35 -26
- metadata +33 -17
- data/spec/ib-ruby/messages/README.md +0 -16
- data/spec/ib-ruby/messages/account_info_spec.rb +0 -84
- data/spec/ib-ruby/messages/just_connect_spec.rb +0 -33
- data/spec/ib-ruby/messages/market_data_spec.rb +0 -92
- data/spec/ib-ruby/messages/orders_spec.rb +0 -219
- 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
|
+
|
data/spec/message_helper.rb
CHANGED
@@ -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
|
54
|
-
|
55
|
-
|
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
|
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
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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.
|
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-
|
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.
|
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/
|
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/
|
111
|
-
- spec/ib-ruby/messages/
|
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/
|
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/
|
165
|
-
- spec/ib-ruby/messages/
|
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
|