ib-ruby 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
data/HISTORY CHANGED
@@ -189,3 +189,7 @@
189
189
  == 0.8.0 / 2012-06-07
190
190
 
191
191
  * TWS 926 support
192
+
193
+ == 0.8.1 / 2012-06-13
194
+
195
+ * Combo routing parameters and algo parameters supported
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.8.0
1
+ 0.8.1
@@ -83,9 +83,9 @@ class AddOrders < ActiveRecord::Migration
83
83
  t.float :basis_points_type # double: EFP orders only
84
84
  t.string :algo_strategy
85
85
 
86
- # t.string :algo_params # public Vector<TagValue> m_algoParams; ?!
87
- # t.string :leg_prices # Vector<OrderComboLeg> m_orderComboLegs
88
- # t.string :combo_params # not used yet
86
+ t.text :leg_prices # Vector<OrderComboLeg> m_orderComboLegs
87
+ t.text :algo_params # public Vector<TagValue> m_algoParams; ?!
88
+ t.text :combo_params # not used yet
89
89
 
90
90
  t.integer :scale_init_level_size # int: Size of the first (initial) order component.
91
91
  t.integer :scale_subs_level_size # int: Order size of the subsequent scale order
@@ -49,6 +49,7 @@ module IB
49
49
  end
50
50
 
51
51
  def []= key, val
52
+ # p key, val
52
53
  attributes[key.to_sym] = val
53
54
  end
54
55
 
@@ -222,9 +222,9 @@ module IB
222
222
  alias order_combo_legs leg_prices
223
223
  alias smart_combo_routing_params combo_params
224
224
 
225
- #serialize :leg_prices
226
- #serialize :algo_params
227
- #serialize :combo_params
225
+ serialize :leg_prices
226
+ serialize :algo_params, Hash
227
+ serialize :combo_params
228
228
 
229
229
  # Order is always placed for a contract. Here, we explicitly set this link.
230
230
  belongs_to :contract
@@ -306,8 +306,8 @@ module IB
306
306
  :transmit => true,
307
307
  :what_if => false,
308
308
  :leg_prices => [],
309
- :algo_params => [],
310
- :combo_params => [],
309
+ :algo_params => HashWithIndifferentAccess.new, #{},
310
+ :combo_params => HashWithIndifferentAccess.new, #{},
311
311
  :order_state => IB::OrderState.new(:status => 'New',
312
312
  :filled => 0,
313
313
  :remaining => 0,
@@ -315,13 +315,6 @@ module IB
315
315
  :average_price => 0)
316
316
  end
317
317
 
318
- #after_initialize do #opts = {}
319
- # #self.leg_prices = []
320
- # #self.algo_params = {}
321
- # #self.combo_params = {}
322
- # #self.order_state ||= IB::OrderState.new :status => 'New'
323
- #end
324
-
325
318
  def serialize_algo
326
319
  if algo_strategy.nil? || algo_strategy.empty?
327
320
  ''
@@ -103,7 +103,7 @@ describe IB::Connection do
103
103
 
104
104
  before(:all) do
105
105
  @ib.send_message :RequestAccountData
106
- @ib.wait_for :AccountDownloadEnd
106
+ @ib.wait_for :AccountDownloadEnd, 3
107
107
  end
108
108
 
109
109
  after(:all) { @ib.send_message :RequestAccountData, :subscribe => false }
@@ -1,87 +1,87 @@
1
1
  require 'model_helper'
2
2
 
3
3
  describe IB::Models::Order,
4
- :props =>
5
- {:local_id => 23,
6
- :order_ref => 'Test',
7
- :client_id => 1111,
8
- :perm_id => 173276893,
9
- :parent_id => 0,
10
- :side => :buy,
11
- :order_type => :market_if_touched,
12
- :limit_price => 0.1,
13
- :quantity => 100,
14
- :tif => :good_till_cancelled,
15
- :open_close => :close,
16
- :oca_group => '',
17
- :oca_type => :reduce_no_block,
18
- :origin => :firm,
19
- :designated_location => "WHATEVER",
20
- :exempt_code => 123,
21
- :delta_neutral_order_type => :market,
22
- :transmit => false,
23
- :outside_rth => true,
24
- :what_if => true,
25
- :not_held => true},
26
-
27
- # TODO: :presents => { Object => "Formatted"}
28
- :human => "<Order: Test MIT GTC buy 100 New 0.1 #23/173276893 from 1111>",
29
-
30
- :errors => {:side =>["should be buy/sell/short"]},
31
-
32
- :assigns =>
33
- {[:order_type, :delta_neutral_order_type] => codes_and_values_for(:order_type),
34
-
35
- :open_close =>
36
- {[42, nil, 'Foo', :bar] => /should be same.open.close.unknown/,
37
- ['SAME', 'same', 'S', 's', :same, 0, '0'] => :same,
38
- ['OPEN', 'open', 'O', 'o', :open, 1, '1'] => :open,
39
- ['CLOSE', 'close', 'C', 'c', :close, 2, '2'] => :close,
40
- ['UNKNOWN', 'unknown', 'U', 'u', :unknown, 3, '3'] => :unknown,
41
- },
42
-
43
- [:what_if, :not_held, :outside_rth, :hidden, :transmit, :block_order,
44
- :sweep_to_fill, :override_percentage_constraints, :all_or_none,
45
- :etrade_only, :firm_quote_only, :opt_out_smart_routing, :scale_auto_reset,
46
- :scale_random_percent] => boolean_assigns,
47
-
48
- [:local_id, :perm_id, :parent_id] => numeric_or_nil_assigns,
49
- },
50
-
51
- :aliases =>
52
- {[:side, :action] => buy_sell_short_assigns,
53
- [:quantity, :total_quantity] => numeric_or_nil_assigns,
54
- },
55
-
56
- :collections =>
57
- {:order_states =>[{:status => :Foo},
58
- {:status => 'Bar'},],
59
-
60
- :executions =>
61
- [{:local_id => 23,
62
- :client_id => 1111,
63
- :perm_id => 173276893,
64
- :exchange => "IDEALPRO",
65
- :exec_id => "0001f4e8.4f5d48f1.01.01",
66
- :price => 0.1,
67
- :average_price => 0.1,
68
- :shares => 40,
69
- :cumulative_quantity => 40,
70
- :side => :buy,
71
- :time => "20120312 15:41:09"},
72
-
73
- {:local_id => 23,
74
- :client_id => 1111,
75
- :perm_id => 173276893,
76
- :exchange => "IDEALPRO",
77
- :exec_id => "0001f4e8.4f5d48f1.01.02",
78
- :price => 0.1,
79
- :average_price => 0.1,
80
- :shares => 60,
81
- :cumulative_quantity => 100,
82
- :side => :buy,
83
- :time => "20120312 15:41:10"}]
84
- } do
4
+ :props =>
5
+ {:local_id => 23,
6
+ :order_ref => 'Test',
7
+ :client_id => 1111,
8
+ :perm_id => 173276893,
9
+ :parent_id => 0,
10
+ :side => :buy,
11
+ :order_type => :market_if_touched,
12
+ :limit_price => 0.1,
13
+ :quantity => 100,
14
+ :tif => :good_till_cancelled,
15
+ :open_close => :close,
16
+ :oca_group => '',
17
+ :oca_type => :reduce_no_block,
18
+ :origin => :firm,
19
+ :designated_location => "WHATEVER",
20
+ :exempt_code => 123,
21
+ :delta_neutral_order_type => :market,
22
+ :transmit => false,
23
+ :outside_rth => true,
24
+ :what_if => true,
25
+ :not_held => true},
26
+
27
+ # TODO: :presents => { Object => "Formatted"}
28
+ :human => "<Order: Test MIT GTC buy 100 New 0.1 #23/173276893 from 1111>",
29
+
30
+ :errors => {:side =>["should be buy/sell/short"]},
31
+
32
+ :assigns =>
33
+ {[:order_type, :delta_neutral_order_type] => codes_and_values_for(:order_type),
34
+
35
+ :open_close =>
36
+ {[42, nil, 'Foo', :bar] => /should be same.open.close.unknown/,
37
+ ['SAME', 'same', 'S', 's', :same, 0, '0'] => :same,
38
+ ['OPEN', 'open', 'O', 'o', :open, 1, '1'] => :open,
39
+ ['CLOSE', 'close', 'C', 'c', :close, 2, '2'] => :close,
40
+ ['UNKNOWN', 'unknown', 'U', 'u', :unknown, 3, '3'] => :unknown,
41
+ },
42
+
43
+ [:what_if, :not_held, :outside_rth, :hidden, :transmit, :block_order,
44
+ :sweep_to_fill, :override_percentage_constraints, :all_or_none,
45
+ :etrade_only, :firm_quote_only, :opt_out_smart_routing, :scale_auto_reset,
46
+ :scale_random_percent] => boolean_assigns,
47
+
48
+ [:local_id, :perm_id, :parent_id] => numeric_or_nil_assigns,
49
+ },
50
+
51
+ :aliases =>
52
+ {[:side, :action] => buy_sell_short_assigns,
53
+ [:quantity, :total_quantity] => numeric_or_nil_assigns,
54
+ },
55
+
56
+ :collections =>
57
+ {:order_states =>[{:status => :Foo},
58
+ {:status => 'Bar'},],
59
+
60
+ :executions =>
61
+ [{:local_id => 23,
62
+ :client_id => 1111,
63
+ :perm_id => 173276893,
64
+ :exchange => "IDEALPRO",
65
+ :exec_id => "0001f4e8.4f5d48f1.01.01",
66
+ :price => 0.1,
67
+ :average_price => 0.1,
68
+ :shares => 40,
69
+ :cumulative_quantity => 40,
70
+ :side => :buy,
71
+ :time => "20120312 15:41:09"},
72
+
73
+ {:local_id => 23,
74
+ :client_id => 1111,
75
+ :perm_id => 173276893,
76
+ :exchange => "IDEALPRO",
77
+ :exec_id => "0001f4e8.4f5d48f1.01.02",
78
+ :price => 0.1,
79
+ :average_price => 0.1,
80
+ :shares => 60,
81
+ :cumulative_quantity => 100,
82
+ :side => :buy,
83
+ :time => "20120312 15:41:10"}]
84
+ } do
85
85
 
86
86
  it_behaves_like 'Self-equal Model'
87
87
  it_behaves_like 'Model with invalid defaults'
@@ -173,53 +173,89 @@ describe IB::Models::Order,
173
173
 
174
174
  it 'is not equal for Orders with different limit price' do
175
175
  order1 = IB::Order.new :quantity => 100,
176
- :limit_price => 1,
177
- :action => 'BUY'
176
+ :limit_price => 1,
177
+ :action => 'BUY'
178
178
 
179
179
  order2 = IB::Order.new :total_quantity => 100,
180
- :limit_price => 2,
181
- :action => 'BUY'
180
+ :limit_price => 2,
181
+ :action => 'BUY'
182
182
  order1.should_not == order2
183
183
  order2.should_not == order1
184
184
  end
185
185
 
186
186
  it 'is not equal for Orders with different total_quantity' do
187
187
  order1 = IB::Order.new :quantity => 20000,
188
- :limit_price => 1,
189
- :action => 'BUY'
188
+ :limit_price => 1,
189
+ :action => 'BUY'
190
190
 
191
191
  order2 = IB::Order.new :total_quantity => 100,
192
- :action => 'BUY',
193
- :limit_price => 1
192
+ :action => 'BUY',
193
+ :limit_price => 1
194
194
  order1.should_not == order2
195
195
  order2.should_not == order1
196
196
  end
197
197
 
198
198
  it 'is not equal for Orders with different action/side' do
199
199
  order1 = IB::Order.new :quantity => 100,
200
- :limit_price => 1,
201
- :action => 'SELL'
200
+ :limit_price => 1,
201
+ :action => 'SELL'
202
202
 
203
203
  order2 = IB::Order.new :quantity => 100,
204
- :action => 'BUY',
205
- :limit_price => 1
204
+ :action => 'BUY',
205
+ :limit_price => 1
206
206
  order1.should_not == order2
207
207
  order2.should_not == order1
208
208
  end
209
209
 
210
210
  it 'is not equal for Orders with different order_type' do
211
211
  order1 = IB::Order.new :quantity => 100,
212
- :limit_price => 1,
213
- :action => 'BUY',
214
- :order_type => 'LMT'
212
+ :limit_price => 1,
213
+ :action => 'BUY',
214
+ :order_type => 'LMT'
215
215
 
216
216
  order2 = IB::Order.new :quantity => 100,
217
- :action => 'BUY',
218
- :limit_price => 1,
219
- :order_type => 'MKT'
217
+ :action => 'BUY',
218
+ :limit_price => 1,
219
+ :order_type => 'MKT'
220
220
  order1.should_not == order2
221
221
  order2.should_not == order1
222
222
  end
223
223
  end
224
224
 
225
+ context 'DB-backed serialization of properties', :db => true do
226
+ let(:serializable_props) do
227
+ {
228
+ :algo_strategy => "ArrivalPx",
229
+ :algo_params => { "maxPctVol" => "0.01",
230
+ "riskAversion" => "Passive",
231
+ "startTime" => "9:00:00 EST",
232
+ "endTime" => "15:00:00 EST",
233
+ "forceCompletion" => "0",
234
+ "allowPastEndTime" => "1"},
235
+ :combo_params => {"NonGuaranteed" => "1",
236
+ "LeginPrio" => "0"},
237
+ :leg_prices => [1,2,3],
238
+ }
239
+ end
240
+
241
+ subject { IB::Order.new(props.merge(serializable_props)) }
242
+
243
+ after(:all) { DatabaseCleaner.clean }
244
+
245
+ it 'is saved to DB with serializable_props' do
246
+ subject.save.should be_true
247
+ end
248
+
249
+ it 'is loaded from DB with serializable_props' do
250
+ models = described_class.find(:all)
251
+ models.should have_exactly(1).model
252
+ order = models.first
253
+ order.algo_strategy.should == serializable_props[:algo_strategy]
254
+ order.algo_params.should == serializable_props[:algo_params]
255
+ order.combo_params.should == serializable_props[:combo_params]
256
+ order.leg_prices.should == serializable_props[:leg_prices]
257
+ p order.combo_params
258
+ end
259
+ end # DB
260
+
225
261
  end # describe IB::Order
data/tasks/common.rake CHANGED
@@ -1,18 +1,5 @@
1
- #task :default => 'test:run'
2
- #task 'gem:release' => 'test:run'
1
+ task :default => 'spec:spec'
3
2
 
4
3
  task :notes do
5
4
  puts 'Output annotations (TBD)'
6
5
  end
7
-
8
- #Bundler not ready for prime time just yet
9
- #desc 'Bundle dependencies'
10
- #task :bundle do
11
- # output = `bundle check 2>&1`
12
- #
13
- # unless $?.to_i == 0
14
- # puts output
15
- # system "bundle install"
16
- # puts
17
- # end
18
- #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.8.0
5
+ version: 0.8.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - Paul Legato
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-06-07 00:00:00.000000000 Z
13
+ date: 2012-06-13 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -34,13 +34,13 @@ dependencies:
34
34
  requirements:
35
35
  - - ! '>='
36
36
  - !ruby/object:Gem::Version
37
- version: 0.0.1
37
+ version: 3.2.0
38
38
  none: false
39
39
  requirement: !ruby/object:Gem::Requirement
40
40
  requirements:
41
41
  - - ! '>='
42
42
  - !ruby/object:Gem::Version
43
- version: 0.0.1
43
+ version: 3.2.0
44
44
  none: false
45
45
  prerelease: false
46
46
  type: :runtime
@@ -84,13 +84,13 @@ dependencies:
84
84
  requirements:
85
85
  - - ! '>='
86
86
  - !ruby/object:Gem::Version
87
- version: 2.8.0
87
+ version: 0.7.2
88
88
  none: false
89
89
  requirement: !ruby/object:Gem::Requirement
90
90
  requirements:
91
91
  - - ! '>='
92
92
  - !ruby/object:Gem::Version
93
- version: 2.8.0
93
+ version: 0.7.2
94
94
  none: false
95
95
  prerelease: false
96
96
  type: :development
@@ -110,6 +110,24 @@ dependencies:
110
110
  none: false
111
111
  prerelease: false
112
112
  type: :development
113
+ - !ruby/object:Gem::Dependency
114
+ name: standalone_migrations
115
+ version_requirements: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ! '>='
118
+ - !ruby/object:Gem::Version
119
+ version: !binary |-
120
+ MA==
121
+ none: false
122
+ requirement: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ! '>='
125
+ - !ruby/object:Gem::Version
126
+ version: !binary |-
127
+ MA==
128
+ none: false
129
+ prerelease: false
130
+ type: :development
113
131
  - !ruby/object:Gem::Dependency
114
132
  name: my_scripts
115
133
  version_requirements: !ruby/object:Gem::Requirement
@@ -416,8 +434,6 @@ files:
416
434
  VkVSU0lPTg==
417
435
  - !binary |-
418
436
  SElTVE9SWQ==
419
- - !binary |-
420
- VE9ETw==
421
437
  - !binary |-
422
438
  LmdpdGlnbm9yZQ==
423
439
  homepage: https://github.com/pjlegato/ib-ruby
@@ -430,6 +446,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
430
446
  requirements:
431
447
  - - ! '>='
432
448
  - !ruby/object:Gem::Version
449
+ segments:
450
+ - 0
451
+ hash: 2
433
452
  version: !binary |-
434
453
  MA==
435
454
  none: false
@@ -437,12 +456,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
437
456
  requirements:
438
457
  - - ! '>='
439
458
  - !ruby/object:Gem::Version
459
+ segments:
460
+ - 0
461
+ hash: 2
440
462
  version: !binary |-
441
463
  MA==
442
464
  none: false
443
465
  requirements: []
444
466
  rubyforge_project:
445
- rubygems_version: 1.8.23
467
+ rubygems_version: 1.8.24
446
468
  signing_key:
447
469
  specification_version: 3
448
470
  summary: Ruby Implementation of the Interactive Brokers TWS API
@@ -535,4 +557,3 @@ test_files:
535
557
  c3BlYy9pbnRlZ3JhdGlvbi9vcmRlcnMvdHJhZGVzX3NwZWMucmI=
536
558
  - !binary |-
537
559
  c3BlYy9pbnRlZ3JhdGlvbi9vcmRlcnMvdmFsaWRfaWRzX3NwZWMucmI=
538
- ...
data/TODO DELETED
@@ -1,43 +0,0 @@
1
- Plan:
2
-
3
- 1. IB#send_message method should accept block, thus compressing subscribe/send_message
4
- pair into a single call - to simplify DSL.
5
-
6
- 2. IB Connection uses delays to prevent hitting 50 msgs/sec limit:
7
- http://finance.groups.yahoo.com/group/TWSAPI/message/25413
8
-
9
- 3. IB Connection reconnects gracefully in case if TWS disconnects/reconnects
10
-
11
- 4. Messages should be Models as well (audit trail), @received_at timestamp in messages
12
-
13
- 5. Detailed message documentation
14
-
15
- 6. Move Float values to Decimal (roundoff errors showed in spec!)
16
-
17
-
18
- Done:
19
-
20
- 1. Create integration tests for basic use cases
21
-
22
- 2. IB#subscribe should accept regexes.
23
-
24
- 3. Compatibility with API v.966, 967
25
-
26
- 4. Collect all received messages in Connection#received[:type] by default
27
-
28
- 5. Flow handlers: Connection#wait_for / Connection#received?
29
-
30
- 6. Add ActiveRecord backend to all Models
31
-
32
- 7. Make ActiveModel-like attributes Hash and serialization for tableless Models
33
-
34
-
35
- Ideas for future:
36
-
37
- 1. Decouple Broker-specific Adapter from universal high-level messaging layer
38
- (potentially adding other broker adapters)
39
-
40
- 2. Tweak IB::Message API for speed (use class methods)
41
-
42
- 3. Create integration tests for more use cases (spec/README)
43
-