ib-ruby 0.7.4 → 0.7.6
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/.gitignore +3 -0
- data/HISTORY +8 -0
- data/README.md +2 -2
- data/Rakefile +15 -0
- data/TODO +7 -2
- data/VERSION +1 -1
- data/bin/account_info +1 -1
- data/bin/cancel_orders +1 -1
- data/bin/contract_details +1 -1
- data/bin/depth_of_market +1 -1
- data/bin/fa_accounts +1 -1
- data/bin/fundamental_data +42 -0
- data/bin/historic_data +1 -1
- data/bin/historic_data_cli +1 -1
- data/bin/list_orders +1 -2
- data/bin/market_data +1 -1
- data/bin/option_data +1 -1
- data/bin/place_combo_order +1 -1
- data/bin/place_order +1 -1
- data/bin/template +1 -4
- data/bin/tick_data +2 -2
- data/bin/time_and_sales +1 -1
- data/lib/ib-ruby.rb +4 -0
- data/lib/ib-ruby/connection.rb +50 -34
- data/lib/ib-ruby/constants.rb +232 -37
- data/lib/ib-ruby/db.rb +25 -0
- data/lib/ib-ruby/extensions.rb +51 -1
- data/lib/ib-ruby/messages/abstract_message.rb +0 -8
- data/lib/ib-ruby/messages/incoming.rb +18 -493
- data/lib/ib-ruby/messages/incoming/abstract_message.rb +100 -0
- data/lib/ib-ruby/messages/incoming/alert.rb +34 -0
- data/lib/ib-ruby/messages/incoming/contract_data.rb +82 -0
- data/lib/ib-ruby/messages/incoming/delta_neutral_validation.rb +20 -0
- data/lib/ib-ruby/messages/incoming/execution_data.rb +59 -0
- data/lib/ib-ruby/messages/incoming/historical_data.rb +55 -0
- data/lib/ib-ruby/messages/incoming/market_depths.rb +44 -0
- data/lib/ib-ruby/messages/incoming/open_order.rb +32 -16
- data/lib/ib-ruby/messages/incoming/order_status.rb +67 -0
- data/lib/ib-ruby/messages/incoming/portfolio_value.rb +39 -0
- data/lib/ib-ruby/messages/incoming/real_time_bar.rb +32 -0
- data/lib/ib-ruby/messages/incoming/scanner_data.rb +49 -0
- data/lib/ib-ruby/messages/outgoing.rb +25 -223
- data/lib/ib-ruby/messages/outgoing/abstract_message.rb +61 -0
- data/lib/ib-ruby/messages/outgoing/bar_requests.rb +149 -0
- data/lib/ib-ruby/messages/outgoing/place_order.rb +24 -0
- data/lib/ib-ruby/models.rb +4 -0
- data/lib/ib-ruby/models/bar.rb +31 -14
- data/lib/ib-ruby/models/combo_leg.rb +48 -23
- data/lib/ib-ruby/models/contracts.rb +2 -2
- data/lib/ib-ruby/models/contracts/bag.rb +11 -7
- data/lib/ib-ruby/models/contracts/contract.rb +90 -66
- data/lib/ib-ruby/models/contracts/option.rb +16 -7
- data/lib/ib-ruby/models/execution.rb +34 -18
- data/lib/ib-ruby/models/model.rb +15 -7
- data/lib/ib-ruby/models/model_properties.rb +101 -44
- data/lib/ib-ruby/models/order.rb +176 -187
- data/lib/ib-ruby/models/order_state.rb +99 -0
- data/lib/ib-ruby/symbols/forex.rb +10 -10
- data/lib/ib-ruby/symbols/futures.rb +6 -6
- data/lib/ib-ruby/symbols/stocks.rb +3 -3
- data/spec/account_helper.rb +4 -5
- data/spec/combo_helper.rb +4 -4
- data/spec/db.rb +18 -0
- data/spec/ib-ruby/messages/{incoming_spec.rb → incoming/alert_spec.rb} +1 -0
- data/spec/ib-ruby/messages/incoming/open_order_spec.rb +100 -0
- data/spec/ib-ruby/messages/incoming/order_status_spec.rb +74 -0
- data/spec/ib-ruby/messages/{outgoing_spec.rb → outgoing/account_data_spec.rb} +0 -0
- data/spec/ib-ruby/messages/outgoing/market_data_type_spec.rb +44 -0
- data/spec/ib-ruby/models/bag_spec.rb +97 -0
- data/spec/ib-ruby/models/bar_spec.rb +45 -0
- data/spec/ib-ruby/models/combo_leg_spec.rb +56 -40
- data/spec/ib-ruby/models/contract_spec.rb +134 -170
- data/spec/ib-ruby/models/execution_spec.rb +35 -50
- data/spec/ib-ruby/models/option_spec.rb +127 -0
- data/spec/ib-ruby/models/order_spec.rb +89 -68
- data/spec/ib-ruby/models/order_state_spec.rb +55 -0
- data/spec/integration/contract_info_spec.rb +4 -6
- data/spec/integration/fundamental_data_spec.rb +41 -0
- data/spec/integration/historic_data_spec.rb +4 -4
- data/spec/integration/market_data_spec.rb +1 -3
- data/spec/integration/orders/attached_spec.rb +8 -10
- data/spec/integration/orders/combo_spec.rb +2 -2
- data/spec/integration/orders/execution_spec.rb +0 -1
- data/spec/integration/orders/placement_spec.rb +1 -3
- data/spec/integration/orders/valid_ids_spec.rb +1 -2
- data/spec/message_helper.rb +1 -1
- data/spec/model_helper.rb +211 -0
- data/spec/order_helper.rb +44 -37
- data/spec/spec_helper.rb +36 -23
- data/spec/v.rb +7 -0
- data/tasks/doc.rake +1 -1
- metadata +116 -12
- data/spec/integration/orders/open_order +0 -98
File without changes
|
@@ -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 '
|
1
|
+
require 'model_helper'
|
2
2
|
|
3
3
|
describe IB::Models::ComboLeg do
|
4
4
|
|
5
|
-
let(:
|
6
|
-
{:con_id =>
|
7
|
-
:ratio=>
|
8
|
-
:action =>
|
9
|
-
:exchange => '
|
10
|
-
:open_close =>
|
11
|
-
:short_sale_slot =>
|
12
|
-
:designated_location =>
|
13
|
-
:exempt_code =>
|
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
|
-
|
17
|
-
|
18
|
-
|
16
|
+
let(:human) do
|
17
|
+
"<ComboLeg: buy 2 con_id 81032967 at CBOE>"
|
18
|
+
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
28
|
-
|
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
|
-
|
31
|
-
|
55
|
+
it_behaves_like 'Model'
|
56
|
+
it_behaves_like 'Self-equal Model'
|
32
57
|
|
33
|
-
|
34
|
-
|
35
|
-
subject.send(name).should == value
|
36
|
-
end
|
37
|
-
end
|
58
|
+
context "serialization" do
|
59
|
+
subject { IB::ComboLeg.new props }
|
38
60
|
|
39
|
-
|
40
|
-
|
41
|
-
end
|
61
|
+
it "serializes short" do
|
62
|
+
subject.serialize.should == [81032967, 2, "BUY", "CBOE"]
|
42
63
|
end
|
43
64
|
|
44
|
-
it
|
45
|
-
|
46
|
-
|
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 #
|
69
|
+
end #serialization
|
54
70
|
|
55
71
|
end # describe IB::Models::Contract::ComboLeg
|
@@ -1,216 +1,180 @@
|
|
1
|
-
require '
|
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(:
|
6
|
-
{:symbol =>
|
7
|
-
:sec_type =>
|
8
|
-
:expiry => '
|
9
|
-
:strike =>
|
10
|
-
:right =>
|
11
|
-
:multiplier =>
|
12
|
-
:exchange =>
|
13
|
-
:currency =>
|
14
|
-
:local_symbol =>
|
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
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
end
|
54
|
-
end
|
36
|
+
let(:errors) do
|
37
|
+
{:sec_type => ["should be valid security type"],
|
38
|
+
}
|
39
|
+
end
|
55
40
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
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
|
-
|
68
|
-
|
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
|
-
|
82
|
-
|
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
|
-
|
85
|
-
|
56
|
+
:exchange =>
|
57
|
+
{[:cboe, 'cboE', 'CBOE'] => 'CBOE',
|
58
|
+
[:smart, 'SMART', 'smArt'] => 'SMART'},
|
86
59
|
|
87
|
-
|
88
|
-
|
89
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
133
|
-
|
68
|
+
[:callable, :puttable, :convertible, :next_option_partial] =>
|
69
|
+
{[1, true] => true, [0, false] => false},
|
70
|
+
}
|
71
|
+
end
|
134
72
|
|
135
|
-
|
136
|
-
|
73
|
+
it_behaves_like 'Model'
|
74
|
+
it_behaves_like 'Self-equal Model'
|
137
75
|
|
138
|
-
|
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
|
-
|
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 '
|
147
|
-
|
148
|
-
|
149
|
-
|
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 '
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
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 '
|
167
|
-
|
168
|
-
|
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
|
-
|
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
|
-
|
177
|
-
|
178
|
-
|
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
|
-
|
181
|
-
|
182
|
-
|
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
|
-
|
185
|
-
|
186
|
-
|
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
|
-
|
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
|
-
["
|
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
|
-
["
|
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
|
208
|
-
should ==
|
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 '
|
212
|
-
should ==
|
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
|