ib-ruby 0.7.4 → 0.7.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/.gitignore +3 -0
  2. data/HISTORY +8 -0
  3. data/README.md +2 -2
  4. data/Rakefile +15 -0
  5. data/TODO +7 -2
  6. data/VERSION +1 -1
  7. data/bin/account_info +1 -1
  8. data/bin/cancel_orders +1 -1
  9. data/bin/contract_details +1 -1
  10. data/bin/depth_of_market +1 -1
  11. data/bin/fa_accounts +1 -1
  12. data/bin/fundamental_data +42 -0
  13. data/bin/historic_data +1 -1
  14. data/bin/historic_data_cli +1 -1
  15. data/bin/list_orders +1 -2
  16. data/bin/market_data +1 -1
  17. data/bin/option_data +1 -1
  18. data/bin/place_combo_order +1 -1
  19. data/bin/place_order +1 -1
  20. data/bin/template +1 -4
  21. data/bin/tick_data +2 -2
  22. data/bin/time_and_sales +1 -1
  23. data/lib/ib-ruby.rb +4 -0
  24. data/lib/ib-ruby/connection.rb +50 -34
  25. data/lib/ib-ruby/constants.rb +232 -37
  26. data/lib/ib-ruby/db.rb +25 -0
  27. data/lib/ib-ruby/extensions.rb +51 -1
  28. data/lib/ib-ruby/messages/abstract_message.rb +0 -8
  29. data/lib/ib-ruby/messages/incoming.rb +18 -493
  30. data/lib/ib-ruby/messages/incoming/abstract_message.rb +100 -0
  31. data/lib/ib-ruby/messages/incoming/alert.rb +34 -0
  32. data/lib/ib-ruby/messages/incoming/contract_data.rb +82 -0
  33. data/lib/ib-ruby/messages/incoming/delta_neutral_validation.rb +20 -0
  34. data/lib/ib-ruby/messages/incoming/execution_data.rb +59 -0
  35. data/lib/ib-ruby/messages/incoming/historical_data.rb +55 -0
  36. data/lib/ib-ruby/messages/incoming/market_depths.rb +44 -0
  37. data/lib/ib-ruby/messages/incoming/open_order.rb +32 -16
  38. data/lib/ib-ruby/messages/incoming/order_status.rb +67 -0
  39. data/lib/ib-ruby/messages/incoming/portfolio_value.rb +39 -0
  40. data/lib/ib-ruby/messages/incoming/real_time_bar.rb +32 -0
  41. data/lib/ib-ruby/messages/incoming/scanner_data.rb +49 -0
  42. data/lib/ib-ruby/messages/outgoing.rb +25 -223
  43. data/lib/ib-ruby/messages/outgoing/abstract_message.rb +61 -0
  44. data/lib/ib-ruby/messages/outgoing/bar_requests.rb +149 -0
  45. data/lib/ib-ruby/messages/outgoing/place_order.rb +24 -0
  46. data/lib/ib-ruby/models.rb +4 -0
  47. data/lib/ib-ruby/models/bar.rb +31 -14
  48. data/lib/ib-ruby/models/combo_leg.rb +48 -23
  49. data/lib/ib-ruby/models/contracts.rb +2 -2
  50. data/lib/ib-ruby/models/contracts/bag.rb +11 -7
  51. data/lib/ib-ruby/models/contracts/contract.rb +90 -66
  52. data/lib/ib-ruby/models/contracts/option.rb +16 -7
  53. data/lib/ib-ruby/models/execution.rb +34 -18
  54. data/lib/ib-ruby/models/model.rb +15 -7
  55. data/lib/ib-ruby/models/model_properties.rb +101 -44
  56. data/lib/ib-ruby/models/order.rb +176 -187
  57. data/lib/ib-ruby/models/order_state.rb +99 -0
  58. data/lib/ib-ruby/symbols/forex.rb +10 -10
  59. data/lib/ib-ruby/symbols/futures.rb +6 -6
  60. data/lib/ib-ruby/symbols/stocks.rb +3 -3
  61. data/spec/account_helper.rb +4 -5
  62. data/spec/combo_helper.rb +4 -4
  63. data/spec/db.rb +18 -0
  64. data/spec/ib-ruby/messages/{incoming_spec.rb → incoming/alert_spec.rb} +1 -0
  65. data/spec/ib-ruby/messages/incoming/open_order_spec.rb +100 -0
  66. data/spec/ib-ruby/messages/incoming/order_status_spec.rb +74 -0
  67. data/spec/ib-ruby/messages/{outgoing_spec.rb → outgoing/account_data_spec.rb} +0 -0
  68. data/spec/ib-ruby/messages/outgoing/market_data_type_spec.rb +44 -0
  69. data/spec/ib-ruby/models/bag_spec.rb +97 -0
  70. data/spec/ib-ruby/models/bar_spec.rb +45 -0
  71. data/spec/ib-ruby/models/combo_leg_spec.rb +56 -40
  72. data/spec/ib-ruby/models/contract_spec.rb +134 -170
  73. data/spec/ib-ruby/models/execution_spec.rb +35 -50
  74. data/spec/ib-ruby/models/option_spec.rb +127 -0
  75. data/spec/ib-ruby/models/order_spec.rb +89 -68
  76. data/spec/ib-ruby/models/order_state_spec.rb +55 -0
  77. data/spec/integration/contract_info_spec.rb +4 -6
  78. data/spec/integration/fundamental_data_spec.rb +41 -0
  79. data/spec/integration/historic_data_spec.rb +4 -4
  80. data/spec/integration/market_data_spec.rb +1 -3
  81. data/spec/integration/orders/attached_spec.rb +8 -10
  82. data/spec/integration/orders/combo_spec.rb +2 -2
  83. data/spec/integration/orders/execution_spec.rb +0 -1
  84. data/spec/integration/orders/placement_spec.rb +1 -3
  85. data/spec/integration/orders/valid_ids_spec.rb +1 -2
  86. data/spec/message_helper.rb +1 -1
  87. data/spec/model_helper.rb +211 -0
  88. data/spec/order_helper.rb +44 -37
  89. data/spec/spec_helper.rb +36 -23
  90. data/spec/v.rb +7 -0
  91. data/tasks/doc.rake +1 -1
  92. metadata +116 -12
  93. data/spec/integration/orders/open_order +0 -98
@@ -0,0 +1,44 @@
1
+ require 'message_helper'
2
+
3
+ # The API can receive frozen market data from Trader Workstation. Frozen market
4
+ # data is the last data recorded in our system. During normal trading hours,
5
+ # the API receives real-time market data. If you use this function, you are
6
+ # telling TWS to automatically switch to frozen market data AFTER the close.
7
+ # Then, before the opening of the next trading day, market data will automatically
8
+ # switch back to real-time market data.
9
+ # :market_data_type = 1 for real-time streaming, 2 for frozen market data
10
+
11
+ describe "Request Market Data Type", :connected => true, :integration => true do
12
+
13
+ before(:all) do
14
+ verify_account
15
+ @ib = IB::Connection.new OPTS[:connection].merge(:logger => mock_logger)
16
+ end
17
+
18
+ after(:all) { close_connection }
19
+
20
+ context "switching to real_time streaming after-hours" do
21
+ before(:all) do
22
+ @ib.send_message :RequestMarketDataType, :market_data_type => :real_time
23
+ @ib.wait_for 2 # sec
24
+ end
25
+
26
+ after(:all) { clean_connection }
27
+
28
+ it 'just works' do
29
+ end
30
+ end
31
+
32
+ context "switching to frozen market data after-hours" do
33
+ before(:all) do
34
+ @ib.send_message :RequestMarketDataType, :market_data_type => :frozen
35
+ @ib.wait_for 2 # sec
36
+ end
37
+
38
+ after(:all) { clean_connection }
39
+
40
+ it 'just works' do
41
+ end
42
+ end
43
+
44
+ end # Request Market Data Type
@@ -0,0 +1,97 @@
1
+ require 'model_helper'
2
+
3
+ describe IB::Models::Contracts::Bag do # AKA IB::Bag
4
+
5
+ let(:props) do
6
+ {:symbol => 'GOOG',
7
+ :exchange => 'SMART',
8
+ :currency => 'USD',
9
+ :legs => [IB::ComboLeg.new(:con_id => 81032967, :weight => 1),
10
+ IB::ComboLeg.new(:con_id => 81032968, :weight => -2),
11
+ IB::ComboLeg.new(:con_id => 81032973, :weight => 1)]
12
+ }
13
+ end
14
+
15
+ let(:human) do
16
+ "<Bag: GOOG SMART USD legs: 81032967|1,81032968|-2,81032973|1 >"
17
+ end
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
+ let(:errors) do
30
+ {:legs => ["legs cannot be empty"],
31
+ }
32
+ end
33
+
34
+ let(:assigns) do
35
+ {:expiry =>
36
+ {[nil, ''] => '',
37
+ [20060913, '20060913', 200609, '200609', :foo, 2006, 42, 'bar'] =>
38
+ /should be blank/},
39
+
40
+ :sec_type =>
41
+ {['BAG', :bag] => :bag,
42
+ IB::CODES[:sec_type].reject { |k, v,| k == :bag }.to_a =>
43
+ /should be a bag/},
44
+
45
+ :right =>
46
+ {['?', :none, '', '0'] => :none,
47
+ ["PUT", :put, "CALL", "C", :call, :foo, 'BAR', 42] =>
48
+ /should be none/},
49
+
50
+ :exchange =>
51
+ {[:cboe, 'cboE', 'CBOE'] => 'CBOE',
52
+ [:smart, 'SMART', 'smArt'] => 'SMART'},
53
+
54
+ :primary_exchange =>
55
+ {[:cboe, 'cboE', 'CBOE'] => 'CBOE',
56
+ [:SMART, 'SMART'] => /should not be SMART/},
57
+
58
+ [:symbol, :local_symbol] =>
59
+ {['AAPL', :AAPL] => 'AAPL'},
60
+
61
+ :multiplier => {['123', 123] => 123},
62
+
63
+ [:under_con_id, :min_tick, :coupon] => {123 => 123}
64
+ }
65
+ end
66
+
67
+ context 'using shortest class name without properties' do
68
+ subject { IB::Bag.new }
69
+ it_behaves_like 'Model instantiated empty'
70
+ end
71
+
72
+ it_behaves_like 'Model'
73
+ it_behaves_like 'Self-equal Model'
74
+
75
+ context 'properly initiated' do
76
+ subject { IB::Bag.new props }
77
+
78
+ it_behaves_like 'Contract'
79
+
80
+ it 'has extra legs_description accessor' do
81
+ subject.legs_description.should == "81032967|1,81032968|-2,81032973|1"
82
+ end
83
+ end
84
+
85
+ it 'correctly defines Contract type (sec_type) for Bag contract' do
86
+ [IB::Contract.new(:sec_type => :bag),
87
+ IB::Contract.new(:sec_type => 'BAG'),
88
+ IB::Bag.new
89
+ ].each do |contract|
90
+ contract.should be_bag
91
+ contract.should_not be_bond
92
+ contract.should_not be_stock
93
+ contract.should_not be_option
94
+ end
95
+ end
96
+
97
+ end # describe IB::Bag
@@ -0,0 +1,45 @@
1
+ require 'model_helper'
2
+
3
+ describe IB::Models::Bar do # AKA IB::Bar
4
+
5
+ let(:props) do
6
+ {:open => 1.31,
7
+ :high => 1.35,
8
+ :low => 1.30,
9
+ :close => 1.33,
10
+ :wap => 1.32,
11
+ :volume => 20000,
12
+ :has_gaps => true,
13
+ :trades => 50,
14
+ :time => "20120312 15:41:09",
15
+ }
16
+ end
17
+
18
+ let(:defaults) do
19
+ {:created_at => Time,
20
+ }
21
+ end
22
+
23
+ let(:errors) do
24
+ {:close => ["is not a number"],
25
+ :high => ["is not a number"],
26
+ :low => ["is not a number"],
27
+ :open => ["is not a number"],
28
+ :volume => ["is not a number"]}
29
+ end
30
+
31
+ let(:assigns) do
32
+ {:has_gaps => {[1, true] => true, [0, false] => false},
33
+
34
+ [:open, :high, :low, :close, :volume] =>
35
+ {[:foo, 'BAR', nil] => /is not a number/}
36
+ }
37
+ end
38
+
39
+ let(:human) do
40
+ "<Bar: 20120312 15:41:09 wap 1.32 OHLC 1.31 1.35 1.3 1.33 trades 50 vol 20000 gaps true>"
41
+ end
42
+
43
+ it_behaves_like 'Model'
44
+
45
+ end # describe IB::Bar
@@ -1,55 +1,71 @@
1
- require 'spec_helper'
1
+ require 'model_helper'
2
2
 
3
3
  describe IB::Models::ComboLeg do
4
4
 
5
- let(:properties) do
6
- {:con_id => 123,
7
- :ratio=> 1234,
8
- :action => 'BUY',
9
- :exchange => 'BLAH',
10
- :open_close => IB::ComboLeg::OPEN,
11
- :short_sale_slot => 1,
12
- :designated_location => 'BLEH',
13
- :exempt_code => 12}
5
+ let(:props) do
6
+ {:con_id => 81032967,
7
+ :ratio => 2,
8
+ :action => :buy,
9
+ :exchange => 'CBOE',
10
+ :open_close => :open,
11
+ :short_sale_slot => :broker,
12
+ :designated_location => nil,
13
+ :exempt_code => -1}
14
14
  end
15
15
 
16
- context "instantiation" do
17
- context 'empty without properties' do
18
- subject { IB::ComboLeg.new }
16
+ let(:human) do
17
+ "<ComboLeg: buy 2 con_id 81032967 at CBOE>"
18
+ end
19
19
 
20
- it { should_not be_nil }
21
- its(:con_id) {should == 0}
22
- its(:open_close) {should == 0}
23
- its(:short_sale_slot) {should == 0}
24
- its(:designated_location) {should == ''}
25
- its(:exempt_code) {should == -1}
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
26
29
 
27
- its(:created_at) {should be_a Time}
28
- end
30
+ let(:errors) do
31
+ {:ratio => ["is not a number"],
32
+ :side => ["should be buy/sell/short"]}
33
+ end
34
+
35
+ 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
+
50
+ :designated_location =>
51
+ {[42, 'FOO', :bar] => /should be blank or orders will be rejected/},
52
+ }
53
+ end
29
54
 
30
- context 'with properties' do
31
- subject { IB::ComboLeg.new properties }
55
+ it_behaves_like 'Model'
56
+ it_behaves_like 'Self-equal Model'
32
57
 
33
- it 'sets properties right' do
34
- properties.each do |name, value|
35
- subject.send(name).should == value
36
- end
37
- end
58
+ context "serialization" do
59
+ subject { IB::ComboLeg.new props }
38
60
 
39
- context 'essential properties are still set, even if not given explicitely' do
40
- its(:created_at) {should be_a Time}
41
- end
61
+ it "serializes short" do
62
+ subject.serialize.should == [81032967, 2, "BUY", "CBOE"]
42
63
  end
43
64
 
44
- it 'allows setting attributes' do
45
- expect {
46
- x = IB::ComboLeg.new
47
- properties.each do |name, value|
48
- subject.send("#{name}=", value)
49
- subject.send(name).should == value
50
- end
51
- }.to_not raise_error
65
+ it "serializes extended" do
66
+ subject.serialize(:extended).should ==
67
+ [81032967, 2, "BUY", "CBOE", 1, 1, nil, -1]
52
68
  end
53
- end #instantiation
69
+ end #serialization
54
70
 
55
71
  end # describe IB::Models::Contract::ComboLeg
@@ -1,216 +1,180 @@
1
- require 'spec_helper'
1
+ require 'model_helper'
2
+ require 'combo_helper'
2
3
 
3
4
  describe IB::Models::Contracts::Contract do # AKA IB::Contract
4
5
 
5
- let(:properties) do
6
- {:symbol => "TEST",
7
- :sec_type => IB::SECURITY_TYPES[:stock],
8
- :expiry => '200609',
9
- :strike => 1234,
10
- :right => "PUT",
11
- :multiplier => 123,
12
- :exchange => "SMART",
13
- :currency => "USD",
14
- :local_symbol => "baz"}
6
+ let(:props) do
7
+ {:symbol => 'AAPL',
8
+ :sec_type => :option,
9
+ :expiry => '201301',
10
+ :strike => 600,
11
+ :right => :put,
12
+ :multiplier => 10,
13
+ :exchange => 'SMART',
14
+ :currency => 'USD',
15
+ :local_symbol => 'AAPL 130119C00500000'}
15
16
  end
16
17
 
17
- context "instantiation" do
18
- context 'using fully qualified class name without properties' do
19
- subject { IB::Models::Contract.new }
20
-
21
- it { should_not be_nil }
22
- its(:con_id) { should == 0 }
23
- its(:strike) { should == 0 }
24
- its(:sec_type) { should be_nil }
25
- its(:created_at) { should be_a Time }
26
- its(:include_expired) { should == false }
27
- end
28
-
29
- context 'using short class name without properties' do
30
- subject { IB::Contract.new }
31
-
32
- it { should_not be_nil }
33
- its(:con_id) { should == 0 }
34
- its(:strike) { should == 0 }
35
- its(:sec_type) { should be_nil }
36
- its(:created_at) { should be_a Time }
37
- its(:include_expired) { should == false }
38
- end
39
-
40
- context 'with properties' do
41
- subject { IB::Contract.new properties }
18
+ let(:human) do
19
+ "<Contract: AAPL option 201301 put 600 SMART USD>"
20
+ end
42
21
 
43
- it 'sets properties right' do
44
- properties.each do |name, value|
45
- subject.send(name).should == value
46
- end
47
- end
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
+ }
34
+ end
48
35
 
49
- context 'essential properties are still set, even if not given explicitely' do
50
- its(:con_id) { should == 0 }
51
- its(:created_at) { should be_a Time }
52
- its(:include_expired) { should == false }
53
- end
54
- end
36
+ let(:errors) do
37
+ {:sec_type => ["should be valid security type"],
38
+ }
39
+ end
55
40
 
56
- context "ContractDetails properties" do
57
- let(:detailed_properties) do
58
- {:under_con_id => 123,
59
- :min_tick=> 1234,
60
- :callable => true,
61
- :puttable => true,
62
- :coupon => 12345,
63
- :convertible => true,
64
- :next_option_partial => true}
65
- end
41
+ let(:assigns) do
42
+ {:expiry =>
43
+ {[200609, '200609'] => '200609',
44
+ [20060913, '20060913'] => '20060913',
45
+ [:foo, 2006, 42, 'bar'] => /should be YYYYMM or YYYYMMDD/},
66
46
 
67
- context 'empty without properties' do
68
- subject { IB::Contract.new }
69
-
70
- its(:summary) { should == subject }
71
- its(:under_con_id) { should == 0 }
72
- its(:min_tick) { should == 0 }
73
- its(:callable) { should == false }
74
- its(:puttable) { should == false }
75
- its(:coupon) { should == 0 }
76
- its(:convertible) { should == false }
77
- its(:next_option_partial) { should == false }
78
- its(:created_at) { should be_a Time }
79
- end
47
+ :sec_type => codes_and_values_for(:sec_type).
48
+ merge([:foo, 'BAR', 42] => /should be valid security type/),
80
49
 
81
- context 'with properties' do
82
- subject { IB::Contract.new detailed_properties }
50
+ :right =>
51
+ {["PUT", "put", "P", "p", :put] => :put,
52
+ ["CALL", "call", "C", "c", :call] => :call,
53
+ ['', '0', '?', :none] => :none,
54
+ [:foo, 'BAR', 42] => /should be put, call or none/},
83
55
 
84
- its(:summary) { should == subject }
85
- its(:created_at) { should be_a Time }
56
+ :exchange =>
57
+ {[:cboe, 'cboE', 'CBOE'] => 'CBOE',
58
+ [:smart, 'SMART', 'smArt'] => 'SMART'},
86
59
 
87
- it 'sets properties right' do
88
- detailed_properties.each do |name, value|
89
- subject.send(name).should == value
90
- end
91
- end
92
- end
93
- end #instantiation
94
-
95
- it 'allows setting attributes' do
96
- expect {
97
- x = IB::Contract.new
98
- properties.each do |name, value|
99
- subject.send("#{name}=", value)
100
- subject.send(name).should == value
101
- end
102
- x.expiry = 200609
103
- x.expiry.should == '200609'
104
- }.to_not raise_error
105
- end
60
+ :primary_exchange =>
61
+ {[:cboe, 'cboE', 'CBOE'] => 'CBOE',
62
+ [:SMART, 'SMART'] => /should not be SMART/},
106
63
 
107
- it 'allows setting ContractDetails attributes' do
108
- x = IB::Contract.new
109
- expect {
110
- x.callable = true
111
- x.puttable = true
112
- x.convertible = true
113
- x.under_con_id = 321
114
- x.min_tick = 123
115
- x.next_option_partial = true
116
- }.to_not raise_error
117
-
118
- x.callable.should == true
119
- x.puttable.should == true
120
- x.convertible.should == true
121
- x.under_con_id.should == 321
122
- x.min_tick.should == 123
123
- x.next_option_partial.should == true
124
- end
64
+ :multiplier => {['123', 123] => 123},
125
65
 
126
- it 'converts multiplier to int' do
127
- expect { @contract = IB::Contract.new(:multiplier => '123') }.to_not raise_error
128
- expect { @contract.multiplier = '123' }.to_not raise_error
129
- @contract.multiplier.should == 123
130
- end
66
+ [:under_con_id, :min_tick, :coupon] => {123 => 123},
131
67
 
132
- it 'raises on wrong security type' do
133
- expect { IB::Contract.new(:sec_type => "asdf") }.to raise_error ArgumentError
68
+ [:callable, :puttable, :convertible, :next_option_partial] =>
69
+ {[1, true] => true, [0, false] => false},
70
+ }
71
+ end
134
72
 
135
- expect { IB::Contract.new.sec_type = "asdf" }.to raise_error ArgumentError
136
- end
73
+ it_behaves_like 'Model'
74
+ it_behaves_like 'Self-equal Model'
137
75
 
138
- it 'accepts pre-determined security types' do
139
- IB::SECURITY_TYPES.values.each do |type|
140
- expect { IB::Contract.new(:sec_type => type) }.to_not raise_error
76
+ context 'testing for Contract type (sec_type)' do
141
77
 
142
- expect { IB::Contract.new.sec_type = type }.to_not raise_error
78
+ it 'correctly defines Contract type (sec_type) for Option contract' do
79
+ [IB::Contract.new(:sec_type => :option),
80
+ IB::Contract.new(:sec_type => 'OPT'),
81
+ IB::Option.new
82
+ ].each do |contract|
83
+ contract.should_not be_bag
84
+ contract.should_not be_bond
85
+ contract.should_not be_stock
86
+ contract.should be_option
143
87
  end
144
88
  end
145
89
 
146
- it 'raises on wrong expiry' do
147
- expect { IB::Contract.new(:expiry => "foo") }.to raise_error ArgumentError
148
-
149
- expect { IB::Contract.new.expiry = "foo" }.to raise_error ArgumentError
90
+ it 'correctly defines Contract type for Bag Contracts' do
91
+ [IB::Contract.new(:sec_type => :bag),
92
+ IB::Contract.new(:sec_type => 'BAG'),
93
+ IB::Bag.new
94
+ ].each do |contract|
95
+ contract.should be_bag
96
+ contract.should_not be_bond
97
+ contract.should_not be_stock
98
+ contract.should_not be_option
99
+ end
150
100
  end
151
101
 
152
- it 'accepts correct expiry' do
153
- expect { IB::Contract.new(:expiry => "200607") }.to_not raise_error
154
-
155
- expect { IB::Contract.new.expiry = "200607" }.to_not raise_error
156
-
157
- expect { IB::Contract.new(:expiry => 200607) }.to_not raise_error
158
-
159
- expect {
160
- x = IB::Contract.new
161
- x.expiry = 200607
162
- x.expiry.should == "200607" # converted to a string
163
- }.to_not raise_error
102
+ it 'correctly defines Contract type for Bag Contracts' do
103
+ [IB::Contract.new(:sec_type => :stock),
104
+ IB::Contract.new(:sec_type => 'STK'),
105
+ ].each do |contract|
106
+ contract.should_not be_bag
107
+ contract.should_not be_bond
108
+ contract.should be_stock
109
+ contract.should_not be_option
110
+ end
164
111
  end
165
112
 
166
- it 'raises on incorrect right (option type)' do
167
- expect { IB::Contract.new(:right => "foo") }.to raise_error ArgumentError
168
- expect { IB::Contract.new.right = "foo" }.to raise_error ArgumentError
113
+ it 'correctly defines Contract type for Bond Contracts' do
114
+ [IB::Contract.new(:sec_type => :bond),
115
+ IB::Contract.new(:sec_type => 'BOND'),
116
+ ].each do |contract|
117
+ contract.should_not be_bag
118
+ contract.should be_bond
119
+ contract.should_not be_stock
120
+ contract.should_not be_option
121
+ end
169
122
  end
170
123
 
171
- it 'accepts all correct values for right (option type)' do
172
- ["PUT", "put", "P", "p"].each do |right|
173
- expect { @contract = IB::Contract.new(:right => right) }.to_not raise_error
174
- @contract.right.should == "PUT"
124
+ end
175
125
 
176
- expect { @contract.right = right }.to_not raise_error
177
- @contract.right.should == "PUT"
178
- end
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
179
132
 
180
- ["CALL", "call", "C", "c"].each do |right|
181
- expect { @contract = IB::Contract.new(:right => right) }.to_not raise_error
182
- @contract.right.should == "CALL"
133
+ context 'using shortest class name without properties' do
134
+ subject { IB::Contract.new }
135
+ it_behaves_like 'Model instantiated empty'
136
+ it_behaves_like 'Self-equal Model'
137
+ it_behaves_like 'Contract'
138
+ end
183
139
 
184
- expect { @contract.right = right }.to_not raise_error
185
- @contract.right.should == "CALL"
186
- end
140
+ context "serialization" do
141
+ before(:all) do
142
+ @ib = IB::Connection.new OPTS[:connection].merge(:logger => mock_logger)
143
+ @ib.wait_for :ManagedAccounts
144
+ @combo = butterfly 'GOOG', '201301', 'CALL', 500, 510, 520
145
+ close_connection
187
146
  end
188
- end #instantiation
189
147
 
190
- context "serialization" do
191
- subject { IB::Contract.new properties }
148
+ subject { IB::Contract.new props }
192
149
 
193
150
  it "serializes long" do
194
151
  subject.serialize_long.should ==
195
- ["TEST", IB::SECURITY_TYPES[:stock], "200609", 1234, "PUT", 123, "SMART", nil, "USD", "baz"]
152
+ ["AAPL", "OPT", "201301", 600, "P", 10, "SMART", nil, "USD", "AAPL 130119C00500000"]
196
153
  end
197
154
 
198
155
  it "serializes short" do
199
156
  subject.serialize_short.should ==
200
- ["TEST", IB::SECURITY_TYPES[:stock], "200609", 1234, "PUT", 123, "SMART", "USD", "baz"]
157
+ ["AAPL", "OPT", "201301", 600, "P", 10, "SMART", "USD", "AAPL 130119C00500000"]
201
158
  end
202
- end #serialization
203
-
204
- context 'equality' do
205
- subject { IB::Contract.new properties }
206
159
 
207
- it 'be self-equal ' do
208
- should == subject
160
+ it "serializes combo (BAG) contracts for Order placement" do
161
+ @combo.serialize_long(:con_id, :sec_id).should ==
162
+ [0, "GOOG", "BAG", nil, 0.0, "", nil, "SMART", nil, "USD", nil, nil, nil]
209
163
  end
210
164
 
211
- it 'be equal to object with the same properties' do
212
- should == IB::Contract.new(properties)
165
+ it 'also serializes attached combo legs' do
166
+ subject.serialize_legs.should == []
167
+ subject.serialize_legs(:extended).should == []
168
+
169
+ @combo.serialize_legs.should ==
170
+ [3, 81032967, 1, "BUY", "SMART", 81032968, 2, "SELL", "SMART", 81032973, 1, "BUY", "SMART"]
171
+
172
+ @combo.serialize_legs(:extended).should ==
173
+ [3, 81032967, 1, "BUY", "SMART", 0, 0, "", -1,
174
+ 81032968, 2, "SELL", "SMART", 0, 0, "", -1,
175
+ 81032973, 1, "BUY", "SMART", 0, 0, "", -1]
213
176
  end
214
- end
177
+ end #serialization
178
+
215
179
 
216
180
  end # describe IB::Contract