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
@@ -0,0 +1,99 @@
|
|
1
|
+
module IB
|
2
|
+
module Models
|
3
|
+
|
4
|
+
# OrderState represents dynamic (changeable) info about a single Order,
|
5
|
+
# isolating these changes and making Order essentially immutable
|
6
|
+
class OrderState < Model.for(:order_state)
|
7
|
+
include ModelProperties
|
8
|
+
|
9
|
+
#p column_names
|
10
|
+
# has_one :order
|
11
|
+
|
12
|
+
# Properties arriving via OpenOrder message
|
13
|
+
prop :init_margin, # Float: The impact the order would have on your initial margin.
|
14
|
+
:maint_margin, # Float: The impact the order would have on your maintenance margin.
|
15
|
+
:equity_with_loan, # Float: The impact the order would have on your equity
|
16
|
+
:commission, # double: Shows the commission amount on the order.
|
17
|
+
:min_commission, # The possible min range of the actual order commission.
|
18
|
+
:max_commission, # The possible max range of the actual order commission.
|
19
|
+
:commission_currency, # String: Shows the currency of the commission.
|
20
|
+
:warning_text # String: Displays a warning message if warranted.
|
21
|
+
|
22
|
+
# Properties arriving via OrderStatus message:
|
23
|
+
prop :filled, # int
|
24
|
+
:remaining, # int
|
25
|
+
:average_fill_price, # double
|
26
|
+
:last_fill_price, # double
|
27
|
+
:why_held # String: comma-separated list of reasons for order to be held.
|
28
|
+
|
29
|
+
# Properties arriving in both messages:
|
30
|
+
prop :order_id, # int: Order id associated with client (volatile).
|
31
|
+
:perm_id, # int: TWS permanent id, remains the same over TWS sessions.
|
32
|
+
:client_id, # int: The id of the client that placed this order.
|
33
|
+
:parent_id, # int: The order ID of the parent (original) order, used
|
34
|
+
:status # String: Displays the order status. Possible values include:
|
35
|
+
# - PendingSubmit - indicates that you have transmitted the order, but
|
36
|
+
# have not yet received confirmation that it has been accepted by the
|
37
|
+
# order destination. NOTE: This order status is NOT sent back by TWS
|
38
|
+
# and should be explicitly set by YOU when an order is submitted.
|
39
|
+
# - PendingCancel - indicates that you have sent a request to cancel
|
40
|
+
# the order but have not yet received cancel confirmation from the
|
41
|
+
# order destination. At this point, your order cancel is not confirmed.
|
42
|
+
# You may still receive an execution while your cancellation request
|
43
|
+
# is pending. NOTE: This order status is not sent back by TWS and
|
44
|
+
# should be explicitly set by YOU when an order is canceled.
|
45
|
+
# - PreSubmitted - indicates that a simulated order type has been
|
46
|
+
# accepted by the IB system and that this order has yet to be elected.
|
47
|
+
# The order is held in the IB system until the election criteria are
|
48
|
+
# met. At that time the order is transmitted to the order destination
|
49
|
+
# as specified.
|
50
|
+
# - Submitted - indicates that your order has been accepted at the order
|
51
|
+
# destination and is working.
|
52
|
+
# - Cancelled - indicates that the balance of your order has been
|
53
|
+
# confirmed canceled by the IB system. This could occur unexpectedly
|
54
|
+
# when IB or the destination has rejected your order.
|
55
|
+
# - ApiCancelled - canceled via API
|
56
|
+
# - Filled - indicates that the order has been completely filled.
|
57
|
+
# - Inactive - indicates that the order has been accepted by the system
|
58
|
+
# (simulated orders) or an exchange (native orders) but that currently
|
59
|
+
# the order is inactive due to system, exchange or other issues.
|
60
|
+
|
61
|
+
prop :tester
|
62
|
+
|
63
|
+
validates_numericality_of :order_id, :perm_id, :client_id, :only_integer => true
|
64
|
+
|
65
|
+
DEFAULT_PROPS = {:status => 'New'} # Starting new Orders with this status
|
66
|
+
|
67
|
+
# Comparison
|
68
|
+
def == other
|
69
|
+
other && other.is_a?(OrderState) &&
|
70
|
+
status == other.status &&
|
71
|
+
order_id == other.order_id &&
|
72
|
+
perm_id == other.perm_id &&
|
73
|
+
client_id == other.client_id &&
|
74
|
+
filled == other.filled &&
|
75
|
+
remaining == other.remaining &&
|
76
|
+
last_fill_price == other.last_fill_price &&
|
77
|
+
init_margin == other.init_margin &&
|
78
|
+
maint_margin == other.maint_margin &&
|
79
|
+
equity_with_loan == other.equity_with_loan &&
|
80
|
+
why_held == other.why_held &&
|
81
|
+
warning_text == other.warning_text &&
|
82
|
+
commission == other.commission
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_human
|
86
|
+
"<OrderState: #{status} ##{order_id}/#{perm_id} from #{client_id}" +
|
87
|
+
(filled ? " filled #{filled}/#{remaining}" : '') +
|
88
|
+
(last_fill_price ? " at #{last_fill_price}/#{average_fill_price}" : '') +
|
89
|
+
(init_margin ? " margin #{init_margin}/#{maint_margin}" : '') +
|
90
|
+
(equity_with_loan ? " equity #{equity_with_loan}" : '') +
|
91
|
+
(commission && commission > 0 ? " fee #{commission}" : "") +
|
92
|
+
(why_held ? " why_held #{why_held}" : '') +
|
93
|
+
((warning_text && warning_text != '') ? " warning #{warning_text}" : '') + ">"
|
94
|
+
end
|
95
|
+
|
96
|
+
alias to_s to_human
|
97
|
+
end # class Order
|
98
|
+
end # module Models
|
99
|
+
end # module IB
|
@@ -10,61 +10,61 @@ module IB
|
|
10
10
|
:audusd => IB::Contract.new(:symbol => "AUD",
|
11
11
|
:exchange => "IDEALPRO",
|
12
12
|
:currency => "USD",
|
13
|
-
:sec_type =>
|
13
|
+
:sec_type => :forex,
|
14
14
|
:description => "AUDUSD"),
|
15
15
|
|
16
16
|
:gbpusd => IB::Contract.new(:symbol => "GBP",
|
17
17
|
:exchange => "IDEALPRO",
|
18
18
|
:currency => "USD",
|
19
|
-
:sec_type =>
|
19
|
+
:sec_type => :forex,
|
20
20
|
:description => "GBPUSD"),
|
21
21
|
|
22
22
|
:euraud => IB::Contract.new(:symbol => "EUR",
|
23
23
|
:exchange => "IDEALPRO",
|
24
24
|
:currency => "AUD",
|
25
|
-
:sec_type =>
|
25
|
+
:sec_type => :forex,
|
26
26
|
:description => "EURAUD"),
|
27
27
|
|
28
28
|
:eurgbp => IB::Contract.new(:symbol => "EUR",
|
29
29
|
:exchange => "IDEALPRO",
|
30
30
|
:currency => "GBP",
|
31
|
-
:sec_type =>
|
31
|
+
:sec_type => :forex,
|
32
32
|
:description => "EURGBP"),
|
33
33
|
|
34
34
|
:eurjpy => IB::Contract.new(:symbol => "EUR",
|
35
35
|
:exchange => "IDEALPRO",
|
36
36
|
:currency => "JPY",
|
37
|
-
:sec_type =>
|
37
|
+
:sec_type => :forex,
|
38
38
|
:description => "EURJPY"),
|
39
39
|
|
40
40
|
:eurusd => IB::Contract.new(:symbol => "EUR",
|
41
41
|
:exchange => "IDEALPRO",
|
42
42
|
:currency => "USD",
|
43
|
-
:sec_type =>
|
43
|
+
:sec_type => :forex,
|
44
44
|
:description => "EURUSD"),
|
45
45
|
|
46
46
|
:eurcad => IB::Contract.new(:symbol => "EUR",
|
47
47
|
:exchange => "IDEALPRO",
|
48
48
|
:currency => "CAD",
|
49
|
-
:sec_type =>
|
49
|
+
:sec_type => :forex,
|
50
50
|
:description => "EURCAD"),
|
51
51
|
|
52
52
|
:usdchf => IB::Contract.new(:symbol => "USD",
|
53
53
|
:exchange => "IDEALPRO",
|
54
54
|
:currency => "CHF",
|
55
|
-
:sec_type =>
|
55
|
+
:sec_type => :forex,
|
56
56
|
:description => "USDCHF"),
|
57
57
|
|
58
58
|
:usdcad => IB::Contract.new(:symbol => "USD",
|
59
59
|
:exchange => "IDEALPRO",
|
60
60
|
:currency => "CAD",
|
61
|
-
:sec_type =>
|
61
|
+
:sec_type => :forex,
|
62
62
|
:description => "USDCAD"),
|
63
63
|
|
64
64
|
:usdjpy => IB::Contract.new(:symbol => "USD",
|
65
65
|
:exchange => "IDEALPRO",
|
66
66
|
:currency => "JPY",
|
67
|
-
:sec_type =>
|
67
|
+
:sec_type => :forex,
|
68
68
|
:description => "USDJPY")
|
69
69
|
}
|
70
70
|
end
|
@@ -66,14 +66,14 @@ module IB
|
|
66
66
|
:expiry => next_expiry,
|
67
67
|
:exchange => "ECBOT",
|
68
68
|
:currency => "USD",
|
69
|
-
:sec_type =>
|
69
|
+
:sec_type => :future,
|
70
70
|
:description => "Mini Dow Jones Industrial"),
|
71
71
|
|
72
72
|
:es => IB::Contract.new(:symbol => "ES",
|
73
73
|
:expiry => next_expiry,
|
74
74
|
:exchange => "GLOBEX",
|
75
75
|
:currency => "USD",
|
76
|
-
:sec_type =>
|
76
|
+
:sec_type => :future,
|
77
77
|
:multiplier => 50,
|
78
78
|
:description => "E-Mini S&P 500"),
|
79
79
|
|
@@ -81,7 +81,7 @@ module IB
|
|
81
81
|
:expiry => next_expiry,
|
82
82
|
:exchange => "GLOBEX",
|
83
83
|
:currency => "USD",
|
84
|
-
:sec_type =>
|
84
|
+
:sec_type => :future,
|
85
85
|
:multiplier => 62500,
|
86
86
|
:description => "British Pounds"),
|
87
87
|
|
@@ -89,7 +89,7 @@ module IB
|
|
89
89
|
:expiry => next_expiry,
|
90
90
|
:exchange => "GLOBEX",
|
91
91
|
:currency => "USD",
|
92
|
-
:sec_type =>
|
92
|
+
:sec_type => :future,
|
93
93
|
:multiplier => 12500,
|
94
94
|
:description => "Euro FX"),
|
95
95
|
|
@@ -97,7 +97,7 @@ module IB
|
|
97
97
|
:expiry => next_expiry,
|
98
98
|
:exchange => "GLOBEX",
|
99
99
|
:currency => "USD",
|
100
|
-
:sec_type =>
|
100
|
+
:sec_type => :future,
|
101
101
|
:multiplier => 12500000,
|
102
102
|
:description => "Japanese Yen"),
|
103
103
|
|
@@ -105,7 +105,7 @@ module IB
|
|
105
105
|
:expiry => next_expiry,
|
106
106
|
:exchange => "HKFE",
|
107
107
|
:currency => "HKD",
|
108
|
-
:sec_type =>
|
108
|
+
:sec_type => :future,
|
109
109
|
:multiplier => 50,
|
110
110
|
:description => "Hang Seng Index")
|
111
111
|
}
|
@@ -11,18 +11,18 @@ module IB
|
|
11
11
|
{:wfc => IB::Contract.new(:symbol => "WFC",
|
12
12
|
:exchange => "NYSE",
|
13
13
|
:currency => "USD",
|
14
|
-
:sec_type =>
|
14
|
+
:sec_type => :stock,
|
15
15
|
:description => "Wells Fargo"),
|
16
16
|
|
17
17
|
:aapl => IB::Contract.new(:symbol => "AAPL",
|
18
18
|
:currency => "USD",
|
19
|
-
:sec_type =>
|
19
|
+
:sec_type => :stock,
|
20
20
|
:description => "Apple Inc."),
|
21
21
|
|
22
22
|
:wrong => IB::Contract.new(:symbol => "QEEUUE",
|
23
23
|
:exchange => "NYSE",
|
24
24
|
:currency => "USD",
|
25
|
-
:sec_type =>
|
25
|
+
:sec_type => :stock,
|
26
26
|
:description => "Non-existent stock"),
|
27
27
|
}
|
28
28
|
end
|
data/spec/account_helper.rb
CHANGED
@@ -14,13 +14,12 @@ def verify_account
|
|
14
14
|
raise "Please configure IB PAPER ACCOUNT in spec/spec_helper.rb" unless account
|
15
15
|
|
16
16
|
@ib = IB::Connection.new OPTS[:connection].merge(:logger => mock_logger)
|
17
|
-
@ib.send_message :RequestAccountData, :subscribe => true
|
18
17
|
|
19
|
-
@ib.wait_for :
|
20
|
-
@ib.
|
21
|
-
raise "Unable to verify IB PAPER ACCOUNT" unless @ib.received?(:
|
18
|
+
@ib.wait_for :ManagedAccounts, 5
|
19
|
+
puts @ib.received.map { |type, msg| [" #{type}:", msg.map(&:to_human)] }
|
20
|
+
raise "Unable to verify IB PAPER ACCOUNT" unless @ib.received?(:ManagedAccounts)
|
22
21
|
|
23
|
-
received = @ib.received[:
|
22
|
+
received = @ib.received[:ManagedAccounts].first.accounts_list
|
24
23
|
raise "Connected to wrong account #{received}, expected #{account}" if account != received
|
25
24
|
|
26
25
|
close_connection
|
data/spec/combo_helper.rb
CHANGED
@@ -2,16 +2,16 @@ require 'integration_helper'
|
|
2
2
|
|
3
3
|
# Define butterfly
|
4
4
|
def butterfly symbol, expiry, right, *strikes
|
5
|
-
unless @ib && @ib.connected?
|
6
|
-
@ib = IB::Connection.new OPTS[:connection].merge(:logger => mock_logger)
|
7
|
-
end
|
5
|
+
raise 'Unable to create butterfly, no connection' unless @ib && @ib.connected?
|
8
6
|
|
9
7
|
legs = strikes.zip([1, -2, 1]).map do |strike, weight|
|
8
|
+
|
10
9
|
# Create contract
|
11
10
|
contract = IB::Option.new :symbol => symbol,
|
12
11
|
:expiry => expiry,
|
13
12
|
:right => right,
|
14
13
|
:strike => strike
|
14
|
+
|
15
15
|
# Find out contract's con_id
|
16
16
|
@ib.clear_received :ContractData, :ContractDataEnd
|
17
17
|
@ib.send_message :RequestContractData, :id => strike, :contract => contract
|
@@ -22,7 +22,7 @@ def butterfly symbol, expiry, right, *strikes
|
|
22
22
|
IB::ComboLeg.new :con_id => con_id, :weight => weight
|
23
23
|
end
|
24
24
|
|
25
|
-
#
|
25
|
+
# Return butterfly Combo
|
26
26
|
IB::Bag.new :symbol => symbol,
|
27
27
|
:currency => "USD", # Only US options in combo Contracts
|
28
28
|
:exchange => "SMART",
|
data/spec/db.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
puts 'To run specs with database backend (ActiveRecord), use:'
|
2
|
+
puts '$ rspec -rdb spec'
|
3
|
+
|
4
|
+
require 'yaml'
|
5
|
+
require 'pathname'
|
6
|
+
require 'ib-ruby/db'
|
7
|
+
require 'database_cleaner'
|
8
|
+
|
9
|
+
# Load DB config, determine correct environment
|
10
|
+
db_file = Pathname.new(__FILE__).realpath.dirname + '../db/config.yml'
|
11
|
+
raise "Unable to find DB config file: #{db_file}" unless db_file.exist?
|
12
|
+
|
13
|
+
env = RUBY_PLATFORM =~ /java/ ? 'test-jruby' : 'test'
|
14
|
+
db_config = YAML::load_file(db_file)[env]
|
15
|
+
|
16
|
+
# Establish connection to test DB
|
17
|
+
IB::DB.connect db_config
|
18
|
+
|
@@ -39,6 +39,7 @@ describe IB::Messages::Incoming do
|
|
39
39
|
before(:all) do
|
40
40
|
@ib = IB::Connection.new OPTS[:connection].merge(:logger => mock_logger)
|
41
41
|
@ib.wait_for :Alert
|
42
|
+
pending 'No Alert received upon connect!' unless @ib.received? :Alert
|
42
43
|
end
|
43
44
|
|
44
45
|
after(:all) { close_connection }
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'order_helper'
|
2
|
+
|
3
|
+
shared_examples_for 'OpenOrder message' do
|
4
|
+
it { should be_an IB::Messages::Incoming::OpenOrder }
|
5
|
+
its(:message_type) { should == :OpenOrder }
|
6
|
+
its(:message_id) { should == 5 }
|
7
|
+
its(:version) { should == 28 }
|
8
|
+
its(:data) { should_not be_empty }
|
9
|
+
its(:order_id) { should be_an Integer }
|
10
|
+
its(:status) { should =~ /Submit/ }
|
11
|
+
its(:to_human) { should =~
|
12
|
+
/<OpenOrder: <Contract: WFC stock NYSE USD> <Order: LMT DAY buy 100 .*Submit.* 9.13 #\d+\/\d+ from 1111/ }
|
13
|
+
|
14
|
+
it 'has proper contract accessor' do
|
15
|
+
c = subject.contract
|
16
|
+
c.should be_an IB::Contract
|
17
|
+
c.symbol.should == 'WFC'
|
18
|
+
c.exchange.should == 'NYSE'
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'has proper order accessor' do
|
22
|
+
o = subject.order
|
23
|
+
o.should be_an IB::Order
|
24
|
+
o.client_id.should == 1111
|
25
|
+
o.parent_id.should == 0
|
26
|
+
o.order_id.should be_an Integer
|
27
|
+
o.perm_id.should be_an Integer
|
28
|
+
o.order_type.should == :limit
|
29
|
+
o.tif.should == :day
|
30
|
+
o.status.should =~ /Submit/
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'has proper order_state accessor' do
|
34
|
+
os = subject.order_state
|
35
|
+
os.order_id.should be_an Integer
|
36
|
+
os.perm_id.should be_an Integer
|
37
|
+
os.client_id.should == 1111
|
38
|
+
os.parent_id.should == 0
|
39
|
+
os.status.should =~ /Submit/
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'has class accessors as well' do
|
43
|
+
subject.class.message_id.should == 5
|
44
|
+
subject.class.version.should == [23, 28] # Two message versions supported
|
45
|
+
subject.class.message_type.should == :OpenOrder
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
describe IB::Messages::Incoming::OpenOrder do
|
51
|
+
|
52
|
+
context 'Instantiated with data Hash' do
|
53
|
+
subject do
|
54
|
+
IB::Messages::Incoming::OpenOrder.new :version => 28,
|
55
|
+
:order =>
|
56
|
+
{:order_id => 1313,
|
57
|
+
:perm_id => 172323928,
|
58
|
+
:client_id => 1111,
|
59
|
+
:parent_id => 0,
|
60
|
+
:side => :buy,
|
61
|
+
:order_type => :limit,
|
62
|
+
:limit_price => 9.13,
|
63
|
+
:total_quantity => 100,
|
64
|
+
},
|
65
|
+
:order_state =>
|
66
|
+
{:order_id => 1313,
|
67
|
+
:perm_id => 172323928,
|
68
|
+
:client_id => 1111,
|
69
|
+
:parent_id => 0,
|
70
|
+
:status => 'PreSubmitted',
|
71
|
+
},
|
72
|
+
:contract =>
|
73
|
+
{:symbol => 'WFC',
|
74
|
+
:exchange => 'NYSE',
|
75
|
+
:currency => 'USD',
|
76
|
+
:sec_type => :stock
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
it_behaves_like 'OpenOrder message'
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'received from IB' do
|
84
|
+
before(:all) do
|
85
|
+
verify_account
|
86
|
+
@ib = IB::Connection.new OPTS[:connection].merge(:logger => mock_logger)
|
87
|
+
@ib.wait_for :NextValidId
|
88
|
+
place_order IB::Symbols::Stocks[:wfc]
|
89
|
+
@ib.wait_for :OpenOrder
|
90
|
+
end
|
91
|
+
|
92
|
+
after(:all) { close_connection } # implicitly cancels order
|
93
|
+
|
94
|
+
subject { @ib.received[:OpenOrder].first }
|
95
|
+
|
96
|
+
it_behaves_like 'OpenOrder message'
|
97
|
+
|
98
|
+
#it 'has extended order_state attributes' do
|
99
|
+
end
|
100
|
+
end # describe IB::Messages:Incoming
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'order_helper'
|
2
|
+
|
3
|
+
shared_examples_for 'OrderStatus message' do
|
4
|
+
it { should be_an IB::Messages::Incoming::OrderStatus }
|
5
|
+
its(:message_type) { should == :OrderStatus }
|
6
|
+
its(:message_id) { should == 3 }
|
7
|
+
its(:version) { should == 6 }
|
8
|
+
its(:data) { should_not be_empty }
|
9
|
+
its(:order_id) { should be_an Integer }
|
10
|
+
its(:status) { should =~ /Submit/ }
|
11
|
+
its(:to_human) { should =~
|
12
|
+
/<OrderStatus: <OrderState: .*Submit.* #\d+\/\d+ from 1111 filled 0\/100/ }
|
13
|
+
|
14
|
+
it 'has proper order_state accessor' do
|
15
|
+
os = subject.order_state
|
16
|
+
os.order_id.should be_an Integer
|
17
|
+
os.perm_id.should be_an Integer
|
18
|
+
os.client_id.should == 1111
|
19
|
+
os.parent_id.should == 0
|
20
|
+
os.filled.should == 0
|
21
|
+
os.remaining.should == 100
|
22
|
+
os.average_fill_price.should == 0.0
|
23
|
+
os.last_fill_price.should == 0.0
|
24
|
+
os.status.should =~ /Submit/
|
25
|
+
os.why_held.should =~ /child|/
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'has class accessors as well' do
|
29
|
+
subject.class.message_id.should == 3
|
30
|
+
subject.class.version.should == 6
|
31
|
+
subject.class.message_type.should == :OrderStatus
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
describe IB::Messages::Incoming::OrderStatus do
|
37
|
+
|
38
|
+
context 'Instantiated with data Hash' do
|
39
|
+
subject do
|
40
|
+
IB::Messages::Incoming::OrderStatus.new :version => 6,
|
41
|
+
:order_state =>
|
42
|
+
{:order_id => 1313,
|
43
|
+
:perm_id => 172323928,
|
44
|
+
:client_id => 1111,
|
45
|
+
:parent_id => 0,
|
46
|
+
:status => 'PreSubmitted',
|
47
|
+
:filled => 0,
|
48
|
+
:remaining => 100,
|
49
|
+
:average_fill_price => 0.0,
|
50
|
+
:last_fill_price => 0.0,
|
51
|
+
:why_held => 'child'}
|
52
|
+
end
|
53
|
+
|
54
|
+
it_behaves_like 'OrderStatus message'
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'received from IB' do
|
58
|
+
before(:all) do
|
59
|
+
verify_account
|
60
|
+
@ib = IB::Connection.new OPTS[:connection].merge(:logger => mock_logger)
|
61
|
+
@ib.wait_for :NextValidId
|
62
|
+
clean_connection
|
63
|
+
place_order IB::Symbols::Stocks[:wfc]
|
64
|
+
@ib.wait_for :OrderStatus, 6
|
65
|
+
end
|
66
|
+
|
67
|
+
after(:all) { close_connection } # implicitly cancels order
|
68
|
+
|
69
|
+
subject { @ib.received[:OrderStatus].first }
|
70
|
+
|
71
|
+
it_behaves_like 'OrderStatus message'
|
72
|
+
end
|
73
|
+
|
74
|
+
end # describe IB::Messages:Incoming
|