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.
- 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,100 @@
|
|
1
|
+
require 'ib-ruby/messages/abstract_message'
|
2
|
+
|
3
|
+
module IB
|
4
|
+
module Messages
|
5
|
+
module Incoming
|
6
|
+
|
7
|
+
# Container for specific message classes, keyed by their message_ids
|
8
|
+
Classes = {}
|
9
|
+
|
10
|
+
class AbstractMessage < IB::Messages::AbstractMessage
|
11
|
+
|
12
|
+
def version # Per message, received messages may have the different versions
|
13
|
+
@data[:version]
|
14
|
+
end
|
15
|
+
|
16
|
+
def check_version actual, expected
|
17
|
+
unless actual == expected || expected.is_a?(Array) && expected.include?(actual)
|
18
|
+
error "Unsupported version #{actual} received, expected #{expected}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Create incoming message from a given source (IB server or data Hash)
|
23
|
+
def initialize source
|
24
|
+
@created_at = Time.now
|
25
|
+
if source[:socket] # Source is a server
|
26
|
+
@server = source
|
27
|
+
@data = Hash.new
|
28
|
+
begin
|
29
|
+
self.load
|
30
|
+
rescue => e
|
31
|
+
error "Reading #{self.class}: #{e.class}: #{e.message}", :load, e.backtrace
|
32
|
+
ensure
|
33
|
+
@server = nil
|
34
|
+
end
|
35
|
+
else # Source is a @data Hash
|
36
|
+
@data = source
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def socket
|
41
|
+
@server[:socket]
|
42
|
+
end
|
43
|
+
|
44
|
+
# Every message loads received message version first
|
45
|
+
# Override the load method in your subclass to do actual reading into @data.
|
46
|
+
def load
|
47
|
+
@data[:version] = socket.read_int
|
48
|
+
|
49
|
+
check_version @data[:version], self.class.version
|
50
|
+
|
51
|
+
load_map *self.class.data_map
|
52
|
+
end
|
53
|
+
|
54
|
+
# Load @data from the socket according to the given data map.
|
55
|
+
#
|
56
|
+
# map is a series of Arrays in the format of
|
57
|
+
# [ :name, :type ], [ :group, :name, :type]
|
58
|
+
# type identifiers must have a corresponding read_type method on socket (read_int, etc.).
|
59
|
+
# group is used to lump together aggregates, such as Contract or Order fields
|
60
|
+
def load_map(*map)
|
61
|
+
map.each do |instruction|
|
62
|
+
# We determine the function of the first element
|
63
|
+
head = instruction.first
|
64
|
+
case head
|
65
|
+
when Integer # >= Version condition: [ min_version, [map]]
|
66
|
+
load_map *instruction.drop(1) if version >= head
|
67
|
+
|
68
|
+
when Proc # Callable condition: [ condition, [map]]
|
69
|
+
load_map *instruction.drop(1) if head.call
|
70
|
+
|
71
|
+
when true # Pre-condition already succeeded!
|
72
|
+
load_map *instruction.drop(1)
|
73
|
+
|
74
|
+
when nil, false # Pre-condition already failed! Do nothing...
|
75
|
+
|
76
|
+
when Symbol # Normal map
|
77
|
+
group, name, type, block =
|
78
|
+
if instruction[2].nil? || instruction[2].is_a?(Proc)
|
79
|
+
[nil] + instruction # No group, [ :name, :type, (:block) ]
|
80
|
+
else
|
81
|
+
instruction # [ :group, :name, :type, (:block)]
|
82
|
+
end
|
83
|
+
|
84
|
+
data = socket.__send__("read_#{type}", &block)
|
85
|
+
if group
|
86
|
+
@data[group] ||= {}
|
87
|
+
@data[group][name] = data
|
88
|
+
else
|
89
|
+
@data[name] = data
|
90
|
+
end
|
91
|
+
else
|
92
|
+
error "Unrecognized instruction #{instruction}"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end # class AbstractMessage
|
98
|
+
end # module Incoming
|
99
|
+
end # module Messages
|
100
|
+
end # module IB
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
|
5
|
+
# Called Error in Java code, but in fact this type of messages also
|
6
|
+
# deliver system alerts and additional (non-error) info from TWS.
|
7
|
+
ErrorMessage = Error = Alert = def_message([4, 2],
|
8
|
+
[:error_id, :int],
|
9
|
+
[:code, :int],
|
10
|
+
[:message, :string])
|
11
|
+
class Alert
|
12
|
+
# Is it an Error message?
|
13
|
+
def error?
|
14
|
+
code < 1000
|
15
|
+
end
|
16
|
+
|
17
|
+
# Is it a System message?
|
18
|
+
def system?
|
19
|
+
code > 1000 && code < 2000
|
20
|
+
end
|
21
|
+
|
22
|
+
# Is it a Warning message?
|
23
|
+
def warning?
|
24
|
+
code > 2000
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_human
|
28
|
+
"TWS #{ error? ? 'Error' : system? ? 'System' : 'Warning'} #{code}: #{message}"
|
29
|
+
end
|
30
|
+
end # class Alert
|
31
|
+
|
32
|
+
end # module Incoming
|
33
|
+
end # module Messages
|
34
|
+
end # module IB
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
|
5
|
+
ContractDetails = ContractData =
|
6
|
+
def_message([10, 6],
|
7
|
+
[:request_id, :int], # request id
|
8
|
+
[:contract, :symbol, :string],
|
9
|
+
[:contract, :sec_type, :string],
|
10
|
+
[:contract, :expiry, :string],
|
11
|
+
[:contract, :strike, :decimal],
|
12
|
+
[:contract, :right, :string],
|
13
|
+
[:contract, :exchange, :string],
|
14
|
+
[:contract, :currency, :string],
|
15
|
+
[:contract, :local_symbol, :string],
|
16
|
+
|
17
|
+
[:contract, :market_name, :string], # extended
|
18
|
+
[:contract, :trading_class, :string],
|
19
|
+
[:contract, :con_id, :int],
|
20
|
+
[:contract, :min_tick, :decimal],
|
21
|
+
[:contract, :multiplier, :string],
|
22
|
+
[:contract, :order_types, :string],
|
23
|
+
[:contract, :valid_exchanges, :string],
|
24
|
+
[:contract, :price_magnifier, :int],
|
25
|
+
[:contract, :under_con_id, :int],
|
26
|
+
[:contract, :long_name, :string],
|
27
|
+
[:contract, :primary_exchange, :string],
|
28
|
+
[:contract, :contract_month, :string],
|
29
|
+
[:contract, :industry, :string],
|
30
|
+
[:contract, :category, :string],
|
31
|
+
[:contract, :subcategory, :string],
|
32
|
+
[:contract, :time_zone, :string],
|
33
|
+
[:contract, :trading_hours, :string],
|
34
|
+
[:contract, :liquid_hours, :string])
|
35
|
+
|
36
|
+
class ContractData
|
37
|
+
|
38
|
+
def contract
|
39
|
+
@contract = IB::Contract.build @data[:contract]
|
40
|
+
end
|
41
|
+
end # ContractData
|
42
|
+
|
43
|
+
BondContractData =
|
44
|
+
def_message [18, 4],
|
45
|
+
[:request_id, :int],
|
46
|
+
[:contract, :symbol, :string],
|
47
|
+
[:contract, :sec_type, :string],
|
48
|
+
[:contract, :cusip, :string],
|
49
|
+
[:contract, :coupon, :decimal],
|
50
|
+
[:contract, :maturity, :string],
|
51
|
+
[:contract, :issue_date, :string],
|
52
|
+
[:contract, :ratings, :string],
|
53
|
+
[:contract, :bond_type, :string],
|
54
|
+
[:contract, :coupon_type, :string],
|
55
|
+
[:contract, :convertible, :boolean],
|
56
|
+
[:contract, :callable, :boolean],
|
57
|
+
[:contract, :puttable, :boolean],
|
58
|
+
[:contract, :desc_append, :string],
|
59
|
+
[:contract, :exchange, :string],
|
60
|
+
[:contract, :currency, :string],
|
61
|
+
[:contract, :market_name, :string], # extended
|
62
|
+
[:contract, :trading_class, :string],
|
63
|
+
[:contract, :con_id, :int],
|
64
|
+
[:contract, :min_tick, :decimal],
|
65
|
+
[:contract, :order_types, :string],
|
66
|
+
[:contract, :valid_exchanges, :string],
|
67
|
+
[:contract, :valid_next_option_date, :string],
|
68
|
+
[:contract, :valid_next_option_type, :string],
|
69
|
+
[:contract, :valid_next_option_partial, :string],
|
70
|
+
[:contract, :notes, :string],
|
71
|
+
[:contract, :long_name, :string]
|
72
|
+
|
73
|
+
class BondContractData
|
74
|
+
|
75
|
+
def contract
|
76
|
+
@contract = IB::Contract.build @data[:contract]
|
77
|
+
end
|
78
|
+
end # BondContractData
|
79
|
+
|
80
|
+
end # module Incoming
|
81
|
+
end # module Messages
|
82
|
+
end # module IB
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
|
5
|
+
# The server sends this message upon accepting a Delta-Neutral DN RFQ
|
6
|
+
# - see API Reference p. 26
|
7
|
+
DeltaNeutralValidation = def_message 56,
|
8
|
+
[:request_id, :int],
|
9
|
+
[:contract, :under_con_id, :int],
|
10
|
+
[:contract, :under_delta, :decimal],
|
11
|
+
[:contract, :under_price, :decimal]
|
12
|
+
class DeltaNeutralValidation
|
13
|
+
def contract
|
14
|
+
@contract = IB::Contract.build @data[:contract].merge(:under_comp => true)
|
15
|
+
end
|
16
|
+
end # DeltaNeutralValidation
|
17
|
+
|
18
|
+
end # module Incoming
|
19
|
+
end # module Messages
|
20
|
+
end # module IB
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
|
5
|
+
ExecutionData =
|
6
|
+
def_message [11, 8],
|
7
|
+
# The reqID that was specified previously in the call to reqExecution()
|
8
|
+
[:request_id, :int],
|
9
|
+
[:execution, :order_id, :int],
|
10
|
+
[:contract, :con_id, :int],
|
11
|
+
[:contract, :symbol, :string],
|
12
|
+
[:contract, :sec_type, :string],
|
13
|
+
[:contract, :expiry, :string],
|
14
|
+
[:contract, :strike, :decimal],
|
15
|
+
[:contract, :right, :string],
|
16
|
+
[:contract, :exchange, :string],
|
17
|
+
[:contract, :currency, :string],
|
18
|
+
[:contract, :local_symbol, :string],
|
19
|
+
|
20
|
+
[:execution, :exec_id, :string], # Weird format
|
21
|
+
[:execution, :time, :string],
|
22
|
+
[:execution, :account_name, :string],
|
23
|
+
[:execution, :exchange, :string],
|
24
|
+
[:execution, :side, :string],
|
25
|
+
[:execution, :shares, :int],
|
26
|
+
[:execution, :price, :decimal],
|
27
|
+
[:execution, :perm_id, :int],
|
28
|
+
[:execution, :client_id, :int],
|
29
|
+
[:execution, :liquidation, :int],
|
30
|
+
[:execution, :cumulative_quantity, :int],
|
31
|
+
[:execution, :average_price, :decimal]
|
32
|
+
|
33
|
+
class ExecutionData
|
34
|
+
|
35
|
+
def contract
|
36
|
+
@contract = IB::Contract.build @data[:contract]
|
37
|
+
end
|
38
|
+
|
39
|
+
def execution
|
40
|
+
@execution = IB::Execution.new @data[:execution]
|
41
|
+
end
|
42
|
+
|
43
|
+
def load
|
44
|
+
super
|
45
|
+
|
46
|
+
# As of client v.53, we can receive orderRef in ExecutionData
|
47
|
+
load_map [proc { | | @server[:client_version] >= 53 },
|
48
|
+
[:execution, :order_ref, :string]
|
49
|
+
]
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_human
|
53
|
+
"<ExecutionData #{request_id}: #{contract.to_human}, #{execution}>"
|
54
|
+
end
|
55
|
+
|
56
|
+
end # ExecutionData
|
57
|
+
end # module Incoming
|
58
|
+
end # module Messages
|
59
|
+
end # module IB
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
|
5
|
+
# HistoricalData contains following @data:
|
6
|
+
# General:
|
7
|
+
# :request_id - The ID of the request to which this is responding
|
8
|
+
# :count - Number of Historical data points returned (size of :results).
|
9
|
+
# :results - an Array of Historical Data Bars
|
10
|
+
# :start_date - beginning of returned Historical data period
|
11
|
+
# :end_date - end of returned Historical data period
|
12
|
+
# Each returned Bar in @data[:results] Array contains this data:
|
13
|
+
# :date - The date-time stamp of the start of the bar. The format is
|
14
|
+
# determined by the RequestHistoricalData formatDate parameter.
|
15
|
+
# :open - The bar opening price.
|
16
|
+
# :high - The high price during the time covered by the bar.
|
17
|
+
# :low - The low price during the time covered by the bar.
|
18
|
+
# :close - The bar closing price.
|
19
|
+
# :volume - The volume during the time covered by the bar.
|
20
|
+
# :trades - When TRADES historical data is returned, represents number of trades
|
21
|
+
# that occurred during the time period the bar covers
|
22
|
+
# :wap - The weighted average price during the time covered by the bar.
|
23
|
+
# :has_gaps - Whether or not there are gaps in the data.
|
24
|
+
|
25
|
+
HistoricalData = def_message [17, 3],
|
26
|
+
[:request_id, :int],
|
27
|
+
[:start_date, :string],
|
28
|
+
[:end_date, :string],
|
29
|
+
[:count, :int]
|
30
|
+
class HistoricalData
|
31
|
+
attr_accessor :results
|
32
|
+
|
33
|
+
def load
|
34
|
+
super
|
35
|
+
|
36
|
+
@results = Array.new(@data[:count]) do |_|
|
37
|
+
IB::Bar.new :time => socket.read_string,
|
38
|
+
:open => socket.read_decimal,
|
39
|
+
:high => socket.read_decimal,
|
40
|
+
:low => socket.read_decimal,
|
41
|
+
:close => socket.read_decimal,
|
42
|
+
:volume => socket.read_int,
|
43
|
+
:wap => socket.read_decimal,
|
44
|
+
:has_gaps => socket.read_string,
|
45
|
+
:trades => socket.read_int
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_human
|
50
|
+
"<HistoricalData: #{request_id}, #{count} items, #{start_date} to #{end_date}>"
|
51
|
+
end
|
52
|
+
end # HistoricalData
|
53
|
+
end # module Incoming
|
54
|
+
end # module Messages
|
55
|
+
end # module IB
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
|
5
|
+
MarketDepth =
|
6
|
+
def_message 12, [:request_id, :int],
|
7
|
+
[:position, :int], # The row Id of this market depth entry.
|
8
|
+
[:operation, :int], # How it should be applied to the market depth:
|
9
|
+
# 0 = insert this new order into the row identified by :position
|
10
|
+
# 1 = update the existing order in the row identified by :position
|
11
|
+
# 2 = delete the existing order at the row identified by :position
|
12
|
+
[:side, :int], # side of the book: 0 = ask, 1 = bid
|
13
|
+
[:price, :decimal],
|
14
|
+
[:size, :int]
|
15
|
+
|
16
|
+
class MarketDepth
|
17
|
+
def side
|
18
|
+
@data[:side] == 0 ? :ask : :bid
|
19
|
+
end
|
20
|
+
|
21
|
+
def operation
|
22
|
+
@data[:operation] == 0 ? :insert : @data[:operation] == 1 ? :update : :delete
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_human
|
26
|
+
"<#{self.message_type}: #{operation} #{side} @ "+
|
27
|
+
"#{position} = #{price} x #{size}>"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
MarketDepthL2 =
|
32
|
+
def_message 13, MarketDepth, # Fields descriptions - see above
|
33
|
+
[:request_id, :int],
|
34
|
+
[:position, :int],
|
35
|
+
[:market_maker, :string], # The exchange hosting this order.
|
36
|
+
[:operation, :int],
|
37
|
+
[:side, :int],
|
38
|
+
[:price, :decimal],
|
39
|
+
[:size, :int]
|
40
|
+
|
41
|
+
|
42
|
+
end # module Incoming
|
43
|
+
end # module Messages
|
44
|
+
end # module IB
|
@@ -1,8 +1,8 @@
|
|
1
|
-
# OpenOrder is the longest message with complex processing logics, it is isolated here
|
2
1
|
module IB
|
3
2
|
module Messages
|
4
3
|
module Incoming
|
5
4
|
|
5
|
+
# OpenOrder is the longest message with complex processing logics
|
6
6
|
OpenOrder =
|
7
7
|
def_message [5, [23, 28]],
|
8
8
|
[:order, :order_id, :int],
|
@@ -73,13 +73,32 @@ module IB
|
|
73
73
|
|
74
74
|
class OpenOrder
|
75
75
|
|
76
|
+
|
76
77
|
# Accessors to make OpenOrder API-compatible with OrderStatus message
|
78
|
+
|
79
|
+
def order
|
80
|
+
@order ||= IB::Order.new @data[:order].merge(:order_state => order_state)
|
81
|
+
end
|
82
|
+
|
83
|
+
def order_state
|
84
|
+
@order_state ||= IB::OrderState.new(
|
85
|
+
@data[:order_state].merge(
|
86
|
+
:order_id => @data[:order][:order_id],
|
87
|
+
:perm_id => @data[:order][:perm_id],
|
88
|
+
:parent_id => @data[:order][:parent_id],
|
89
|
+
:client_id => @data[:order][:client_id]))
|
90
|
+
end
|
91
|
+
|
92
|
+
def contract
|
93
|
+
@contract ||= IB::Contract.build @data[:contract]
|
94
|
+
end
|
95
|
+
|
77
96
|
def order_id
|
78
|
-
order
|
97
|
+
order.order_id
|
79
98
|
end
|
80
99
|
|
81
100
|
def status
|
82
|
-
order
|
101
|
+
order.status
|
83
102
|
end
|
84
103
|
|
85
104
|
def load
|
@@ -166,20 +185,17 @@ module IB
|
|
166
185
|
],
|
167
186
|
|
168
187
|
[:order, :what_if, :boolean],
|
169
|
-
[:order, :status, :string],
|
170
188
|
|
189
|
+
[:order_state, :status, :string],
|
171
190
|
# IB uses weird String with Java Double.MAX_VALUE to indicate no value here
|
172
|
-
[:
|
173
|
-
[:
|
174
|
-
[:
|
175
|
-
[:
|
176
|
-
[:
|
177
|
-
[:
|
178
|
-
[:
|
179
|
-
[:
|
180
|
-
|
181
|
-
@order = IB::Order.new @data[:order]
|
182
|
-
@contract = IB::Contract.build @data[:contract]
|
191
|
+
[:order_state, :init_margin, :decimal_max], # :string],
|
192
|
+
[:order_state, :maint_margin, :decimal_max], # :string],
|
193
|
+
[:order_state, :equity_with_loan, :decimal_max], # :string],
|
194
|
+
[:order_state, :commission, :decimal_max], # May be nil!
|
195
|
+
[:order_state, :min_commission, :decimal_max], # May be nil!
|
196
|
+
[:order_state, :max_commission, :decimal_max], # May be nil!
|
197
|
+
[:order_state, :commission_currency, :string],
|
198
|
+
[:order_state, :warning_text, :string]
|
183
199
|
end
|
184
200
|
|
185
201
|
# Check if given value was set by TWS to something vaguely "positive"
|
@@ -195,7 +211,7 @@ module IB
|
|
195
211
|
end
|
196
212
|
|
197
213
|
def to_human
|
198
|
-
"<OpenOrder: #{
|
214
|
+
"<OpenOrder: #{contract.to_human} #{order.to_human}>"
|
199
215
|
end
|
200
216
|
|
201
217
|
end # class OpenOrder
|