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.
- data/HISTORY +4 -0
- data/TODO +21 -20
- data/VERSION +1 -1
- data/bin/cancel_orders +1 -1
- data/bin/list_orders +1 -2
- data/lib/ib-ruby/connection.rb +25 -8
- data/lib/ib-ruby/constants.rb +1 -0
- data/lib/ib-ruby/messages/incoming.rb +5 -5
- data/lib/ib-ruby/messages/outgoing.rb +21 -21
- data/lib/ib-ruby/models/contract.rb +52 -2
- data/lib/ib-ruby/models/model.rb +10 -0
- data/lib/ib-ruby/models/order.rb +34 -2
- data/lib/ib-ruby/socket.rb +1 -1
- data/spec/ib-ruby/connection_spec.rb +24 -17
- data/spec/ib-ruby/messages/account_info_spec.rb +5 -5
- data/spec/ib-ruby/messages/just_connect_spec.rb +3 -1
- data/spec/ib-ruby/messages/market_data_spec.rb +3 -3
- data/spec/ib-ruby/messages/open_order +273 -0
- data/spec/ib-ruby/messages/orders_spec.rb +219 -0
- data/spec/ib-ruby/models/contract_spec.rb +65 -69
- data/spec/ib-ruby/models/order_spec.rb +34 -12
- data/spec/message_helper.rb +16 -2
- data/spec/spec_helper.rb +16 -1
- metadata +7 -3
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|