ib-ruby 0.5.18 → 0.5.19

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