ib-ruby 0.7.6 → 0.7.8
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/HISTORY +8 -0
- data/Rakefile +8 -0
- data/VERSION +1 -1
- data/bin/fundamental_data +6 -9
- data/lib/ib-ruby/connection.rb +16 -19
- data/lib/ib-ruby/constants.rb +3 -1
- data/lib/ib-ruby/extensions.rb +5 -0
- data/lib/ib-ruby/messages/incoming/contract_data.rb +46 -45
- data/lib/ib-ruby/messages/incoming/delta_neutral_validation.rb +8 -5
- data/lib/ib-ruby/messages/incoming/execution_data.rb +2 -2
- data/lib/ib-ruby/messages/incoming/next_valid_id.rb +18 -0
- data/lib/ib-ruby/messages/incoming/open_order.rb +23 -16
- data/lib/ib-ruby/messages/incoming/order_status.rb +5 -3
- data/lib/ib-ruby/messages/incoming/scanner_data.rb +15 -11
- data/lib/ib-ruby/messages/incoming.rb +1 -5
- data/lib/ib-ruby/messages/outgoing/abstract_message.rb +2 -1
- data/lib/ib-ruby/messages/outgoing/place_order.rb +1 -1
- data/lib/ib-ruby/messages/outgoing.rb +1 -1
- data/lib/ib-ruby/models/bag.rb +59 -0
- data/lib/ib-ruby/models/combo_leg.rb +10 -6
- data/lib/ib-ruby/models/contract.rb +278 -0
- data/lib/ib-ruby/models/contract_detail.rb +70 -0
- data/lib/ib-ruby/models/execution.rb +22 -16
- data/lib/ib-ruby/models/model.rb +75 -17
- data/lib/ib-ruby/models/model_properties.rb +40 -26
- data/lib/ib-ruby/models/option.rb +62 -0
- data/lib/ib-ruby/models/order.rb +122 -86
- data/lib/ib-ruby/models/order_state.rb +11 -12
- data/lib/ib-ruby/models/underlying.rb +36 -0
- data/lib/ib-ruby/models.rb +1 -4
- data/spec/account_helper.rb +2 -1
- data/spec/db.rb +1 -1
- data/spec/db_helper.rb +105 -0
- data/spec/ib-ruby/connection_spec.rb +3 -3
- data/spec/ib-ruby/messages/incoming/open_order_spec.rb +5 -5
- data/spec/ib-ruby/messages/incoming/order_status_spec.rb +3 -3
- data/spec/ib-ruby/models/bag_spec.rb +15 -23
- data/spec/ib-ruby/models/bar_spec.rb +0 -5
- data/spec/ib-ruby/models/combo_leg_spec.rb +18 -25
- data/spec/ib-ruby/models/contract_detail_spec.rb +54 -0
- data/spec/ib-ruby/models/contract_spec.rb +25 -37
- data/spec/ib-ruby/models/execution_spec.rb +64 -19
- data/spec/ib-ruby/models/option_spec.rb +12 -34
- data/spec/ib-ruby/models/order_spec.rb +107 -45
- data/spec/ib-ruby/models/order_state_spec.rb +12 -12
- data/spec/ib-ruby/models/underlying_spec.rb +36 -0
- data/spec/integration/contract_info_spec.rb +65 -55
- data/spec/integration/fundamental_data_spec.rb +2 -2
- data/spec/integration/orders/attached_spec.rb +3 -3
- data/spec/integration/orders/combo_spec.rb +3 -3
- data/spec/integration/orders/placement_spec.rb +8 -8
- data/spec/integration/orders/{execution_spec.rb → trades_spec.rb} +8 -12
- data/spec/integration/orders/valid_ids_spec.rb +3 -3
- data/spec/message_helper.rb +1 -1
- data/spec/model_helper.rb +150 -85
- data/spec/order_helper.rb +35 -18
- metadata +18 -10
- data/lib/ib-ruby/models/contracts/bag.rb +0 -62
- data/lib/ib-ruby/models/contracts/contract.rb +0 -320
- data/lib/ib-ruby/models/contracts/option.rb +0 -66
- 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(:
|
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.
|
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.
|
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
|
-
{:
|
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
|
-
{:
|
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(:
|
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.
|
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
|
-
{:
|
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::
|
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,
|
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
|
-
|
52
|
-
[:smart, 'SMART', 'smArt'] => 'SMART'},
|
40
|
+
:exchange => string_upcase_assigns.merge(
|
41
|
+
[:smart, 'SMART', 'smArt'] => 'SMART'),
|
53
42
|
|
54
|
-
:primary_exchange =>
|
55
|
-
|
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 =>
|
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'
|
@@ -5,7 +5,7 @@ describe IB::Models::ComboLeg do
|
|
5
5
|
let(:props) do
|
6
6
|
{:con_id => 81032967,
|
7
7
|
:ratio => 2,
|
8
|
-
:
|
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
|
-
|
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::
|
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
|
-
|
58
|
-
[:smart, 'SMART', 'smArt'] => 'SMART'},
|
50
|
+
:exchange => string_upcase_assigns.merge(
|
51
|
+
[:smart, 'SMART', 'smArt'] => 'SMART'),
|
59
52
|
|
60
|
-
:primary_exchange =>
|
61
|
-
|
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 =>
|
56
|
+
:multiplier => to_i_assigns,
|
65
57
|
|
66
|
-
|
58
|
+
:strike => to_f_assigns,
|
67
59
|
|
68
|
-
|
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",
|
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",
|
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
|
-
:
|
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
|
-
{:
|
46
|
-
|
47
|
-
|
34
|
+
{[:perm_id, :client_id, :cumulative_quantity, :price, :average_price] => numeric_assigns,
|
35
|
+
:liquidation => boolean_assigns,
|
36
|
+
}
|
37
|
+
end
|
48
38
|
|
49
|
-
|
50
|
-
|
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
|
-
|
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::
|
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,
|
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
|
-
|
51
|
-
[:smart, 'SMART', 'smArt'] => 'SMART'},
|
39
|
+
:exchange => string_upcase_assigns.merge(
|
40
|
+
[:smart, 'SMART', 'smArt'] => 'SMART'),
|
52
41
|
|
53
|
-
:primary_exchange =>
|
54
|
-
|
55
|
-
[:SMART, 'SMART'] => /should not be SMART/},
|
42
|
+
:primary_exchange =>string_upcase_assigns.merge(
|
43
|
+
[:SMART, 'SMART'] => /should not be SMART/),
|
56
44
|
|
57
|
-
:
|
58
|
-
|
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'
|