my-ib-api 0.0.1
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.
- checksums.yaml +7 -0
- data/lib/ib-api.rb +10 -0
- data/lib/ib/base.rb +99 -0
- data/lib/ib/base_properties.rb +154 -0
- data/lib/ib/connection.rb +327 -0
- data/lib/ib/constants.rb +334 -0
- data/lib/ib/db.rb +29 -0
- data/lib/ib/engine.rb +35 -0
- data/lib/ib/errors.rb +40 -0
- data/lib/ib/extensions.rb +72 -0
- data/lib/ib/flex.rb +106 -0
- data/lib/ib/logger.rb +25 -0
- data/lib/ib/messages.rb +88 -0
- data/lib/ib/messages/abstract_message.rb +89 -0
- data/lib/ib/messages/incoming.rb +134 -0
- data/lib/ib/messages/incoming/abstract_message.rb +99 -0
- data/lib/ib/messages/incoming/alert.rb +34 -0
- data/lib/ib/messages/incoming/contract_data.rb +102 -0
- data/lib/ib/messages/incoming/delta_neutral_validation.rb +23 -0
- data/lib/ib/messages/incoming/execution_data.rb +54 -0
- data/lib/ib/messages/incoming/historical_data.rb +55 -0
- data/lib/ib/messages/incoming/market_depths.rb +44 -0
- data/lib/ib/messages/incoming/next_valid_id.rb +18 -0
- data/lib/ib/messages/incoming/open_order.rb +232 -0
- data/lib/ib/messages/incoming/order_status.rb +81 -0
- data/lib/ib/messages/incoming/portfolio_value.rb +39 -0
- data/lib/ib/messages/incoming/real_time_bar.rb +32 -0
- data/lib/ib/messages/incoming/scanner_data.rb +53 -0
- data/lib/ib/messages/incoming/ticks.rb +131 -0
- data/lib/ib/messages/outgoing.rb +331 -0
- data/lib/ib/messages/outgoing/abstract_message.rb +73 -0
- data/lib/ib/messages/outgoing/bar_requests.rb +189 -0
- data/lib/ib/messages/outgoing/place_order.rb +141 -0
- data/lib/ib/model.rb +6 -0
- data/lib/ib/models.rb +10 -0
- data/lib/ib/requires.rb +9 -0
- data/lib/ib/socket.rb +81 -0
- data/lib/ib/symbols.rb +35 -0
- data/lib/ib/symbols/bonds.rb +28 -0
- data/lib/ib/symbols/forex.rb +41 -0
- data/lib/ib/symbols/futures.rb +117 -0
- data/lib/ib/symbols/options.rb +39 -0
- data/lib/ib/symbols/stocks.rb +37 -0
- data/lib/ib/version.rb +6 -0
- data/lib/models/ib/bag.rb +51 -0
- data/lib/models/ib/bar.rb +45 -0
- data/lib/models/ib/combo_leg.rb +103 -0
- data/lib/models/ib/contract.rb +292 -0
- data/lib/models/ib/contract_detail.rb +89 -0
- data/lib/models/ib/execution.rb +65 -0
- data/lib/models/ib/option.rb +60 -0
- data/lib/models/ib/order.rb +391 -0
- data/lib/models/ib/order_state.rb +128 -0
- data/lib/models/ib/underlying.rb +34 -0
- metadata +96 -0
@@ -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,102 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
module ContractAccessors
|
5
|
+
|
6
|
+
end
|
7
|
+
|
8
|
+
ContractDetails = ContractData =
|
9
|
+
def_message([10, [6, 8]],
|
10
|
+
[:request_id, :int], # request id
|
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
|
+
[:contract_detail, :market_name, :string], # extended
|
21
|
+
[:contract_detail, :trading_class, :string],
|
22
|
+
[:contract, :con_id, :int],
|
23
|
+
[:contract_detail, :min_tick, :decimal],
|
24
|
+
[:contract, :multiplier, :string],
|
25
|
+
[:contract_detail, :order_types, :string],
|
26
|
+
[:contract_detail, :valid_exchanges, :string],
|
27
|
+
[:contract_detail, :price_magnifier, :int],
|
28
|
+
[:contract_detail, :under_con_id, :int],
|
29
|
+
[:contract_detail, :long_name, :string],
|
30
|
+
[:contract, :primary_exchange, :string],
|
31
|
+
[:contract_detail, :contract_month, :string],
|
32
|
+
[:contract_detail, :industry, :string],
|
33
|
+
[:contract_detail, :category, :string],
|
34
|
+
[:contract_detail, :subcategory, :string],
|
35
|
+
[:contract_detail, :time_zone, :string],
|
36
|
+
[:contract_detail, :trading_hours, :string],
|
37
|
+
[:contract_detail, :liquid_hours, :string],
|
38
|
+
[:contract_detail, :ev_rule, :decimal],
|
39
|
+
[:contract_detail, :ev_multipler, :string],
|
40
|
+
[:sec_id_list_count, :int])
|
41
|
+
|
42
|
+
|
43
|
+
class ContractData
|
44
|
+
|
45
|
+
def contract
|
46
|
+
@contract = IB::Contract.build @data[:contract].
|
47
|
+
merge(:contract_detail => contract_detail)
|
48
|
+
end
|
49
|
+
|
50
|
+
def contract_detail
|
51
|
+
@contract_detail = IB::ContractDetail.new @data[:contract_detail]
|
52
|
+
end
|
53
|
+
|
54
|
+
alias contract_details contract_detail
|
55
|
+
|
56
|
+
def load
|
57
|
+
super
|
58
|
+
|
59
|
+
@data[:contract_detail][:sec_id_list] ||= HashWithIndifferentAccess.new
|
60
|
+
@data[:sec_id_list_count].times do
|
61
|
+
@data[:contract_detail][:sec_id_list][socket.read_string] = socket.read_string
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end # ContractData
|
66
|
+
|
67
|
+
BondContractData =
|
68
|
+
def_message [18, [4, 6]], ContractData,
|
69
|
+
[:request_id, :int],
|
70
|
+
[:contract, :symbol, :string],
|
71
|
+
[:contract, :sec_type, :string],
|
72
|
+
[:contract_detail, :cusip, :string],
|
73
|
+
[:contract_detail, :coupon, :decimal],
|
74
|
+
[:contract_detail, :maturity, :string],
|
75
|
+
[:contract_detail, :issue_date, :string],
|
76
|
+
[:contract_detail, :ratings, :string],
|
77
|
+
[:contract_detail, :bond_type, :string],
|
78
|
+
[:contract_detail, :coupon_type, :string],
|
79
|
+
[:contract_detail, :convertible, :boolean],
|
80
|
+
[:contract_detail, :callable, :boolean],
|
81
|
+
[:contract_detail, :puttable, :boolean],
|
82
|
+
[:contract_detail, :desc_append, :string],
|
83
|
+
[:contract, :exchange, :string],
|
84
|
+
[:contract, :currency, :string],
|
85
|
+
[:contract_detail, :market_name, :string], # extended
|
86
|
+
[:contract_detail, :trading_class, :string],
|
87
|
+
[:contract, :con_id, :int],
|
88
|
+
[:contract_detail, :min_tick, :decimal],
|
89
|
+
[:contract_detail, :order_types, :string],
|
90
|
+
[:contract_detail, :valid_exchanges, :string],
|
91
|
+
[:contract_detail, :valid_next_option_date, :string],
|
92
|
+
[:contract_detail, :valid_next_option_type, :string],
|
93
|
+
[:contract_detail, :valid_next_option_partial, :string],
|
94
|
+
[:contract_detail, :notes, :string],
|
95
|
+
[:contract_detail, :long_name, :string],
|
96
|
+
[:contract_detail, :ev_rule, :decimal],
|
97
|
+
[:contract_detail, :ev_multipler, :string],
|
98
|
+
[:sec_id_list_count, :int]
|
99
|
+
|
100
|
+
end # module Incoming
|
101
|
+
end # module Messages
|
102
|
+
end # module IB
|
@@ -0,0 +1,23 @@
|
|
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
|
+
[:underlying, :con_id, :int],
|
10
|
+
[:underlying, :delta, :decimal],
|
11
|
+
[:underlying, :price, :decimal]
|
12
|
+
class DeltaNeutralValidation
|
13
|
+
def underlying
|
14
|
+
@underlying = IB::Underlying.new @data[:underlying]
|
15
|
+
end
|
16
|
+
|
17
|
+
alias under_comp underlying
|
18
|
+
|
19
|
+
end # DeltaNeutralValidation
|
20
|
+
|
21
|
+
end # module Incoming
|
22
|
+
end # module Messages
|
23
|
+
end # module IB
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
|
5
|
+
ExecutionData =
|
6
|
+
def_message [11, [8, 9]],
|
7
|
+
# The reqID that was specified previously in the call to reqExecution()
|
8
|
+
[:request_id, :int],
|
9
|
+
[:execution, :local_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, :multiplier, :string],
|
17
|
+
[:contract, :exchange, :string],
|
18
|
+
[:contract, :currency, :string],
|
19
|
+
[:contract, :local_symbol, :string],
|
20
|
+
|
21
|
+
[:execution, :exec_id, :string], # Weird format
|
22
|
+
[:execution, :time, :string],
|
23
|
+
[:execution, :account_name, :string],
|
24
|
+
[:execution, :exchange, :string],
|
25
|
+
[:execution, :side, :string],
|
26
|
+
[:execution, :quantity, :int],
|
27
|
+
[:execution, :price, :decimal],
|
28
|
+
[:execution, :perm_id, :int],
|
29
|
+
[:execution, :client_id, :int],
|
30
|
+
[:execution, :liquidation, :int],
|
31
|
+
[:execution, :cumulative_quantity, :int],
|
32
|
+
[:execution, :average_price, :decimal],
|
33
|
+
[:execution, :order_ref, :string],
|
34
|
+
[:execution, :ev_rule, :string],
|
35
|
+
[:execution, :ev_multiplier, :decimal]
|
36
|
+
|
37
|
+
class ExecutionData
|
38
|
+
|
39
|
+
def contract
|
40
|
+
@contract = IB::Contract.build @data[:contract]
|
41
|
+
end
|
42
|
+
|
43
|
+
def execution
|
44
|
+
@execution = IB::Execution.new @data[:execution]
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_human
|
48
|
+
"<ExecutionData #{request_id}: #{contract.to_human}, #{execution}>"
|
49
|
+
end
|
50
|
+
|
51
|
+
end # ExecutionData
|
52
|
+
end # module Incoming
|
53
|
+
end # module Messages
|
54
|
+
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
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
|
5
|
+
# This message is always sent by TWS automatically at connect.
|
6
|
+
# The IB::Connection class subscribes to it automatically and stores
|
7
|
+
# the order id in its @next_local_id attribute.
|
8
|
+
NextValidID = NextValidId = def_message(9, [:local_id, :int])
|
9
|
+
|
10
|
+
class NextValidId
|
11
|
+
|
12
|
+
# Legacy accessor
|
13
|
+
alias order_id local_id
|
14
|
+
|
15
|
+
end # class NextValidId
|
16
|
+
end # module Incoming
|
17
|
+
end # module Messages
|
18
|
+
end # module IB
|
@@ -0,0 +1,232 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
|
5
|
+
# OpenOrder is the longest message with complex processing logics
|
6
|
+
OpenOrder =
|
7
|
+
def_message [5, 30],
|
8
|
+
[:order, :local_id, :int],
|
9
|
+
|
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
|
+
[:order, :action, :string],
|
21
|
+
[:order, :total_quantity, :int],
|
22
|
+
[:order, :order_type, :string],
|
23
|
+
[:order, :limit_price, :decimal_max],
|
24
|
+
[:order, :aux_price, :decimal_max],
|
25
|
+
[:order, :tif, :string],
|
26
|
+
[:order, :oca_group, :string],
|
27
|
+
[:order, :account, :string],
|
28
|
+
[:order, :open_close, :string],
|
29
|
+
[:order, :origin, :int],
|
30
|
+
[:order, :order_ref, :string],
|
31
|
+
[:order, :client_id, :int],
|
32
|
+
[:order, :perm_id, :int],
|
33
|
+
[:order, :outside_rth, :boolean], # (@socket.read_int == 1)
|
34
|
+
[:order, :hidden, :boolean], # (@socket.read_int == 1)
|
35
|
+
[:order, :discretionary_amount, :decimal],
|
36
|
+
[:order, :good_after_time, :string],
|
37
|
+
[:shares_allocation, :string], # deprecated! field
|
38
|
+
|
39
|
+
[:order, :fa_group, :string],
|
40
|
+
[:order, :fa_method, :string],
|
41
|
+
[:order, :fa_percentage, :string],
|
42
|
+
[:order, :fa_profile, :string],
|
43
|
+
[:order, :good_till_date, :string],
|
44
|
+
[:order, :rule_80a, :string],
|
45
|
+
[:order, :percent_offset, :decimal_max],
|
46
|
+
[:order, :settling_firm, :string],
|
47
|
+
[:order, :short_sale_slot, :int],
|
48
|
+
[:order, :designated_location, :string],
|
49
|
+
[:order, :exempt_code, :int], # skipped in ver 51?
|
50
|
+
[:order, :auction_strategy, :int],
|
51
|
+
[:order, :starting_price, :decimal_max],
|
52
|
+
[:order, :stock_ref_price, :decimal_max],
|
53
|
+
[:order, :delta, :decimal_max],
|
54
|
+
[:order, :stock_range_lower, :decimal_max],
|
55
|
+
[:order, :stock_range_upper, :decimal_max],
|
56
|
+
[:order, :display_size, :int],
|
57
|
+
#@order.rth_only = @socket.read_boolean
|
58
|
+
[:order, :block_order, :boolean],
|
59
|
+
[:order, :sweep_to_fill, :boolean],
|
60
|
+
[:order, :all_or_none, :boolean],
|
61
|
+
[:order, :min_quantity, :int_max],
|
62
|
+
[:order, :oca_type, :int],
|
63
|
+
[:order, :etrade_only, :boolean],
|
64
|
+
[:order, :firm_quote_only, :boolean],
|
65
|
+
[:order, :nbbo_price_cap, :decimal_max],
|
66
|
+
[:order, :parent_id, :int],
|
67
|
+
[:order, :trigger_method, :int],
|
68
|
+
[:order, :volatility, :decimal_max],
|
69
|
+
[:order, :volatility_type, :int],
|
70
|
+
[:order, :delta_neutral_order_type, :string],
|
71
|
+
[:order, :delta_neutral_aux_price, :decimal_max]
|
72
|
+
|
73
|
+
class OpenOrder
|
74
|
+
|
75
|
+
# Accessors to make OpenOrder API-compatible with OrderStatus message
|
76
|
+
|
77
|
+
def client_id
|
78
|
+
order.client_id
|
79
|
+
end
|
80
|
+
|
81
|
+
def parent_id
|
82
|
+
order.parent_id
|
83
|
+
end
|
84
|
+
|
85
|
+
def perm_id
|
86
|
+
order.perm_id
|
87
|
+
end
|
88
|
+
|
89
|
+
def local_id
|
90
|
+
order.local_id
|
91
|
+
end
|
92
|
+
|
93
|
+
alias order_id local_id
|
94
|
+
|
95
|
+
def status
|
96
|
+
order.status
|
97
|
+
end
|
98
|
+
|
99
|
+
# Object accessors
|
100
|
+
|
101
|
+
def order
|
102
|
+
@order ||= IB::Order.new @data[:order].merge(:order_state => order_state)
|
103
|
+
end
|
104
|
+
|
105
|
+
def order_state
|
106
|
+
@order_state ||= IB::OrderState.new(
|
107
|
+
@data[:order_state].merge(
|
108
|
+
:local_id => @data[:order][:local_id],
|
109
|
+
:perm_id => @data[:order][:perm_id],
|
110
|
+
:parent_id => @data[:order][:parent_id],
|
111
|
+
:client_id => @data[:order][:client_id]))
|
112
|
+
end
|
113
|
+
|
114
|
+
def contract
|
115
|
+
@contract ||= IB::Contract.build(
|
116
|
+
@data[:contract].merge(:underlying => underlying)
|
117
|
+
)
|
118
|
+
end
|
119
|
+
|
120
|
+
def underlying
|
121
|
+
@underlying = @data[:underlying_present] ? IB::Underlying.new(@data[:underlying]) : nil
|
122
|
+
end
|
123
|
+
|
124
|
+
alias under_comp underlying
|
125
|
+
|
126
|
+
def load
|
127
|
+
super
|
128
|
+
|
129
|
+
load_map [proc { | | filled?(@data[:order][:delta_neutral_order_type]) },
|
130
|
+
# As of client v.52, we may receive delta... params in openOrder
|
131
|
+
[:order, :delta_neutral_con_id, :int],
|
132
|
+
[:order, :delta_neutral_settling_firm, :string],
|
133
|
+
[:order, :delta_neutral_clearing_account, :string],
|
134
|
+
[:order, :delta_neutral_clearing_intent, :string]],
|
135
|
+
|
136
|
+
[:order, :continuous_update, :int],
|
137
|
+
[:order, :reference_price_type, :int],
|
138
|
+
[:order, :trail_stop_price, :decimal_max],
|
139
|
+
[:order, :trailing_percent, :decimal_max],
|
140
|
+
[:order, :basis_points, :decimal_max],
|
141
|
+
[:order, :basis_points_type, :int_max],
|
142
|
+
[:contract, :legs_description, :string],
|
143
|
+
|
144
|
+
# As of client v.55, we receive in OpenOrder for Combos:
|
145
|
+
# Contract.orderComboLegs Array
|
146
|
+
# Order.leg_prices Array
|
147
|
+
[:contract, :legs, :array, proc do |_|
|
148
|
+
IB::ComboLeg.new :con_id => socket.read_int,
|
149
|
+
:ratio => socket.read_int,
|
150
|
+
:action => socket.read_string,
|
151
|
+
:exchange => socket.read_string,
|
152
|
+
:open_close => socket.read_int,
|
153
|
+
:short_sale_slot => socket.read_int,
|
154
|
+
:designated_location => socket.read_string,
|
155
|
+
:exempt_code => socket.read_int
|
156
|
+
end],
|
157
|
+
[:order, :leg_prices, :array, proc { |_| socket.read_decimal_max }],
|
158
|
+
[:smart_combo_routing_params, :hash],
|
159
|
+
|
160
|
+
[:order, :scale_init_level_size, :int_max],
|
161
|
+
[:order, :scale_subs_level_size, :int_max],
|
162
|
+
|
163
|
+
[:order, :scale_price_increment, :decimal_max],
|
164
|
+
[proc { | | filled?(@data[:order][:scale_price_increment]) },
|
165
|
+
# As of client v.54, we may receive scale order fields
|
166
|
+
[:order, :scale_price_adjust_value, :decimal_max],
|
167
|
+
[:order, :scale_price_adjust_interval, :int_max],
|
168
|
+
[:order, :scale_profit_offset, :decimal_max],
|
169
|
+
[:order, :scale_auto_reset, :boolean],
|
170
|
+
[:order, :scale_init_position, :int_max],
|
171
|
+
[:order, :scale_init_fill_qty, :decimal_max],
|
172
|
+
[:order, :scale_random_percent, :boolean]
|
173
|
+
],
|
174
|
+
|
175
|
+
[:order, :hedge_type, :string],
|
176
|
+
[proc { | | filled?(@data[:order][:hedge_type]) },
|
177
|
+
# As of client v.49/50, we can receive hedgeType, hedgeParam
|
178
|
+
[:order, :hedge_param, :string]
|
179
|
+
],
|
180
|
+
|
181
|
+
[:order, :opt_out_smart_routing, :boolean],
|
182
|
+
[:order, :clearing_account, :string],
|
183
|
+
[:order, :clearing_intent, :string],
|
184
|
+
[:order, :not_held, :boolean],
|
185
|
+
|
186
|
+
[:underlying_present, :boolean],
|
187
|
+
[proc { | | filled?(@data[:underlying_present]) },
|
188
|
+
[:underlying, :con_id, :int],
|
189
|
+
[:underlying, :delta, :decimal],
|
190
|
+
[:underlying, :price, :decimal]
|
191
|
+
],
|
192
|
+
|
193
|
+
# TODO: Test Order with algo_params, scale and legs!
|
194
|
+
[:order, :algo_strategy, :string],
|
195
|
+
[proc { | | filled?(@data[:order][:algo_strategy]) },
|
196
|
+
[:order, :algo_params, :hash]
|
197
|
+
],
|
198
|
+
|
199
|
+
[:order, :what_if, :boolean],
|
200
|
+
|
201
|
+
[:order_state, :status, :string],
|
202
|
+
# IB uses weird String with Java Double.MAX_VALUE to indicate no value here
|
203
|
+
[:order_state, :init_margin, :decimal_max], # :string],
|
204
|
+
[:order_state, :maint_margin, :decimal_max], # :string],
|
205
|
+
[:order_state, :equity_with_loan, :decimal_max], # :string],
|
206
|
+
[:order_state, :commission, :decimal_max], # May be nil!
|
207
|
+
[:order_state, :min_commission, :decimal_max], # May be nil!
|
208
|
+
[:order_state, :max_commission, :decimal_max], # May be nil!
|
209
|
+
[:order_state, :commission_currency, :string],
|
210
|
+
[:order_state, :warning_text, :string]
|
211
|
+
end
|
212
|
+
|
213
|
+
# Check if given value was set by TWS to something vaguely "positive"
|
214
|
+
def filled? value
|
215
|
+
case value
|
216
|
+
when String
|
217
|
+
!value.empty?
|
218
|
+
when Float, Integer
|
219
|
+
value > 0
|
220
|
+
else
|
221
|
+
!!value # to_bool
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def to_human
|
226
|
+
"<OpenOrder: #{contract.to_human} #{order.to_human}>"
|
227
|
+
end
|
228
|
+
|
229
|
+
end # class OpenOrder
|
230
|
+
end # module Incoming
|
231
|
+
end # module Messages
|
232
|
+
end # module IB
|