ib-ruby 0.7.6 → 0.7.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/HISTORY +8 -0
  2. data/Rakefile +8 -0
  3. data/VERSION +1 -1
  4. data/bin/fundamental_data +6 -9
  5. data/lib/ib-ruby/connection.rb +16 -19
  6. data/lib/ib-ruby/constants.rb +3 -1
  7. data/lib/ib-ruby/extensions.rb +5 -0
  8. data/lib/ib-ruby/messages/incoming/contract_data.rb +46 -45
  9. data/lib/ib-ruby/messages/incoming/delta_neutral_validation.rb +8 -5
  10. data/lib/ib-ruby/messages/incoming/execution_data.rb +2 -2
  11. data/lib/ib-ruby/messages/incoming/next_valid_id.rb +18 -0
  12. data/lib/ib-ruby/messages/incoming/open_order.rb +23 -16
  13. data/lib/ib-ruby/messages/incoming/order_status.rb +5 -3
  14. data/lib/ib-ruby/messages/incoming/scanner_data.rb +15 -11
  15. data/lib/ib-ruby/messages/incoming.rb +1 -5
  16. data/lib/ib-ruby/messages/outgoing/abstract_message.rb +2 -1
  17. data/lib/ib-ruby/messages/outgoing/place_order.rb +1 -1
  18. data/lib/ib-ruby/messages/outgoing.rb +1 -1
  19. data/lib/ib-ruby/models/bag.rb +59 -0
  20. data/lib/ib-ruby/models/combo_leg.rb +10 -6
  21. data/lib/ib-ruby/models/contract.rb +278 -0
  22. data/lib/ib-ruby/models/contract_detail.rb +70 -0
  23. data/lib/ib-ruby/models/execution.rb +22 -16
  24. data/lib/ib-ruby/models/model.rb +75 -17
  25. data/lib/ib-ruby/models/model_properties.rb +40 -26
  26. data/lib/ib-ruby/models/option.rb +62 -0
  27. data/lib/ib-ruby/models/order.rb +122 -86
  28. data/lib/ib-ruby/models/order_state.rb +11 -12
  29. data/lib/ib-ruby/models/underlying.rb +36 -0
  30. data/lib/ib-ruby/models.rb +1 -4
  31. data/spec/account_helper.rb +2 -1
  32. data/spec/db.rb +1 -1
  33. data/spec/db_helper.rb +105 -0
  34. data/spec/ib-ruby/connection_spec.rb +3 -3
  35. data/spec/ib-ruby/messages/incoming/open_order_spec.rb +5 -5
  36. data/spec/ib-ruby/messages/incoming/order_status_spec.rb +3 -3
  37. data/spec/ib-ruby/models/bag_spec.rb +15 -23
  38. data/spec/ib-ruby/models/bar_spec.rb +0 -5
  39. data/spec/ib-ruby/models/combo_leg_spec.rb +18 -25
  40. data/spec/ib-ruby/models/contract_detail_spec.rb +54 -0
  41. data/spec/ib-ruby/models/contract_spec.rb +25 -37
  42. data/spec/ib-ruby/models/execution_spec.rb +64 -19
  43. data/spec/ib-ruby/models/option_spec.rb +12 -34
  44. data/spec/ib-ruby/models/order_spec.rb +107 -45
  45. data/spec/ib-ruby/models/order_state_spec.rb +12 -12
  46. data/spec/ib-ruby/models/underlying_spec.rb +36 -0
  47. data/spec/integration/contract_info_spec.rb +65 -55
  48. data/spec/integration/fundamental_data_spec.rb +2 -2
  49. data/spec/integration/orders/attached_spec.rb +3 -3
  50. data/spec/integration/orders/combo_spec.rb +3 -3
  51. data/spec/integration/orders/placement_spec.rb +8 -8
  52. data/spec/integration/orders/{execution_spec.rb → trades_spec.rb} +8 -12
  53. data/spec/integration/orders/valid_ids_spec.rb +3 -3
  54. data/spec/message_helper.rb +1 -1
  55. data/spec/model_helper.rb +150 -85
  56. data/spec/order_helper.rb +35 -18
  57. metadata +18 -10
  58. data/lib/ib-ruby/models/contracts/bag.rb +0 -62
  59. data/lib/ib-ruby/models/contracts/contract.rb +0 -320
  60. data/lib/ib-ruby/models/contracts/option.rb +0 -66
  61. data/lib/ib-ruby/models/contracts.rb +0 -27
data/spec/model_helper.rb CHANGED
@@ -1,9 +1,137 @@
1
1
  require 'spec_helper'
2
+ require 'db_helper'
2
3
 
3
4
  def codes_and_values_for property
4
5
  Hash[IB::VALUES[property].map { |code, value| [[code, value], value] }]
5
6
  end
6
7
 
8
+ def numeric_assigns
9
+ {1313 => 1313,
10
+ [:foo, 'BAR'] => /is not a number/,
11
+ nil => /is not a number/}
12
+ end
13
+
14
+ def numeric_or_nil_assigns
15
+ numeric_assigns.merge(nil => nil)
16
+ end
17
+
18
+ def to_i_assigns
19
+ {[1313, '1313'] => 1313,
20
+ ['foo', 'BAR', nil, '', 0] => 0, } # Symbols NOT coerced! They DO have int equivalent
21
+ end
22
+
23
+ def float_assigns
24
+ {13.13 => 13.13,
25
+ 13 => 13.0,
26
+ nil => /is not a number/,
27
+ [:foo, 'BAR'] => /is not a number/}
28
+ end
29
+
30
+ def to_f_assigns
31
+ {13.13 => 13.13,
32
+ 13 => 13.0,
33
+ [:foo, 'BAR', '', nil, 0] => 0.0}
34
+ end
35
+
36
+ def float_or_nil_assigns
37
+ float_assigns.merge(nil => nil)
38
+ end
39
+
40
+ def boolean_assigns
41
+ {[1, true, 't'] => true,
42
+ [0, false, 'f'] => false}
43
+ end
44
+
45
+ def string_assigns
46
+ {[:Bar, 'Bar'] => 'Bar',
47
+ [:foo, 'foo'] => 'foo'}
48
+ end
49
+
50
+ def string_upcase_assigns
51
+ {[:cboe, :Cboe, 'cboE', 'CBOE'] => 'CBOE',
52
+ [:bar, 'Bar'] => 'BAR',
53
+ [:foo, 'foo'] => 'FOO'}
54
+ end
55
+
56
+ def open_close_assigns
57
+ {['SAME', 'same', 'S', 's', :same, 0, '0'] => :same,
58
+ ['OPEN', 'open', 'O', 'o', :open, 1, '1'] => :open,
59
+ ['CLOSE', 'close', 'C', 'c', :close, 2, '2'] => :close,
60
+ ['UNKNOWN', 'unknown', 'U', 'u', :unknown, 3, '3'] => :unknown,
61
+ [42, nil, 'Foo', :bar] => /should be same.open.close.unknown/}
62
+ end
63
+
64
+ def buy_sell_assigns
65
+ {['BOT', 'BUY', 'Buy', 'buy', :BUY, :BOT, :Buy, :buy, 'B', :b] => :buy,
66
+ ['SELL', 'SLD', 'Sel', 'sell', :SELL, :SLD, :Sell, :sell, 'S', :S] => :sell,
67
+ [1, nil, 'ASK', :foo] => /should be buy.sell/
68
+ }
69
+ end
70
+
71
+ def buy_sell_short_assigns
72
+ buy_sell_assigns.merge(
73
+ ['SSHORT', 'Short', 'short', :SHORT, :short, 'T', :T] => :short,
74
+ ['SSHORTX', 'Shortextemt', 'shortx', :short_exempt, 'X', :X] => :short_exempt,
75
+ [1, nil, 'ASK', :foo] => /should be buy.sell.short/)
76
+ end
77
+
78
+ def test_assigns cases, prop, name
79
+
80
+ # For all test cases given as an Array [res1, res2] or Hash {val => res} ...
81
+ (cases.is_a?(Array) ? cases.map { |e| [e, e] } : cases).each do |values, result|
82
+ #p prop, cases
83
+
84
+ # For all values in this test case ...
85
+ [values].flatten.each do |value|
86
+ #p prop, name, value, result
87
+
88
+ # Assigning this value to a property results in ...
89
+ case result
90
+ when Exception # ... Exception
91
+ expect { subject.send "#{prop}=", value }.
92
+ to raise_error result
93
+
94
+ when Regexp # ... Non-exceptional error, making model invalid
95
+ expect { subject.send "#{prop}=", value }.to_not raise_error
96
+ subject.valid? # just triggers validation
97
+
98
+ #pp subject.errors.messages
99
+
100
+ subject.errors.messages.should have_key name
101
+ subject.should be_invalid
102
+ msg = subject.errors.messages[name].find { |msg| msg =~ result }
103
+ msg.should =~ result
104
+
105
+ else # ... correct uniform assignment to result
106
+
107
+ was_valid = subject.valid?
108
+ expect { subject.send "#{prop}=", value }.to_not raise_error
109
+ subject.send("#{prop}").should == result
110
+ if was_valid
111
+ # Assignment keeps validity
112
+ subject.errors.messages.should_not have_key name
113
+ subject.should be_valid
114
+ end
115
+
116
+ if name != prop # additional asserts for aliases
117
+
118
+ # Assignment to alias changes property as well
119
+ subject.send("#{name}").should == result
120
+
121
+ # Unsetting alias unsets property as well
122
+ subject.send "#{prop}=", nil # unset alias
123
+ subject.send("#{prop}").should be_blank #== nil
124
+ subject.send("#{name}").should be_blank #== nil
125
+
126
+ # Assignment to original property changes alias as well
127
+ subject.send "#{name}=", value
128
+ subject.send("#{prop}").should == result
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+
7
135
  shared_examples_for 'Model' do
8
136
  context 'instantiation without properties' do
9
137
  subject { described_class.new }
@@ -18,7 +146,12 @@ shared_examples_for 'Model' do
18
146
 
19
147
 
20
148
  it 'has correct human-readeable format' do
21
- subject.to_human.should == human
149
+ case human
150
+ when Regexp
151
+ subject.to_human.should =~ human
152
+ else
153
+ subject.to_human.should == human
154
+ end
22
155
  end
23
156
  end
24
157
  end
@@ -39,10 +172,11 @@ shared_examples_for 'Model instantiated empty' do
39
172
  it { should_not be_nil }
40
173
 
41
174
  it 'sets all properties to defaults' do
42
- defined?(defaults) && defaults.each do |name, value|
175
+ subject.default_attributes.each do |name, value|
176
+ #p name, value
43
177
  case value
44
- when Module, Class
45
- subject.send(name).should be_a value
178
+ when Time
179
+ subject.send(name).should be_a Time
46
180
  else
47
181
  subject.send(name).should == value
48
182
  end
@@ -65,9 +199,6 @@ shared_examples_for 'Model instantiated with properties' do
65
199
  end
66
200
 
67
201
  shared_examples_for 'Model properties' do
68
- context 'essential properties are still set, even if not given explicitely' do
69
- its(:created_at) { should be_a Time }
70
- end
71
202
 
72
203
  it 'allows setting properties' do
73
204
  expect {
@@ -80,82 +211,33 @@ shared_examples_for 'Model properties' do
80
211
 
81
212
  it 'sets values to properties as directed by its setters' do
82
213
  defined?(assigns) && assigns.each do |props, cases|
83
- #p props, cases
84
-
85
214
  # For each given property ...
86
- [props].flatten.each do |prop|
87
-
88
- # For all test cases given as an Array [res1, res2] or Hash {val => res} ...
89
- (cases.is_a?(Array) ? cases.map { |e| [e, e] } : cases).each do |values, result|
215
+ [props].flatten.each { |prop| test_assigns cases, prop, prop }
90
216
 
91
- # For all values in this test case ...
92
- [values].flatten.each do |value|
93
-
94
- # Assigning this value to property results in ...
95
- case result
96
- when Exception # ... Exception
97
- expect { subject.send "#{prop}=", value }.
98
- to raise_error result
99
-
100
- when Regexp # ... Non-exceptional error, making model invalid
101
- expect { subject.send "#{prop}=", value }.to_not raise_error
102
- subject.should be_invalid
103
-
104
- #pp subject.errors.messages
105
- #p value, result
106
-
107
- subject.errors.messages[prop].should_not be_nil
108
- msg = subject.errors.messages[prop].find { |msg| msg =~ result }
109
- msg.should =~ result
110
-
111
- else # ... correct uniform assignment to result
112
-
113
- was_valid = subject.valid?
114
- expect { subject.send "#{prop}=", value }.to_not raise_error
115
- subject.send("#{prop}").should == result
116
-
117
- was_valid && (subject.should be_valid) # assignment keeps validity
118
- end
119
- end
120
- end
121
- end
122
217
  end
123
218
  end
124
219
 
220
+ it 'sets values to to aliased properties as well' do
221
+ defined?(aliases) && aliases.each do |alinames, cases|
222
+ name, aliases = *alinames
223
+ # For each original property or alias...
224
+ [name, aliases].flatten.each { |prop| test_assigns cases, prop, name }
225
+ end
226
+ end
125
227
  end
126
228
 
127
229
  shared_examples_for 'Valid Model' do
230
+
128
231
  it 'validates' do
129
- #subject.valid?
130
- #pp subject.errors.messages
131
232
  subject.should be_valid
132
233
  subject.errors.should be_empty
133
234
  end
134
235
 
135
- context 'with DB backend', :db => true do
136
- after(:all) do
137
- #DatabaseCleaner.clean
138
- end
139
-
140
- it 'is saved' do
141
- subject.save.should be_true
142
- end
143
-
144
- it 'is loaded just right' do
145
- models = described_class.find(:all)
146
- model = models.first
147
- #pp model
148
- models.should have_exactly(1).model
149
- model.should == subject
150
- model.should be_valid
151
- props.each do |name, value|
152
- model.send(name).should == value
153
- end
154
- end
155
- end # DB
236
+ it_behaves_like 'Valid DB-backed Model'
156
237
  end
157
238
 
158
239
  shared_examples_for 'Invalid Model' do
240
+
159
241
  it 'does not validate' do
160
242
  subject.should_not be_valid
161
243
  subject.should be_invalid
@@ -163,27 +245,10 @@ shared_examples_for 'Invalid Model' do
163
245
  subject.errors.messages.should == errors if defined? errors
164
246
  end
165
247
 
166
- context 'with DB backend', :db => true do
167
- after(:all) do
168
- #DatabaseCleaner.clean
169
- end
170
-
171
- it 'is not saved' do
172
- subject.save.should be_false
173
- end
174
-
175
- it 'is not loaded' do
176
- models = described_class.find(:all)
177
- models.should have_exactly(0).model
178
- end
179
- end # DB
248
+ it_behaves_like 'Invalid DB-backed Model'
180
249
  end
181
250
 
182
251
  shared_examples_for 'Contract' do
183
- it 'summary points to itself (ContractDetails artifact' do
184
- subject.summary.should == subject
185
- end
186
-
187
252
  it 'becomes invalid if assigned wrong :sec_type property' do
188
253
  subject.sec_type = 'FOO'
189
254
  subject.should be_invalid
data/spec/order_helper.rb CHANGED
@@ -4,9 +4,17 @@ shared_examples_for 'Placed Order' do
4
4
  context "Placing" do
5
5
  after(:all) { clean_connection } # Clear logs and message collector
6
6
 
7
- it 'changes client`s next_order_id' do
8
- @order_id_placed.should == @order_id_before
9
- @ib.next_order_id.should be >= @order_id_before
7
+ it 'sets placement-related properties' do
8
+ @order.placed_at.should be_a Time
9
+ @order.modified_at.should be_a Time
10
+ @order.placed_at.should == @order.modified_at
11
+ @order.local_id.should be_an Integer
12
+ @order.local_id.should == @local_id_before
13
+ end
14
+
15
+ it 'changes client`s next_local_id' do
16
+ @local_id_placed.should == @local_id_before
17
+ @ib.next_local_id.should be >= @local_id_before
10
18
  end
11
19
 
12
20
  it 'receives all appropriate response messages' do
@@ -25,6 +33,7 @@ shared_examples_for 'Placed Order' do
25
33
  order_should_be /Submit/, @attached_order
26
34
  end
27
35
  end
36
+
28
37
  end
29
38
  end # Placing
30
39
 
@@ -36,8 +45,8 @@ shared_examples_for 'Placed Order' do
36
45
 
37
46
  after(:all) { clean_connection } # Clear logs and message collector
38
47
 
39
- it 'does not increase client`s next_order_id further' do
40
- @ib.next_order_id.should == @order_id_after
48
+ it 'does not increase client`s next_local_id further' do
49
+ @ib.next_local_id.should == @local_id_after
41
50
  end
42
51
 
43
52
  it 'receives all appropriate response messages' do
@@ -50,6 +59,8 @@ shared_examples_for 'Placed Order' do
50
59
  order_should_be /Submitted/
51
60
  status_should_be /Submitted/
52
61
 
62
+ #pp @ib.received[:OpenOrder].first
63
+ #
53
64
  if @attached_order
54
65
  if contract_type == :butterfly && @attached_order.tif == :good_till_cancelled
55
66
  pending 'API Bug: Attached GTC orders not working for butterflies!'
@@ -82,8 +93,14 @@ shared_examples_for 'Placed Order' do
82
93
 
83
94
  after(:all) { clean_connection } # Clear logs and message collector
84
95
 
85
- it 'does not increase client`s next_order_id further' do
86
- @ib.next_order_id.should == @order_id_after
96
+ it 'sets placement-related properties' do
97
+ @order.modified_at.should be_a Time
98
+ @order.placed_at.should_not == @order.modified_at
99
+ end
100
+
101
+ it 'does not increase client`s or order`s local_id any more' do
102
+ @order.local_id.should == @local_id_before
103
+ @ib.next_local_id.should == @local_id_after
87
104
  end
88
105
 
89
106
  it 'receives all appropriate response messages' do
@@ -109,14 +126,14 @@ shared_examples_for 'Placed Order' do
109
126
 
110
127
  context "Cancelling placed order" do
111
128
  before(:all) do
112
- @ib.cancel_order @order_id_placed
129
+ @ib.cancel_order @local_id_placed
113
130
  @ib.wait_for [:OrderStatus, 3], :Alert
114
131
  end
115
132
 
116
133
  after(:all) { clean_connection } # Clear logs and message collector
117
134
 
118
- it 'does not increase client`s next_order_id further' do
119
- @ib.next_order_id.should == @order_id_after
135
+ it 'does not increase client`s next_local_id further' do
136
+ @ib.next_local_id.should == @local_id_after
120
137
  end
121
138
 
122
139
  it 'only receives OpenOrder message with PendingCancel' do
@@ -157,20 +174,20 @@ def place_order contract, opts = {}
157
174
  :limit_price => 9.13,
158
175
  :action => 'BUY',
159
176
  :order_type => 'LMT'}.merge(opts))
160
- @order_id_before = @ib.next_order_id
161
- @order_id_placed = @ib.place_order @order, @contract
162
- @order_id_after = @ib.next_order_id
177
+ @local_id_before = @ib.next_local_id
178
+ @local_id_placed = @ib.place_order @order, @contract
179
+ @local_id_after = @ib.next_local_id
163
180
  end
164
181
 
165
182
  def status_should_be status, order=@order
166
183
  msg = @ib.received[:OrderStatus].find do |msg|
167
- msg.order_id == order.order_id &&
184
+ msg.local_id == order.local_id &&
168
185
  status.is_a?(Regexp) ? msg.status =~ status : msg.status == status
169
186
  end
170
187
  msg.should_not be_nil
171
188
  msg.should be_an IB::Messages::Incoming::OrderStatus
172
189
  order_state = msg.order_state
173
- order_state.order_id.should == order.order_id
190
+ order_state.local_id.should == order.local_id
174
191
  order_state.perm_id.should be_an Integer
175
192
  order_state.client_id.should == OPTS[:connection][:client_id]
176
193
  order_state.parent_id.should == 0 unless @attached_order
@@ -193,7 +210,7 @@ end
193
210
 
194
211
  def order_should_be status, order=@order
195
212
  msg = @ib.received[:OpenOrder].find do |msg|
196
- msg.order_id == order.order_id &&
213
+ msg.local_id == order.local_id &&
197
214
  status.is_a?(Regexp) ? msg.status =~ status : msg.status == status
198
215
  end
199
216
  msg.should_not be_nil
@@ -211,8 +228,8 @@ def execution_should_be side, opts={}
211
228
  exec.perm_id.should be_an Integer
212
229
  exec.perm_id.should == @ib.received[:OpenOrder].last.order.perm_id if @ib.received?(:OpenOrder)
213
230
  exec.client_id.should == OPTS[:connection][:client_id]
214
- exec.order_id.should be_an Integer
215
- exec.order_id.should == @order.order_id if @order
231
+ exec.local_id.should be_an Integer
232
+ exec.local_id.should == @order.local_id if @order
216
233
  exec.exec_id.should be_a String
217
234
  exec.time.should =~ /\d\d:\d\d:\d\d/
218
235
  exec.account_name.should == OPTS[:connection][:account_name]
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: ib-ruby
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.7.6
5
+ version: 0.7.8
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-04-18 00:00:00 Z
14
+ date: 2012-04-23 00:00:00 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -21,7 +21,7 @@ dependencies:
21
21
  requirements:
22
22
  - - ">="
23
23
  - !ruby/object:Gem::Version
24
- version: 1.0.20
24
+ version: 1.1.3
25
25
  type: :runtime
26
26
  version_requirements: *id001
27
27
  - !ruby/object:Gem::Dependency
@@ -98,7 +98,7 @@ dependencies:
98
98
  requirements:
99
99
  - - ">="
100
100
  - !ruby/object:Gem::Version
101
- version: 2.8.0
101
+ version: 2.9.0
102
102
  type: :development
103
103
  version_requirements: *id008
104
104
  - !ruby/object:Gem::Dependency
@@ -176,6 +176,7 @@ files:
176
176
  - lib/ib-ruby/messages/incoming/execution_data.rb
177
177
  - lib/ib-ruby/messages/incoming/historical_data.rb
178
178
  - lib/ib-ruby/messages/incoming/market_depths.rb
179
+ - lib/ib-ruby/messages/incoming/next_valid_id.rb
179
180
  - lib/ib-ruby/messages/incoming/open_order.rb
180
181
  - lib/ib-ruby/messages/incoming/order_status.rb
181
182
  - lib/ib-ruby/messages/incoming/portfolio_value.rb
@@ -185,17 +186,18 @@ files:
185
186
  - lib/ib-ruby/messages/outgoing/abstract_message.rb
186
187
  - lib/ib-ruby/messages/outgoing/bar_requests.rb
187
188
  - lib/ib-ruby/messages/outgoing/place_order.rb
189
+ - lib/ib-ruby/models/bag.rb
188
190
  - lib/ib-ruby/models/bar.rb
189
191
  - lib/ib-ruby/models/combo_leg.rb
190
- - lib/ib-ruby/models/contracts.rb
192
+ - lib/ib-ruby/models/contract.rb
193
+ - lib/ib-ruby/models/contract_detail.rb
191
194
  - lib/ib-ruby/models/execution.rb
192
195
  - lib/ib-ruby/models/model.rb
193
196
  - lib/ib-ruby/models/model_properties.rb
197
+ - lib/ib-ruby/models/option.rb
194
198
  - lib/ib-ruby/models/order.rb
195
199
  - lib/ib-ruby/models/order_state.rb
196
- - lib/ib-ruby/models/contracts/bag.rb
197
- - lib/ib-ruby/models/contracts/contract.rb
198
- - lib/ib-ruby/models/contracts/option.rb
200
+ - lib/ib-ruby/models/underlying.rb
199
201
  - lib/ib-ruby/symbols/forex.rb
200
202
  - lib/ib-ruby/symbols/futures.rb
201
203
  - lib/ib-ruby/symbols/options.rb
@@ -203,6 +205,7 @@ files:
203
205
  - spec/account_helper.rb
204
206
  - spec/combo_helper.rb
205
207
  - spec/db.rb
208
+ - spec/db_helper.rb
206
209
  - spec/integration_helper.rb
207
210
  - spec/message_helper.rb
208
211
  - spec/model_helper.rb
@@ -220,11 +223,13 @@ files:
220
223
  - spec/ib-ruby/models/bag_spec.rb
221
224
  - spec/ib-ruby/models/bar_spec.rb
222
225
  - spec/ib-ruby/models/combo_leg_spec.rb
226
+ - spec/ib-ruby/models/contract_detail_spec.rb
223
227
  - spec/ib-ruby/models/contract_spec.rb
224
228
  - spec/ib-ruby/models/execution_spec.rb
225
229
  - spec/ib-ruby/models/option_spec.rb
226
230
  - spec/ib-ruby/models/order_spec.rb
227
231
  - spec/ib-ruby/models/order_state_spec.rb
232
+ - spec/ib-ruby/models/underlying_spec.rb
228
233
  - spec/integration/account_info_spec.rb
229
234
  - spec/integration/contract_info_spec.rb
230
235
  - spec/integration/depth_data_spec.rb
@@ -234,8 +239,8 @@ files:
234
239
  - spec/integration/option_data_spec.rb
235
240
  - spec/integration/orders/attached_spec.rb
236
241
  - spec/integration/orders/combo_spec.rb
237
- - spec/integration/orders/execution_spec.rb
238
242
  - spec/integration/orders/placement_spec.rb
243
+ - spec/integration/orders/trades_spec.rb
239
244
  - spec/integration/orders/valid_ids_spec.rb
240
245
  - tasks/common.rake
241
246
  - tasks/doc.rake
@@ -281,6 +286,7 @@ test_files:
281
286
  - spec/account_helper.rb
282
287
  - spec/combo_helper.rb
283
288
  - spec/db.rb
289
+ - spec/db_helper.rb
284
290
  - spec/integration_helper.rb
285
291
  - spec/message_helper.rb
286
292
  - spec/model_helper.rb
@@ -298,11 +304,13 @@ test_files:
298
304
  - spec/ib-ruby/models/bag_spec.rb
299
305
  - spec/ib-ruby/models/bar_spec.rb
300
306
  - spec/ib-ruby/models/combo_leg_spec.rb
307
+ - spec/ib-ruby/models/contract_detail_spec.rb
301
308
  - spec/ib-ruby/models/contract_spec.rb
302
309
  - spec/ib-ruby/models/execution_spec.rb
303
310
  - spec/ib-ruby/models/option_spec.rb
304
311
  - spec/ib-ruby/models/order_spec.rb
305
312
  - spec/ib-ruby/models/order_state_spec.rb
313
+ - spec/ib-ruby/models/underlying_spec.rb
306
314
  - spec/integration/account_info_spec.rb
307
315
  - spec/integration/contract_info_spec.rb
308
316
  - spec/integration/depth_data_spec.rb
@@ -312,7 +320,7 @@ test_files:
312
320
  - spec/integration/option_data_spec.rb
313
321
  - spec/integration/orders/attached_spec.rb
314
322
  - spec/integration/orders/combo_spec.rb
315
- - spec/integration/orders/execution_spec.rb
316
323
  - spec/integration/orders/placement_spec.rb
324
+ - spec/integration/orders/trades_spec.rb
317
325
  - spec/integration/orders/valid_ids_spec.rb
318
326
  has_rdoc:
@@ -1,62 +0,0 @@
1
- require 'ib-ruby/models/contracts/contract'
2
-
3
- module IB
4
- module Models
5
- module Contracts
6
-
7
- # "BAG" is not really a contract, but a combination (combo) of securities.
8
- # AKA basket or bag of securities. Individual securities in combo are represented
9
- # by ComboLeg objects.
10
- class Bag < Contract
11
- # General Notes:
12
- # 1. :exchange for the leg definition must match that of the combination order.
13
- # The exception is for a STK legs, which must specify the SMART exchange.
14
- # 2. :symbol => "USD" For combo Contract, this is an arbitrary value (like "USD")
15
-
16
- validates_format_of :sec_type, :with => /^bag$/, :message => "should be a bag"
17
- validates_format_of :right, :with => /^none$/, :message => "should be none"
18
- validates_format_of :expiry, :with => /^$/, :message => "should be blank"
19
- validate :legs_cannot_be_empty
20
-
21
- def legs_cannot_be_empty
22
- errors.add(:legs, "legs cannot be empty") if legs.empty?
23
- end
24
-
25
- def initialize opts = {}
26
- @legs = Array.new
27
- self.sec_type = :bag
28
- super opts
29
- end
30
-
31
- def description
32
- self[:description] || to_human
33
- end
34
-
35
- def to_human
36
- "<Bag: #{[symbol, exchange, currency].join(' ')} legs: #{legs_description} >"
37
- end
38
-
39
- ### Leg-related methods
40
- # TODO: Rewrite with legs and legs_description being strictly in sync...
41
-
42
- # TODO: Find a way to serialize legs without references...
43
- # IB-equivalent leg description.
44
- def legs_description
45
- self[:legs_description] || legs.map { |leg| "#{leg.con_id}|#{leg.weight}" }.join(',')
46
- end
47
-
48
- # Check if two Contracts have same legs (maybe in different order)
49
- def same_legs? other
50
- legs == other.legs ||
51
- legs_description.split(',').sort == other.legs_description.split(',').sort
52
- end
53
-
54
- # Contract comparison
55
- def == other
56
- super && same_legs?(other)
57
- end
58
-
59
- end # class Bag
60
- end # Contracts
61
- end # Models
62
- end # IB