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