ib-ruby 0.5.18 → 0.5.19

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,273 @@
1
+ [#<IB::Messages::Incoming::OpenOrder:0xfdc #<IB::Messages::Incoming::OpenOrder:0x10b8 #<IB::Messages::Incoming::OpenOrder:0x1198
2
+ @contract= @contract= @contract=
3
+ #<IB::Models::Contract:0xfe0 #<IB::Models::Contract:0x10bc #<IB::Models::Contract:0x119c
4
+ @con_id="12087792", @con_id="12087792", @con_id="12087792",
5
+ @exchange="IDEALPRO", @exchange="IDEALPRO", @exchange="IDEALPRO",
6
+ @local_symbol="EUR.USD", @local_symbol="EUR.USD", @local_symbol="EUR.USD",
7
+ @sec_type="CASH", @sec_type="CASH", @sec_type="CASH",
8
+ @created_at=Thu Feb 23 12:17:48 +0400 2012, @created_at=Thu Feb 23 12:17:48 +0400 2012, @created_at=Thu Feb 23 12:17:48 +0400 2012,
9
+ @order= @order= @order=
10
+ #<IB::Models::Order:0x1018 #<IB::Models::Order:0x10f4 #<IB::Models::Order:0x11d4
11
+ @client_id=1111, @client_id=1111, @client_id=1111,
12
+ @commission=nil, @commission=2.5, @commission=2.5,
13
+ @commission_currency="USD", @commission_currency="USD", @commission_currency="USD",
14
+ @id=38, @id=38, @id=38,
15
+ @limit_price=1.4, @limit_price=1.4, @limit_price=1.4,
16
+ @perm_id=300145671, @perm_id=300145671, @perm_id=300145671,
17
+ @status="Filled", @status="Filled", @status="Filled",
18
+ @total_quantity=20000, @total_quantity=20000, @total_quantity=20000,
19
+ @socket=nil>, @socket=nil>, @socket=nil>]
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+
51
+
52
+
53
+
54
+
55
+
56
+
57
+
58
+
59
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+
82
+
83
+
84
+
85
+
86
+
87
+
88
+
89
+
90
+
91
+
92
+
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+
101
+
102
+
103
+
104
+
105
+
106
+
107
+
108
+
109
+
110
+
111
+
112
+
113
+
114
+
115
+
116
+
117
+
118
+
119
+
120
+
121
+
122
+
123
+
124
+
125
+
126
+
127
+
128
+
129
+
130
+
131
+
132
+
133
+
134
+
135
+
136
+
137
+
138
+
139
+
140
+
141
+
142
+
143
+
144
+
145
+
146
+
147
+
148
+
149
+
150
+
151
+
152
+
153
+
154
+
155
+
156
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
164
+
165
+
166
+
167
+
168
+
169
+
170
+
171
+
172
+
173
+
174
+
175
+
176
+
177
+
178
+
179
+
180
+
181
+
182
+
183
+
184
+
185
+
186
+
187
+
188
+
189
+
190
+
191
+
192
+
193
+
194
+
195
+
196
+
197
+
198
+
199
+
200
+
201
+
202
+
203
+
204
+
205
+
206
+
207
+
208
+
209
+
210
+
211
+
212
+
213
+
214
+
215
+
216
+
217
+
218
+
219
+
220
+
221
+
222
+
223
+
224
+
225
+
226
+
227
+
228
+ [#<IB::Messages::Incoming::OrderStatus:0x127c
229
+ @created_at=Thu Feb 23 12:17:48 +0400 2012,
230
+ @data=
231
+ {:version=>6,
232
+ :id=>38,
233
+ :status=>"Filled",
234
+ :filled=>20000,
235
+ :remaining=>0,
236
+ :average_fill_price=>1.3292,
237
+ :perm_id=>300145671,
238
+ :parent_id=>0,
239
+ :last_fill_price=>1.3292,
240
+ :client_id=>1111,
241
+ :why_held=>""},
242
+ @socket=nil>,
243
+ #<IB::Messages::Incoming::OrderStatus:0x12bc
244
+ @created_at=Thu Feb 23 12:17:48 +0400 2012,
245
+ @data=
246
+ {:version=>6,
247
+ :id=>38,
248
+ :status=>"Filled",
249
+ :filled=>20000,
250
+ :remaining=>0,
251
+ :average_fill_price=>1.3292,
252
+ :perm_id=>300145671,
253
+ :parent_id=>0,
254
+ :last_fill_price=>1.3292,
255
+ :client_id=>1111,
256
+ :why_held=>""},
257
+ @socket=nil>,
258
+ #<IB::Messages::Incoming::OrderStatus:0x12d8
259
+ @created_at=Thu Feb 23 12:17:48 +0400 2012,
260
+ @data=
261
+ {:version=>6,
262
+ :id=>38,
263
+ :status=>"Filled",
264
+ :filled=>20000,
265
+ :remaining=>0,
266
+ :average_fill_price=>1.3292,
267
+ :perm_id=>300145671,
268
+ :parent_id=>0,
269
+ :last_fill_price=>1.3292,
270
+ :client_id=>1111,
271
+ :why_held=>""},
272
+ @socket=nil>]
273
+
@@ -0,0 +1,219 @@
1
+ require 'message_helper'
2
+
3
+ describe IB::Messages do
4
+
5
+ context "Orders", :connected => true do
6
+
7
+ before(:all) do
8
+ @eur = IB::Symbols::Forex[:eurusd]
9
+ @eur_order = IB::Models::Order.new :total_quantity => 20000,
10
+ :limit_price => 1,
11
+ :action => 'SELL',
12
+ :order_type => 'LMT'
13
+ @wfc = IB::Symbols::Stocks[:wfc]
14
+ @wfc_order = IB::Models::Order.new :total_quantity => 100,
15
+ :action => 'BUY',
16
+ :order_type => 'LMT'
17
+ end
18
+
19
+ context "Placing wrong order" do
20
+
21
+ before(:all) do
22
+ connect_and_receive :NextValidID, :Alert, :OpenOrder, :OrderStatus
23
+ wait_for { received? :NextValidID }
24
+
25
+ @wfc_order.limit_price = 9.131313 # Set weird non-acceptable price
26
+ @order_id_before = @ib.next_order_id
27
+ @order_id_placed = @ib.place_order @wfc_order, @wfc
28
+
29
+ wait_for 2
30
+ end
31
+
32
+ after(:all) do
33
+ @ib.cancel_order @order_id_placed # Just in case...
34
+ close_connection
35
+ end
36
+
37
+ it 'does not place new Order' do
38
+ @received[:OpenOrder].should be_empty
39
+ @received[:OrderStatus].should be_empty
40
+ end
41
+
42
+ it 'still changes client`s next_order_id' do
43
+ @order_id_placed = @order_id_before
44
+ @ib.next_order_id.should == @order_id_before + 1
45
+ end
46
+
47
+ context 'received :Alert message' do
48
+ subject { @received[:Alert].last }
49
+
50
+ it { should be_an IB::Messages::Incoming::Alert }
51
+ it { should be_error }
52
+ its(:code) { should be_a Integer }
53
+ its(:message) { should =~ /The price does not conform to the minimum price variation for this contract/ }
54
+ end
55
+
56
+ end # Placing wrong order
57
+
58
+ context "Off-market order" do
59
+ before(:all) do
60
+ connect_and_receive :NextValidID, :Alert, :OpenOrder, :OrderStatus
61
+ wait_for { received? :NextValidID }
62
+
63
+ @wfc_order.limit_price = 9.13 # Set acceptable price
64
+ @order_id_before = @ib.next_order_id
65
+ @order_id_placed = @ib.place_order @wfc_order, @wfc
66
+
67
+ wait_for(2) { @received[:OpenOrder].size > 1 && @received[:OpenOrder].size > 1 }
68
+ end
69
+
70
+ after(:all) do
71
+ #pp @received[:OpenOrder]
72
+ @ib.cancel_order @order_id_placed # Just in case...
73
+ close_connection
74
+ end
75
+
76
+ context "Placing" do
77
+
78
+ after(:all) { clean_connection } # Clear logs and message collector
79
+
80
+ it 'changes client`s next_order_id' do
81
+ @order_id_placed = @order_id_before
82
+ @ib.next_order_id.should == @order_id_before + 1
83
+ end
84
+
85
+ context 'received :OpenOrder messages' do
86
+ subject { @received[:OpenOrder] }
87
+
88
+ it { should have_at_least(1).message }
89
+
90
+ it 'receives (optional) Order confirmation first' do
91
+ if subject.size > 1
92
+ msg = subject.first
93
+ msg.should be_an IB::Messages::Incoming::OpenOrder
94
+ msg.contract.should == @wfc
95
+ msg.order.should == @wfc_order
96
+ msg.order.order_id.should == @order_id_placed
97
+ msg.order.status.should == 'PreSubmitted'
98
+ else
99
+ puts 'Warning: Confirmation was skipped!'
100
+ end
101
+ end
102
+
103
+ it 'receives Order submission then' do
104
+ msg = subject.last
105
+ msg.should be_an IB::Messages::Incoming::OpenOrder
106
+ msg.contract.should == @wfc
107
+ msg.order.should == @wfc_order
108
+ msg.order.order_id.should == @order_id_placed
109
+ msg.order.status.should == 'Submitted'
110
+ end
111
+ end
112
+
113
+ context 'received :OrderStatus messages' do
114
+ subject { @received[:OrderStatus] }
115
+
116
+ it { should have_at_least(1).message }
117
+
118
+ it 'receives (optional) Order confirmation first' do
119
+ if subject.size > 1
120
+ msg = subject.first
121
+ msg.should be_an IB::Messages::Incoming::OrderStatus
122
+ msg.id.should == @order_id_placed
123
+ msg.perm_id.should be_an Integer
124
+ msg.client_id.should == 1111
125
+ msg.parent_id.should == 0
126
+ #msg.order_id.should == @order_id_placed
127
+ msg.status.should == 'PreSubmitted'
128
+ msg.filled.should == 0
129
+ msg.remaining.should == 100
130
+ msg.average_fill_price.should == 0
131
+ msg.last_fill_price.should == 0
132
+ msg.why_held.should == ''
133
+ else
134
+ puts 'Warning: Confirmation was skipped!'
135
+ end
136
+ end
137
+
138
+ it 'receives Order submission then' do
139
+ msg = subject.last
140
+ msg.should be_an IB::Messages::Incoming::OrderStatus
141
+ msg.id.should == @order_id_placed
142
+ #msg.order_id.should == @order_id_placed
143
+ msg.perm_id.should be_an Integer
144
+ msg.client_id.should == 1111
145
+ msg.parent_id.should == 0
146
+ msg.status.should == 'Submitted'
147
+ msg.filled.should == 0
148
+ msg.remaining.should == 100
149
+ msg.average_fill_price.should == 0
150
+ msg.last_fill_price.should == 0
151
+ msg.why_held.should == ''
152
+ end
153
+ end
154
+ end # Placing
155
+
156
+ context "Cancelling placed order" do
157
+ before(:all) do
158
+ @ib.cancel_order @order_id_placed
159
+
160
+ wait_for(2) { received?(:OrderStatus) && received?(:Alert) }
161
+ end
162
+
163
+ after(:all) { clean_connection } # Clear logs and message collector
164
+
165
+ it 'does not increase client`s next_order_id further' do
166
+ @ib.next_order_id.should == @order_id_before + 1
167
+ end
168
+
169
+ it { @received[:OrderStatus].should have_exactly(1).status_message }
170
+
171
+ it { @received[:Alert].should have_exactly(1).alert_message }
172
+
173
+ it 'receives Order cancellation status' do
174
+ msg = @received[:OrderStatus].first
175
+ msg.should be_an IB::Messages::Incoming::OrderStatus
176
+ msg.id.should == @order_id_placed
177
+ #msg.order_id.should == @order_id_placed
178
+ msg.perm_id.should be_an Integer
179
+ msg.client_id.should == 1111
180
+ msg.parent_id.should == 0
181
+ msg.status.should == 'Cancelled'
182
+ msg.filled.should == 0
183
+ msg.remaining.should == 100
184
+ msg.average_fill_price.should == 0
185
+ msg.last_fill_price.should == 0
186
+ msg.why_held.should == ''
187
+ end
188
+
189
+ it 'receives Order cancelled Alert' do
190
+ alert = @received[:Alert].first
191
+ alert.should be_an IB::Messages::Incoming::Alert
192
+ alert.message.should =~ /Order Canceled - reason:/
193
+ end
194
+ end # Cancelling
195
+
196
+ context "Cancelling wrong order" do
197
+ before(:all) do
198
+ @ib.cancel_order rand(99999999)
199
+
200
+ wait_for(2) { received?(:Alert) }
201
+ end
202
+
203
+ it { @received[:Alert].should have_exactly(1).alert_message }
204
+
205
+ it 'does not increase client`s next_order_id further' do
206
+ @ib.next_order_id.should == @order_id_before + 1
207
+ end
208
+
209
+ it 'receives unable to find Order Alert' do
210
+ alert = @received[:Alert].first
211
+ alert.should be_an IB::Messages::Incoming::Alert
212
+ alert.message.should =~ /Can't find order with id =/
213
+ end
214
+ end # Cancelling
215
+ end # Off-market order
216
+
217
+
218
+ end # Orders
219
+ end # describe IB::Messages::Incomming
@@ -19,11 +19,11 @@ describe IB::Models::Contract do
19
19
  subject { IB::Models::Contract.new }
20
20
 
21
21
  it { should_not be_nil }
22
- its(:con_id) {should == 0}
23
- its(:strike) {should == 0}
24
- its(:sec_type) {should == ''}
25
- its(:created_at) {should be_a Time}
26
- its(:include_expired) {should == false}
22
+ its(:con_id) { should == 0 }
23
+ its(:strike) { should == 0 }
24
+ its(:sec_type) { should == '' }
25
+ its(:created_at) { should be_a Time }
26
+ its(:include_expired) { should == false }
27
27
  end
28
28
 
29
29
  context 'with properties' do
@@ -36,9 +36,9 @@ describe IB::Models::Contract do
36
36
  end
37
37
 
38
38
  context 'essential properties are still set, even if not given explicitely' do
39
- its(:con_id) {should == 0}
40
- its(:created_at) {should be_a Time}
41
- its(:include_expired) {should == false}
39
+ its(:con_id) { should == 0 }
40
+ its(:created_at) { should be_a Time }
41
+ its(:include_expired) { should == false }
42
42
  end
43
43
  end
44
44
 
@@ -56,22 +56,22 @@ describe IB::Models::Contract do
56
56
  context 'empty without properties' do
57
57
  subject { IB::Models::Contract.new }
58
58
 
59
- its(:summary) {should == subject}
60
- its(:under_con_id) {should == 0}
61
- its(:min_tick) {should == 0}
62
- its(:callable) {should == false}
63
- its(:puttable) {should == false}
64
- its(:coupon) {should == 0}
65
- its(:convertible) {should == false}
66
- its(:next_option_partial) {should == false}
67
- its(:created_at) {should be_a Time}
59
+ its(:summary) { should == subject }
60
+ its(:under_con_id) { should == 0 }
61
+ its(:min_tick) { should == 0 }
62
+ its(:callable) { should == false }
63
+ its(:puttable) { should == false }
64
+ its(:coupon) { should == 0 }
65
+ its(:convertible) { should == false }
66
+ its(:next_option_partial) { should == false }
67
+ its(:created_at) { should be_a Time }
68
68
  end
69
69
 
70
70
  context 'with properties' do
71
71
  subject { IB::Models::Contract.new detailed_properties }
72
72
 
73
- its(:summary) {should == subject}
74
- its(:created_at) {should be_a Time}
73
+ its(:summary) { should == subject }
74
+ its(:created_at) { should be_a Time }
75
75
 
76
76
  it 'sets properties right' do
77
77
  detailed_properties.each do |name, value|
@@ -81,10 +81,9 @@ describe IB::Models::Contract do
81
81
  end
82
82
  end #instantiation
83
83
 
84
-
85
84
  it 'allows setting attributes' do
85
+ x = IB::Models::Contract.new
86
86
  expect {
87
- x = IB::Models::Contract.new
88
87
  x.symbol = "TEST"
89
88
  x.sec_type = IB::SECURITY_TYPES[:stock]
90
89
  x.expiry = 200609
@@ -95,11 +94,21 @@ describe IB::Models::Contract do
95
94
  x.currency = "USD"
96
95
  x.local_symbol = "baz"
97
96
  }.to_not raise_error
97
+
98
+ x.symbol.should == "TEST"
99
+ x.sec_type.should == IB::SECURITY_TYPES[:stock]
100
+ x.expiry.should == '200609'
101
+ x.strike.should == 1234
102
+ x.right.should == "PUT"
103
+ x.multiplier.should == 123
104
+ x.exchange.should == "SMART"
105
+ x.currency.should == "USD"
106
+ x.local_symbol = "baz"
98
107
  end
99
108
 
100
109
  it 'allows setting ContractDetails attributes' do
110
+ x = IB::Models::Contract.new
101
111
  expect {
102
- x = IB::Models::Contract.new
103
112
  x.callable = true
104
113
  x.puttable = true
105
114
  x.convertible = true
@@ -107,56 +116,41 @@ describe IB::Models::Contract do
107
116
  x.min_tick = 123
108
117
  x.next_option_partial = true
109
118
  }.to_not raise_error
119
+
120
+ x.callable.should == true
121
+ x.puttable.should == true
122
+ x.convertible.should == true
123
+ x.under_con_id.should == 321
124
+ x.min_tick.should == 123
125
+ x.next_option_partial.should == true
110
126
  end
111
127
 
112
128
  it 'raises on wrong security type' do
113
- expect {
114
- x = IB::Models::Contract.new({:sec_type => "asdf"})
115
- }.to raise_error ArgumentError
129
+ expect { IB::Models::Contract.new(:sec_type => "asdf") }.to raise_error ArgumentError
116
130
 
117
- expect {
118
- x = IB::Models::Contract.new
119
- x.sec_type = "asdf"
120
- }.to raise_error ArgumentError
131
+ expect { IB::Models::Contract.new.sec_type = "asdf" }.to raise_error ArgumentError
121
132
  end
122
133
 
123
134
  it 'accepts pre-determined security types' do
124
135
  IB::SECURITY_TYPES.values.each do |type|
125
- expect {
126
- x = IB::Models::Contract.new({:sec_type => type})
127
- }.to_not raise_error
128
-
129
- expect {
130
- x = IB::Models::Contract.new
131
- x.sec_type = type
132
- }.to_not raise_error
136
+ expect { IB::Models::Contract.new(:sec_type => type) }.to_not raise_error
137
+
138
+ expect { IB::Models::Contract.new.sec_type = type }.to_not raise_error
133
139
  end
134
140
  end
135
141
 
136
142
  it 'raises on wrong expiry' do
137
- expect {
138
- x = IB::Models::Contract.new({:expiry => "foo"})
139
- }.to raise_error ArgumentError
143
+ expect { IB::Models::Contract.new(:expiry => "foo") }.to raise_error ArgumentError
140
144
 
141
- expect {
142
- x = IB::Models::Contract.new
143
- x.expiry = "foo"
144
- }.to raise_error ArgumentError
145
+ expect { IB::Models::Contract.new.expiry = "foo" }.to raise_error ArgumentError
145
146
  end
146
147
 
147
148
  it 'accepts correct expiry' do
148
- expect {
149
- x = IB::Models::Contract.new({:expiry => "200607"})
150
- }.to_not raise_error
149
+ expect { IB::Models::Contract.new(:expiry => "200607") }.to_not raise_error
151
150
 
152
- expect {
153
- x = IB::Models::Contract.new
154
- x.expiry = "200607"
155
- }.to_not raise_error
151
+ expect { IB::Models::Contract.new.expiry = "200607" }.to_not raise_error
156
152
 
157
- expect {
158
- x = IB::Models::Contract.new({:expiry => 200607})
159
- }.to_not raise_error
153
+ expect { IB::Models::Contract.new(:expiry => 200607) }.to_not raise_error
160
154
 
161
155
  expect {
162
156
  x = IB::Models::Contract.new
@@ -167,25 +161,15 @@ describe IB::Models::Contract do
167
161
  end
168
162
 
169
163
  it 'raises on incorrect right (option type)' do
170
- expect {
171
- x = IB::Models::Contract.new({:right => "foo"})
172
- }.to raise_error ArgumentError
173
- expect {
174
- x = IB::Models::Contract.new
175
- x.right = "foo"
176
- }.to raise_error ArgumentError
164
+ expect { IB::Models::Contract.new(:right => "foo") }.to raise_error ArgumentError
165
+ expect { IB::Models::Contract.new.right = "foo" }.to raise_error ArgumentError
177
166
  end
178
167
 
179
168
  it 'accepts all correct values for right (option type)' do
180
169
  ["PUT", "put", "P", "p", "CALL", "call", "C", "c"].each do |right|
181
- expect {
182
- x = IB::Models::Contract.new({:right => right})
183
- }.to_not raise_error
184
-
185
- expect {
186
- x = IB::Models::Contract.new
187
- x.right = right
188
- }.to_not raise_error
170
+ expect { IB::Models::Contract.new(:right => right) }.to_not raise_error
171
+
172
+ expect { IB::Models::Contract.new.right = right }.to_not raise_error
189
173
  end
190
174
  end
191
175
  end #instantiation
@@ -204,4 +188,16 @@ describe IB::Models::Contract do
204
188
  end
205
189
  end #serialization
206
190
 
191
+ context 'equality' do
192
+ subject { IB::Models::Contract.new properties }
193
+
194
+ it 'be self-equal ' do
195
+ should == subject
196
+ end
197
+
198
+ it 'be equal to object with the same properties' do
199
+ should == IB::Models::Contract.new(properties)
200
+ end
201
+ end
202
+
207
203
  end # describe IB::Models::Contract