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
@@ -6,7 +6,7 @@ shared_examples_for 'OpenOrder message' do
6
6
  its(:message_id) { should == 5 }
7
7
  its(:version) { should == 28 }
8
8
  its(:data) { should_not be_empty }
9
- its(:order_id) { should be_an Integer }
9
+ its(:local_id) { should be_an Integer }
10
10
  its(:status) { should =~ /Submit/ }
11
11
  its(:to_human) { should =~
12
12
  /<OpenOrder: <Contract: WFC stock NYSE USD> <Order: LMT DAY buy 100 .*Submit.* 9.13 #\d+\/\d+ from 1111/ }
@@ -23,7 +23,7 @@ shared_examples_for 'OpenOrder message' do
23
23
  o.should be_an IB::Order
24
24
  o.client_id.should == 1111
25
25
  o.parent_id.should == 0
26
- o.order_id.should be_an Integer
26
+ o.local_id.should be_an Integer
27
27
  o.perm_id.should be_an Integer
28
28
  o.order_type.should == :limit
29
29
  o.tif.should == :day
@@ -32,7 +32,7 @@ shared_examples_for 'OpenOrder message' do
32
32
 
33
33
  it 'has proper order_state accessor' do
34
34
  os = subject.order_state
35
- os.order_id.should be_an Integer
35
+ os.local_id.should be_an Integer
36
36
  os.perm_id.should be_an Integer
37
37
  os.client_id.should == 1111
38
38
  os.parent_id.should == 0
@@ -53,7 +53,7 @@ describe IB::Messages::Incoming::OpenOrder do
53
53
  subject do
54
54
  IB::Messages::Incoming::OpenOrder.new :version => 28,
55
55
  :order =>
56
- {:order_id => 1313,
56
+ {:local_id => 1313,
57
57
  :perm_id => 172323928,
58
58
  :client_id => 1111,
59
59
  :parent_id => 0,
@@ -63,7 +63,7 @@ describe IB::Messages::Incoming::OpenOrder do
63
63
  :total_quantity => 100,
64
64
  },
65
65
  :order_state =>
66
- {:order_id => 1313,
66
+ {:local_id => 1313,
67
67
  :perm_id => 172323928,
68
68
  :client_id => 1111,
69
69
  :parent_id => 0,
@@ -6,14 +6,14 @@ shared_examples_for 'OrderStatus message' do
6
6
  its(:message_id) { should == 3 }
7
7
  its(:version) { should == 6 }
8
8
  its(:data) { should_not be_empty }
9
- its(:order_id) { should be_an Integer }
9
+ its(:local_id) { should be_an Integer }
10
10
  its(:status) { should =~ /Submit/ }
11
11
  its(:to_human) { should =~
12
12
  /<OrderStatus: <OrderState: .*Submit.* #\d+\/\d+ from 1111 filled 0\/100/ }
13
13
 
14
14
  it 'has proper order_state accessor' do
15
15
  os = subject.order_state
16
- os.order_id.should be_an Integer
16
+ os.local_id.should be_an Integer
17
17
  os.perm_id.should be_an Integer
18
18
  os.client_id.should == 1111
19
19
  os.parent_id.should == 0
@@ -39,7 +39,7 @@ describe IB::Messages::Incoming::OrderStatus do
39
39
  subject do
40
40
  IB::Messages::Incoming::OrderStatus.new :version => 6,
41
41
  :order_state =>
42
- {:order_id => 1313,
42
+ {:local_id => 1313,
43
43
  :perm_id => 172323928,
44
44
  :client_id => 1111,
45
45
  :parent_id => 0,
@@ -1,6 +1,6 @@
1
1
  require 'model_helper'
2
2
 
3
- describe IB::Models::Contracts::Bag do # AKA IB::Bag
3
+ describe IB::Models::Bag do # AKA IB::Bag
4
4
 
5
5
  let(:props) do
6
6
  {:symbol => 'GOOG',
@@ -16,16 +16,6 @@ describe IB::Models::Contracts::Bag do # AKA IB::Bag
16
16
  "<Bag: GOOG SMART USD legs: 81032967|1,81032968|-2,81032973|1 >"
17
17
  end
18
18
 
19
- let(:defaults) do
20
- {:sec_type => :bag,
21
- :con_id => 0,
22
- :strike => 0,
23
- :min_tick => 0,
24
- :include_expired => false,
25
- :created_at => Time,
26
- }
27
- end
28
-
29
19
  let(:errors) do
30
20
  {:legs => ["legs cannot be empty"],
31
21
  }
@@ -39,7 +29,7 @@ describe IB::Models::Contracts::Bag do # AKA IB::Bag
39
29
 
40
30
  :sec_type =>
41
31
  {['BAG', :bag] => :bag,
42
- IB::CODES[:sec_type].reject { |k, v,| k == :bag }.to_a =>
32
+ IB::CODES[:sec_type].reject { |k, _| k == :bag }.to_a =>
43
33
  /should be a bag/},
44
34
 
45
35
  :right =>
@@ -47,23 +37,25 @@ describe IB::Models::Contracts::Bag do # AKA IB::Bag
47
37
  ["PUT", :put, "CALL", "C", :call, :foo, 'BAR', 42] =>
48
38
  /should be none/},
49
39
 
50
- :exchange =>
51
- {[:cboe, 'cboE', 'CBOE'] => 'CBOE',
52
- [:smart, 'SMART', 'smArt'] => 'SMART'},
40
+ :exchange => string_upcase_assigns.merge(
41
+ [:smart, 'SMART', 'smArt'] => 'SMART'),
53
42
 
54
- :primary_exchange =>
55
- {[:cboe, 'cboE', 'CBOE'] => 'CBOE',
56
- [:SMART, 'SMART'] => /should not be SMART/},
43
+ :primary_exchange =>string_upcase_assigns.merge(
44
+ [:SMART, 'SMART'] => /should not be SMART/),
57
45
 
58
- [:symbol, :local_symbol] =>
59
- {['AAPL', :AAPL] => 'AAPL'},
46
+ [:symbol, :local_symbol] => string_assigns,
60
47
 
61
- :multiplier => {['123', 123] => 123},
62
-
63
- [:under_con_id, :min_tick, :coupon] => {123 => 123}
48
+ :multiplier => to_i_assigns,
64
49
  }
65
50
  end
66
51
 
52
+ it 'does not allow empty legs' do
53
+ bag = IB::Bag.new props
54
+ bag.legs = []
55
+ bag.should be_invalid
56
+ bag.errors.messages[:legs].should include "legs cannot be empty"
57
+ end
58
+
67
59
  context 'using shortest class name without properties' do
68
60
  subject { IB::Bag.new }
69
61
  it_behaves_like 'Model instantiated empty'
@@ -15,11 +15,6 @@ describe IB::Models::Bar do # AKA IB::Bar
15
15
  }
16
16
  end
17
17
 
18
- let(:defaults) do
19
- {:created_at => Time,
20
- }
21
- end
22
-
23
18
  let(:errors) do
24
19
  {:close => ["is not a number"],
25
20
  :high => ["is not a number"],
@@ -5,7 +5,7 @@ describe IB::Models::ComboLeg do
5
5
  let(:props) do
6
6
  {:con_id => 81032967,
7
7
  :ratio => 2,
8
- :action => :buy,
8
+ :side => :buy,
9
9
  :exchange => 'CBOE',
10
10
  :open_close => :open,
11
11
  :short_sale_slot => :broker,
@@ -17,41 +17,34 @@ describe IB::Models::ComboLeg do
17
17
  "<ComboLeg: buy 2 con_id 81032967 at CBOE>"
18
18
  end
19
19
 
20
- let(:defaults) do
21
- {:con_id => 0,
22
- :open_close => :same,
23
- :designated_location => '',
24
- :exempt_code => -1,
25
- :exchange => 'SMART', # Unless SMART, Order modification fails
26
- :created_at => Time,
27
- }
28
- end
29
-
30
20
  let(:errors) do
31
21
  {:ratio => ["is not a number"],
32
22
  :side => ["should be buy/sell/short"]}
33
23
  end
34
24
 
35
25
  let(:assigns) do
36
- {:open_close =>
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, nil, 'Foo', :bar] => /should be same.open.close.unknown/},
42
-
43
- :side =>
44
- {['BOT', 'BUY', 'Buy', 'buy', :BUY, :BOT, :Buy, :buy, 'B', :b] => :buy,
45
- ['SELL', 'SLD', 'Sel', 'sell', :SELL, :SLD, :Sell, :sell, 'S', :S] => :sell,
46
- ['SSHORT', 'Short', 'short', :SHORT, :short, 'T', :T] => :short,
47
- ['SSHORTX', 'Shortextemt', 'shortx', :short_exempt, 'X', :X] => :short_exempt,
48
- [42, nil, 'ASK', :foo] => /should be buy.sell.short/},
49
-
26
+ {:open_close => open_close_assigns,
27
+ :side => buy_sell_short_assigns,
50
28
  :designated_location =>
51
29
  {[42, 'FOO', :bar] => /should be blank or orders will be rejected/},
52
30
  }
53
31
  end
54
32
 
33
+ let(:aliases) do
34
+ {[:side, :action] => buy_sell_short_assigns,
35
+ }
36
+ end
37
+
38
+ it 'has combined weight accessor' do
39
+ leg = IB::ComboLeg.new props
40
+ leg.weight = -3
41
+ leg.side.should == :sell
42
+ leg.ratio.should == 3
43
+ leg.weight = 5
44
+ leg.side.should == :buy
45
+ leg.ratio.should == 5
46
+ end
47
+
55
48
  it_behaves_like 'Model'
56
49
  it_behaves_like 'Self-equal Model'
57
50
 
@@ -0,0 +1,54 @@
1
+ require 'model_helper'
2
+
3
+ describe IB::Models::ContractDetail do # AKA IB::ContractDetail
4
+
5
+ let(:props) do
6
+ {:market_name => 'AAPL',
7
+ :trading_class => 'AAPL',
8
+ :min_tick => 0.01,
9
+ :price_magnifier => 1,
10
+ :order_types => 'ACTIVETIM,ADJUST,ALERT,ALGO,ALLOC,AON,AVGCOST,BASKET,COND,CONDORDER,DAY,DEACT,DEACTDIS,DEACTEOD,FOK,GAT,GTC,GTD,GTT,HID,ICE,IOC,LIT,LMT,MIT,MKT,MTL,NONALGO,OCA,PAON,POSTONLY,RELSTK,SCALE,SCALERST,SMARTSTG,STP,STPLMT,TRAIL,TRAILLIT,TRAILLMT,TRAILMIT,VOLAT,WHATIF,',
11
+ :valid_exchanges => 'SMART,AMEX,BATS,BOX,CBOE,CBOE2,IBSX,ISE,MIBSX,NASDAQOM,PHLX,PSE', # The list of exchanges this contract is traded on.
12
+ :under_con_id => 265598,
13
+ :long_name => 'APPLE INC',
14
+ :contract_month => '201301',
15
+ :industry => 'Technology',
16
+ :category => 'Computers',
17
+ :subcategory => 'Computers',
18
+ :time_zone => 'EST',
19
+ :trading_hours => '20120422:0930-1600;20120423:0930-1600',
20
+ :liquid_hours => '20120422:0930-1600;20120423:0930-1600',
21
+ }
22
+ end
23
+
24
+ let(:human) do
25
+ /<ContractDetail: callable: false category: Computers contract_month: 201301 convertible: false coupon: 0.0 .*industry: Technology liquid_hours: 20120422:0930-1600;20120423:0930-1600 long_name: APPLE INC market_name: AAPL min_tick: 0.01 next_option_partial: false order_types: ACTIVETIM,ADJUST,ALERT,ALGO,ALLOC,AON,AVGCOST,BASKET,COND,CONDORDER,DAY,DEACT,DEACTDIS,DEACTEOD,FOK,GAT,GTC,GTD,GTT,HID,ICE,IOC,LIT,LMT,MIT,MKT,MTL,NONALGO,OCA,PAON,POSTONLY,RELSTK,SCALE,SCALERST,SMARTSTG,STP,STPLMT,TRAIL,TRAILLIT,TRAILLMT,TRAILMIT,VOLAT,WHATIF, price_magnifier: 1 puttable: false subcategory: Computers time_zone: EST trading_class: AAPL trading_hours: 20120422:0930-1600;20120423:0930-1600 under_con_id: 265598 .*valid_exchanges: SMART,AMEX,BATS,BOX,CBOE,CBOE2,IBSX,ISE,MIBSX,NASDAQOM,PHLX,PSE>/
26
+ end
27
+
28
+ let(:errors) do
29
+ {:time_zone => ['should be XXX'],
30
+ }
31
+ end
32
+
33
+ let(:assigns) do
34
+ {[:under_con_id, :min_tick, :coupon] => {123 => 123},
35
+
36
+ [:callable, :puttable, :convertible, :next_option_partial] => boolean_assigns,
37
+ }
38
+ end
39
+
40
+ let(:aliases) do
41
+ {[:contract, :summary] => {IB::Contract.new => IB::Contract.new}
42
+ }
43
+ end
44
+
45
+ it_behaves_like 'Model'
46
+ it_behaves_like 'Self-equal Model'
47
+
48
+ context 'using shortest class name without properties' do
49
+ subject { IB::ContractDetail.new }
50
+ it_behaves_like 'Model instantiated empty'
51
+ it_behaves_like 'Self-equal Model'
52
+ end
53
+
54
+ end # describe IB::Contract
@@ -1,13 +1,13 @@
1
1
  require 'model_helper'
2
2
  require 'combo_helper'
3
3
 
4
- describe IB::Models::Contracts::Contract do # AKA IB::Contract
4
+ describe IB::Models::Contract do # AKA IB::Contract
5
5
 
6
6
  let(:props) do
7
7
  {:symbol => 'AAPL',
8
8
  :sec_type => :option,
9
9
  :expiry => '201301',
10
- :strike => 600,
10
+ :strike => 600.5,
11
11
  :right => :put,
12
12
  :multiplier => 10,
13
13
  :exchange => 'SMART',
@@ -16,21 +16,7 @@ describe IB::Models::Contracts::Contract do # AKA IB::Contract
16
16
  end
17
17
 
18
18
  let(:human) do
19
- "<Contract: AAPL option 201301 put 600 SMART USD>"
20
- end
21
-
22
- let(:defaults) do
23
- {:con_id => 0,
24
- :strike => 0,
25
- :min_tick => 0,
26
- :coupon => 0,
27
- :callable => false,
28
- :puttable => false,
29
- :convertible => false,
30
- :next_option_partial => false,
31
- :include_expired => false,
32
- :created_at => Time,
33
- }
19
+ "<Contract: AAPL option 201301 put 600.5 SMART USD>"
34
20
  end
35
21
 
36
22
  let(:errors) do
@@ -47,26 +33,31 @@ describe IB::Models::Contracts::Contract do # AKA IB::Contract
47
33
  :sec_type => codes_and_values_for(:sec_type).
48
34
  merge([:foo, 'BAR', 42] => /should be valid security type/),
49
35
 
36
+ :sec_id_type =>
37
+ {[:isin, 'ISIN', 'iSin'] => 'ISIN',
38
+ [:sedol, :SEDOL, 'sEDoL', 'SEDOL'] => 'SEDOL',
39
+ [:cusip, :CUSIP, 'Cusip', 'CUSIP'] => 'CUSIP',
40
+ [:ric, :RIC, 'rIC', 'RIC'] => 'RIC',
41
+ [nil, ''] => '',
42
+ [:foo, 'BAR', 'baz'] => /should be valid security identifier/},
43
+
50
44
  :right =>
51
45
  {["PUT", "put", "P", "p", :put] => :put,
52
46
  ["CALL", "call", "C", "c", :call] => :call,
53
47
  ['', '0', '?', :none] => :none,
54
48
  [:foo, 'BAR', 42] => /should be put, call or none/},
55
49
 
56
- :exchange =>
57
- {[:cboe, 'cboE', 'CBOE'] => 'CBOE',
58
- [:smart, 'SMART', 'smArt'] => 'SMART'},
50
+ :exchange => string_upcase_assigns.merge(
51
+ [:smart, 'SMART', 'smArt'] => 'SMART'),
59
52
 
60
- :primary_exchange =>
61
- {[:cboe, 'cboE', 'CBOE'] => 'CBOE',
62
- [:SMART, 'SMART'] => /should not be SMART/},
53
+ :primary_exchange =>string_upcase_assigns.merge(
54
+ [:SMART, 'SMART'] => /should not be SMART/),
63
55
 
64
- :multiplier => {['123', 123] => 123},
56
+ :multiplier => to_i_assigns,
65
57
 
66
- [:under_con_id, :min_tick, :coupon] => {123 => 123},
58
+ :strike => to_f_assigns,
67
59
 
68
- [:callable, :puttable, :convertible, :next_option_partial] =>
69
- {[1, true] => true, [0, false] => false},
60
+ :include_expired => boolean_assigns,
70
61
  }
71
62
  end
72
63
 
@@ -123,13 +114,6 @@ describe IB::Models::Contracts::Contract do # AKA IB::Contract
123
114
 
124
115
  end
125
116
 
126
- context 'using shorter class name without properties' do
127
- subject { IB::Models::Contract.new }
128
- it_behaves_like 'Model instantiated empty'
129
- it_behaves_like 'Self-equal Model'
130
- it_behaves_like 'Contract'
131
- end
132
-
133
117
  context 'using shortest class name without properties' do
134
118
  subject { IB::Contract.new }
135
119
  it_behaves_like 'Model instantiated empty'
@@ -149,17 +133,17 @@ describe IB::Models::Contracts::Contract do # AKA IB::Contract
149
133
 
150
134
  it "serializes long" do
151
135
  subject.serialize_long.should ==
152
- ["AAPL", "OPT", "201301", 600, "P", 10, "SMART", nil, "USD", "AAPL 130119C00500000"]
136
+ ["AAPL", "OPT", "201301", 600.5, "P", 10, "SMART", "", "USD", "AAPL 130119C00500000"]
153
137
  end
154
138
 
155
139
  it "serializes short" do
156
140
  subject.serialize_short.should ==
157
- ["AAPL", "OPT", "201301", 600, "P", 10, "SMART", "USD", "AAPL 130119C00500000"]
141
+ ["AAPL", "OPT", "201301", 600.5, "P", 10, "SMART", "USD", "AAPL 130119C00500000"]
158
142
  end
159
143
 
160
144
  it "serializes combo (BAG) contracts for Order placement" do
161
145
  @combo.serialize_long(:con_id, :sec_id).should ==
162
- [0, "GOOG", "BAG", nil, 0.0, "", nil, "SMART", nil, "USD", nil, nil, nil]
146
+ [0, "GOOG", "BAG", "", 0.0, "", nil, "SMART", "", "USD", "", "", nil]
163
147
  end
164
148
 
165
149
  it 'also serializes attached combo legs' do
@@ -178,3 +162,7 @@ describe IB::Models::Contracts::Contract do # AKA IB::Contract
178
162
 
179
163
 
180
164
  end # describe IB::Contract
165
+
166
+ __END__
167
+ IB::Models::ContractDetail id: nil, contract_id: nil, market_name: "AAPL", trading_class: "AAPL", min_tick: 0.01, price_magnifier: 1, order_types: "ACTIVETIM,ADJUST,ALERT,ALGO,ALLOC,AON,AVGCOST,BASKE...", valid_exchanges: "SMART,AMEX,BATS,BOX,CBOE,CBOE2,IBSX,ISE,MIBSX,NASDA...", under_con_id: 265598, long_name: "APPLE INC", contract_month: "201301", industry: "Technology", category: "Computers", subcategory: "Computers", time_zone: "EST", trading_hours: "20120422:0930-1600;20120423:0930-1600", liquid_hours: "20120422:0930-1600;20120423:0930-1600", cusip: nil, ratings: nil, desc_append: nil, bond_type: nil, coupon_type: nil, coupon: 0.0, maturity: nil, issue_date: nil, next_option_date: nil, next_option_type: nil, notes: nil, callable: false, puttable: false, convertible: false, next_option_partial: false, created_at: "2012-04-23 13:58:05", updated_at: "2012-04-23 13:58:05"
168
+ IB::Models::ContractDetail id: nil, contract_id: nil, market_name: "AAPL", trading_class: "AAPL", min_tick: 0.01, price_magnifier: 1, order_types: "ACTIVETIM,ADJUST,ALERT,ALGO,ALLOC,AON,AVGCOST,BASKE...", valid_exchanges: "SMART,AMEX,BATS,BOX,CBOE,CBOE2,IBSX,ISE,MIBSX,NASDA...", under_con_id: 265598, long_name: "APPLE INC", contract_month: "201301", industry: "Technology", category: "Computers", subcategory: "Computers", time_zone: "EST", trading_hours: "20120422:0930-1600;20120423:0930-1600", liquid_hours: "20120422:0930-1600;20120423:0930-1600", cusip: nil, ratings: nil, desc_append: nil, bond_type: nil, coupon_type: nil, coupon: 0.0, maturity: nil, issue_date: nil, next_option_date: nil, next_option_type: nil, notes: nil, callable: false, puttable: false, convertible: false, next_option_partial: false, created_at: "2012-04-23 13:58:04", updated_at: "2012-04-23 13:58:04">
@@ -8,14 +8,14 @@ describe IB::Models::Execution do # AKA IB::Execution
8
8
  :exchange => "IDEALPRO",
9
9
  :exec_id => "0001f4e8.4f5d48f1.01.01",
10
10
  :liquidation => true,
11
- :order_id => 373,
11
+ :local_id => 373,
12
12
  :perm_id => 1695693619,
13
13
  :price => 1.31075,
14
14
  :average_price => 1.31075,
15
15
  :shares => 20000,
16
16
  :cumulative_quantity => 20000,
17
17
  :side => :buy,
18
- :time => "20120312 15:41:09"
18
+ :time => "20120312 15:41:09",
19
19
  }
20
20
  end
21
21
 
@@ -24,17 +24,6 @@ describe IB::Models::Execution do # AKA IB::Execution
24
24
  "cumulative 20000 at 1.31075, ids 373/1695693619/0001f4e8.4f5d48f1.01.01>"
25
25
  end
26
26
 
27
- let(:defaults) do
28
- {:order_id => 0,
29
- :client_id => 0,
30
- :perm_id => 0,
31
- :shares=> 0,
32
- :price => 0,
33
- :liquidation => false,
34
- :created_at => Time,
35
- }
36
- end
37
-
38
27
  let(:errors) do
39
28
  {:side=>["should be buy/sell/short"],
40
29
  :cumulative_quantity=>["is not a number"],
@@ -42,17 +31,73 @@ describe IB::Models::Execution do # AKA IB::Execution
42
31
  end
43
32
 
44
33
  let(:assigns) do
45
- {:side =>
46
- {['BOT', 'BUY', 'Buy', 'buy', :BUY, :BOT, :Buy, :buy, 'B', :b] => :buy,
47
- ['SELL', 'SLD', 'Sel', 'sell', :SELL, :SLD, :Sell, :sell, 'S', :S] => :sell},
34
+ {[:perm_id, :client_id, :cumulative_quantity, :price, :average_price] => numeric_assigns,
35
+ :liquidation => boolean_assigns,
36
+ }
37
+ end
48
38
 
49
- [:shares, :cumulative_quantity, :price, :average_price] =>
50
- {[:foo, 'BAR', nil] => /is not a number/},
39
+ let(:aliases) do
40
+ {[:side, :action] => buy_sell_assigns,
41
+ [:local_id, :order_id] => numeric_assigns,
42
+ [:quantity, :shares] => numeric_assigns,
43
+ [:account_name, :account_number]=> string_assigns,
44
+ }
45
+ end
51
46
 
52
- :liquidation => {[1, true] => true, [0, false] => false},
47
+ let(:associations) do
48
+ {:order => IB::Order.new(:local_id => 23,
49
+ :perm_id => 173276893,
50
+ :client_id => 1111,
51
+ :parent_id => 0,
52
+ :quantity => 100,
53
+ :order_type => :market)
53
54
  }
54
55
  end
55
56
 
56
57
  it_behaves_like 'Model'
57
58
 
59
+ ## TODO: Playing with associations!
60
+ context 'associations' do
61
+ subject { IB::Execution.new props }
62
+
63
+ before(:all) { DatabaseCleaner.clean if IB::DB }
64
+
65
+ it 'saves associated order' do
66
+ order = associations[:order]
67
+
68
+ #p order.save
69
+
70
+ subject.order = order
71
+
72
+ p subject.save
73
+ p subject.errors.messages
74
+
75
+
76
+ p subject.order
77
+ p subject.order.executions
78
+ p subject.to_xml
79
+ p subject.serializable_hash
80
+ p subject.to_json
81
+ p subject.as_json
82
+
83
+ p IB::Execution.new.from_json subject.to_json # TODO: Strings for keys!
84
+
85
+ pending 'Still need to test associations properly'
86
+ end
87
+
88
+ it 'loads associated execution' do
89
+ pending 'Still need to test associations properly'
90
+
91
+ #s1 = IB::Execution.first
92
+ #p s1
93
+ #p s1.order.executions
94
+
95
+ #p o1 = IB::Order.find(:first)
96
+ #p o1.execution
97
+ #
98
+ #p o1.execution.order_id
99
+ end
100
+
101
+ end
102
+
58
103
  end # describe IB::Models::Contract
@@ -1,27 +1,17 @@
1
1
  require 'model_helper'
2
2
 
3
- describe IB::Models::Contracts::Option do # AKA IB::Option
3
+ describe IB::Models::Option do # AKA IB::Option
4
4
 
5
5
  let(:props) do
6
6
  {:symbol => 'AAPL',
7
7
  :expiry => '201301',
8
- :strike => 600,
8
+ :strike => 600.5,
9
9
  :right => :put,
10
10
  }
11
11
  end
12
12
 
13
13
  let(:human) do
14
- "<Option: AAPL 201301 put 600 SMART >"
15
- end
16
-
17
- let(:defaults) do
18
- {:sec_type => :option,
19
- :con_id => 0,
20
- :strike => 0,
21
- :min_tick => 0,
22
- :include_expired => false,
23
- :created_at => Time,
24
- }
14
+ "<Option: AAPL 201301 put 600.5 SMART >"
25
15
  end
26
16
 
27
17
  let(:errors) do
@@ -38,7 +28,7 @@ describe IB::Models::Contracts::Option do # AKA IB::Option
38
28
 
39
29
  :sec_type =>
40
30
  {['OPT', :option] => :option,
41
- IB::CODES[:sec_type].reject { |k, v,| k == :option }.to_a =>
31
+ IB::CODES[:sec_type].reject { |k, _| k == :option }.to_a =>
42
32
  /should be an option/},
43
33
 
44
34
  :right =>
@@ -46,36 +36,24 @@ describe IB::Models::Contracts::Option do # AKA IB::Option
46
36
  ["CALL", "call", "C", "c", :call] => :call,
47
37
  ['', '0', '?', :none, :foo, 'BAR', 42] => /should be put or call/},
48
38
 
49
- :exchange =>
50
- {[:cboe, 'cboE', 'CBOE'] => 'CBOE',
51
- [:smart, 'SMART', 'smArt'] => 'SMART'},
39
+ :exchange => string_upcase_assigns.merge(
40
+ [:smart, 'SMART', 'smArt'] => 'SMART'),
52
41
 
53
- :primary_exchange =>
54
- {[:cboe, 'cboE', 'CBOE'] => 'CBOE',
55
- [:SMART, 'SMART'] => /should not be SMART/},
42
+ :primary_exchange =>string_upcase_assigns.merge(
43
+ [:SMART, 'SMART'] => /should not be SMART/),
56
44
 
57
- :symbol =>
58
- {['AAPL', :AAPL] => 'AAPL'},
45
+ :multiplier => to_i_assigns,
46
+
47
+ :symbol => string_assigns,
59
48
 
60
49
  :local_symbol =>
61
- {['AAPL 130119C00500000', :'AAPL 130119C00500000'] =>
62
- 'AAPL 130119C00500000',
50
+ {['AAPL 130119C00500000', :'AAPL 130119C00500000'] => 'AAPL 130119C00500000',
63
51
  'BAR'=> /invalid OSI code/},
64
52
 
65
53
  :strike => {[0, -30.0] => /must be greater than 0/},
66
-
67
- :multiplier => {['123', 123] => 123},
68
-
69
- [:under_con_id, :min_tick, :coupon] => {123 => 123}
70
-
71
54
  }
72
55
  end
73
56
 
74
- context 'using shorter class name without properties' do
75
- subject { IB::Models::Option.new }
76
- it_behaves_like 'Model instantiated empty'
77
- end
78
-
79
57
  context 'using shortest class name without properties' do
80
58
  subject { IB::Option.new }
81
59
  it_behaves_like 'Model instantiated empty'