ib-ruby 0.7.4 → 0.7.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/.gitignore +3 -0
  2. data/HISTORY +8 -0
  3. data/README.md +2 -2
  4. data/Rakefile +15 -0
  5. data/TODO +7 -2
  6. data/VERSION +1 -1
  7. data/bin/account_info +1 -1
  8. data/bin/cancel_orders +1 -1
  9. data/bin/contract_details +1 -1
  10. data/bin/depth_of_market +1 -1
  11. data/bin/fa_accounts +1 -1
  12. data/bin/fundamental_data +42 -0
  13. data/bin/historic_data +1 -1
  14. data/bin/historic_data_cli +1 -1
  15. data/bin/list_orders +1 -2
  16. data/bin/market_data +1 -1
  17. data/bin/option_data +1 -1
  18. data/bin/place_combo_order +1 -1
  19. data/bin/place_order +1 -1
  20. data/bin/template +1 -4
  21. data/bin/tick_data +2 -2
  22. data/bin/time_and_sales +1 -1
  23. data/lib/ib-ruby.rb +4 -0
  24. data/lib/ib-ruby/connection.rb +50 -34
  25. data/lib/ib-ruby/constants.rb +232 -37
  26. data/lib/ib-ruby/db.rb +25 -0
  27. data/lib/ib-ruby/extensions.rb +51 -1
  28. data/lib/ib-ruby/messages/abstract_message.rb +0 -8
  29. data/lib/ib-ruby/messages/incoming.rb +18 -493
  30. data/lib/ib-ruby/messages/incoming/abstract_message.rb +100 -0
  31. data/lib/ib-ruby/messages/incoming/alert.rb +34 -0
  32. data/lib/ib-ruby/messages/incoming/contract_data.rb +82 -0
  33. data/lib/ib-ruby/messages/incoming/delta_neutral_validation.rb +20 -0
  34. data/lib/ib-ruby/messages/incoming/execution_data.rb +59 -0
  35. data/lib/ib-ruby/messages/incoming/historical_data.rb +55 -0
  36. data/lib/ib-ruby/messages/incoming/market_depths.rb +44 -0
  37. data/lib/ib-ruby/messages/incoming/open_order.rb +32 -16
  38. data/lib/ib-ruby/messages/incoming/order_status.rb +67 -0
  39. data/lib/ib-ruby/messages/incoming/portfolio_value.rb +39 -0
  40. data/lib/ib-ruby/messages/incoming/real_time_bar.rb +32 -0
  41. data/lib/ib-ruby/messages/incoming/scanner_data.rb +49 -0
  42. data/lib/ib-ruby/messages/outgoing.rb +25 -223
  43. data/lib/ib-ruby/messages/outgoing/abstract_message.rb +61 -0
  44. data/lib/ib-ruby/messages/outgoing/bar_requests.rb +149 -0
  45. data/lib/ib-ruby/messages/outgoing/place_order.rb +24 -0
  46. data/lib/ib-ruby/models.rb +4 -0
  47. data/lib/ib-ruby/models/bar.rb +31 -14
  48. data/lib/ib-ruby/models/combo_leg.rb +48 -23
  49. data/lib/ib-ruby/models/contracts.rb +2 -2
  50. data/lib/ib-ruby/models/contracts/bag.rb +11 -7
  51. data/lib/ib-ruby/models/contracts/contract.rb +90 -66
  52. data/lib/ib-ruby/models/contracts/option.rb +16 -7
  53. data/lib/ib-ruby/models/execution.rb +34 -18
  54. data/lib/ib-ruby/models/model.rb +15 -7
  55. data/lib/ib-ruby/models/model_properties.rb +101 -44
  56. data/lib/ib-ruby/models/order.rb +176 -187
  57. data/lib/ib-ruby/models/order_state.rb +99 -0
  58. data/lib/ib-ruby/symbols/forex.rb +10 -10
  59. data/lib/ib-ruby/symbols/futures.rb +6 -6
  60. data/lib/ib-ruby/symbols/stocks.rb +3 -3
  61. data/spec/account_helper.rb +4 -5
  62. data/spec/combo_helper.rb +4 -4
  63. data/spec/db.rb +18 -0
  64. data/spec/ib-ruby/messages/{incoming_spec.rb → incoming/alert_spec.rb} +1 -0
  65. data/spec/ib-ruby/messages/incoming/open_order_spec.rb +100 -0
  66. data/spec/ib-ruby/messages/incoming/order_status_spec.rb +74 -0
  67. data/spec/ib-ruby/messages/{outgoing_spec.rb → outgoing/account_data_spec.rb} +0 -0
  68. data/spec/ib-ruby/messages/outgoing/market_data_type_spec.rb +44 -0
  69. data/spec/ib-ruby/models/bag_spec.rb +97 -0
  70. data/spec/ib-ruby/models/bar_spec.rb +45 -0
  71. data/spec/ib-ruby/models/combo_leg_spec.rb +56 -40
  72. data/spec/ib-ruby/models/contract_spec.rb +134 -170
  73. data/spec/ib-ruby/models/execution_spec.rb +35 -50
  74. data/spec/ib-ruby/models/option_spec.rb +127 -0
  75. data/spec/ib-ruby/models/order_spec.rb +89 -68
  76. data/spec/ib-ruby/models/order_state_spec.rb +55 -0
  77. data/spec/integration/contract_info_spec.rb +4 -6
  78. data/spec/integration/fundamental_data_spec.rb +41 -0
  79. data/spec/integration/historic_data_spec.rb +4 -4
  80. data/spec/integration/market_data_spec.rb +1 -3
  81. data/spec/integration/orders/attached_spec.rb +8 -10
  82. data/spec/integration/orders/combo_spec.rb +2 -2
  83. data/spec/integration/orders/execution_spec.rb +0 -1
  84. data/spec/integration/orders/placement_spec.rb +1 -3
  85. data/spec/integration/orders/valid_ids_spec.rb +1 -2
  86. data/spec/message_helper.rb +1 -1
  87. data/spec/model_helper.rb +211 -0
  88. data/spec/order_helper.rb +44 -37
  89. data/spec/spec_helper.rb +36 -23
  90. data/spec/v.rb +7 -0
  91. data/tasks/doc.rake +1 -1
  92. metadata +116 -12
  93. data/spec/integration/orders/open_order +0 -98
@@ -0,0 +1,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 => SECURITY_TYPES[:forex],
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 => SECURITY_TYPES[:forex],
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 => SECURITY_TYPES[:forex],
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 => SECURITY_TYPES[:forex],
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 => SECURITY_TYPES[:forex],
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 => SECURITY_TYPES[:forex],
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 => SECURITY_TYPES[:forex],
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 => SECURITY_TYPES[:forex],
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 => SECURITY_TYPES[:forex],
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 => SECURITY_TYPES[:forex],
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 => SECURITY_TYPES[:future],
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 => SECURITY_TYPES[:future],
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 => SECURITY_TYPES[:future],
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 => SECURITY_TYPES[:future],
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 => SECURITY_TYPES[:future],
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 => SECURITY_TYPES[:future],
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 => SECURITY_TYPES[:stock],
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 => SECURITY_TYPES[:stock],
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 => SECURITY_TYPES[:stock],
25
+ :sec_type => :stock,
26
26
  :description => "Non-existent stock"),
27
27
  }
28
28
  end
@@ -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 :AccountDownloadEnd
20
- @ib.send_message :RequestAccountData, :subscribe => false
21
- raise "Unable to verify IB PAPER ACCOUNT" unless @ib.received?(:AccountValue)
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[:AccountValue].first.account_name
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
- # Create new Combo contract
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