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.
- 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'
|