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,81 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
|
5
|
+
# :status - String: Displays the order status. Possible values include:
|
6
|
+
# - PendingSubmit - indicates that you have transmitted the order, but
|
7
|
+
# have not yet received confirmation that it has been accepted by the
|
8
|
+
# order destination. NOTE: This order status is NOT sent back by TWS
|
9
|
+
# and should be explicitly set by YOU when an order is submitted.
|
10
|
+
# - PendingCancel - indicates that you have sent a request to cancel
|
11
|
+
# the order but have not yet received cancel confirmation from the
|
12
|
+
# order destination. At this point, your order cancel is not confirmed.
|
13
|
+
# You may still receive an execution while your cancellation request
|
14
|
+
# is pending. NOTE: This order status is not sent back by TWS and
|
15
|
+
# should be explicitly set by YOU when an order is canceled.
|
16
|
+
# - PreSubmitted - indicates that a simulated order type has been
|
17
|
+
# accepted by the IB system and that this order has yet to be elected.
|
18
|
+
# The order is held in the IB system until the election criteria are
|
19
|
+
# met. At that time the order is transmitted to the order destination
|
20
|
+
# as specified.
|
21
|
+
# - Submitted - indicates that your order has been accepted at the order
|
22
|
+
# destination and is working.
|
23
|
+
# - Cancelled - indicates that the balance of your order has been
|
24
|
+
# confirmed canceled by the IB system. This could occur unexpectedly
|
25
|
+
# when IB or the destination has rejected your order.
|
26
|
+
# - ApiCancelled - canceled via API
|
27
|
+
# - Filled - indicates that the order has been completely filled.
|
28
|
+
# - Inactive - indicates that the order has been accepted by the system
|
29
|
+
# (simulated orders) or an exchange (native orders) but that currently
|
30
|
+
# the order is inactive due to system, exchange or other issues.
|
31
|
+
# :why_held - This property contains the comma-separated list of reasons for
|
32
|
+
# order to be held. For example, when TWS is trying to locate shares for
|
33
|
+
# a short sell, the value used to indicate this is 'locate'.
|
34
|
+
OrderStatus = def_message [3, 6],
|
35
|
+
[:order_state, :local_id, :int],
|
36
|
+
[:order_state, :status, :string],
|
37
|
+
[:order_state, :filled, :int],
|
38
|
+
[:order_state, :remaining, :int],
|
39
|
+
[:order_state, :average_fill_price, :decimal],
|
40
|
+
[:order_state, :perm_id, :int],
|
41
|
+
[:order_state, :parent_id, :int],
|
42
|
+
[:order_state, :last_fill_price, :decimal],
|
43
|
+
[:order_state, :client_id, :int],
|
44
|
+
[:order_state, :why_held, :string]
|
45
|
+
class OrderStatus
|
46
|
+
|
47
|
+
def order_state
|
48
|
+
@order_state ||= IB::OrderState.new @data[:order_state]
|
49
|
+
end
|
50
|
+
|
51
|
+
# Accessors to make OpenOrder and OrderStatus messages API-compatible
|
52
|
+
def client_id
|
53
|
+
order_state.client_id
|
54
|
+
end
|
55
|
+
|
56
|
+
def parent_id
|
57
|
+
order_state.parent_id
|
58
|
+
end
|
59
|
+
|
60
|
+
def perm_id
|
61
|
+
order_state.perm_id
|
62
|
+
end
|
63
|
+
|
64
|
+
def local_id
|
65
|
+
order_state.local_id
|
66
|
+
end
|
67
|
+
|
68
|
+
alias order_id local_id
|
69
|
+
|
70
|
+
def status
|
71
|
+
order_state.status
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_human
|
75
|
+
"<OrderStatus: #{order_state}>"
|
76
|
+
end
|
77
|
+
|
78
|
+
end # class OrderStatus
|
79
|
+
end # module Incoming
|
80
|
+
end # module Messages
|
81
|
+
end # module IB
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
|
5
|
+
PortfolioValue = def_message [7, 7],
|
6
|
+
[:contract, :con_id, :int],
|
7
|
+
[:contract, :symbol, :string],
|
8
|
+
[:contract, :sec_type, :string],
|
9
|
+
[:contract, :expiry, :string],
|
10
|
+
[:contract, :strike, :decimal],
|
11
|
+
[:contract, :right, :string],
|
12
|
+
[:contract, :multiplier, :string],
|
13
|
+
[:contract, :primary_exchange, :string],
|
14
|
+
[:contract, :currency, :string],
|
15
|
+
[:contract, :local_symbol, :string],
|
16
|
+
[:position, :int],
|
17
|
+
[:market_price, :decimal],
|
18
|
+
[:market_value, :decimal],
|
19
|
+
[:average_cost, :decimal],
|
20
|
+
[:unrealized_pnl, :decimal_max], # May be nil!
|
21
|
+
[:realized_pnl, :decimal_max], # May be nil!
|
22
|
+
[:account_name, :string]
|
23
|
+
class PortfolioValue
|
24
|
+
|
25
|
+
def contract
|
26
|
+
@contract = IB::Contract.build @data[:contract]
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_human
|
30
|
+
"<PortfolioValue: #{contract.to_human} (#{position}): Market #{market_price}" +
|
31
|
+
" price #{market_value} value; PnL: #{unrealized_pnl} unrealized," +
|
32
|
+
" #{realized_pnl} realized; account #{account_name}>"
|
33
|
+
end
|
34
|
+
end # PortfolioValue
|
35
|
+
|
36
|
+
|
37
|
+
end # module Incoming
|
38
|
+
end # module Messages
|
39
|
+
end # module IB
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
|
5
|
+
# RealTimeBar contains following @data:
|
6
|
+
# :request_id - The ID of the *request* to which this is responding
|
7
|
+
# :time - The date-time stamp of the start of the bar. The format is offset in
|
8
|
+
# seconds from the beginning of 1970, same format as the UNIX epoch time
|
9
|
+
# :bar - received RT Bar
|
10
|
+
RealTimeBar = def_message [50, 3],
|
11
|
+
[:request_id, :int],
|
12
|
+
[:bar, :time, :int],
|
13
|
+
[:bar, :open, :decimal],
|
14
|
+
[:bar, :high, :decimal],
|
15
|
+
[:bar, :low, :decimal],
|
16
|
+
[:bar, :close, :decimal],
|
17
|
+
[:bar, :volume, :int],
|
18
|
+
[:bar, :wap, :decimal],
|
19
|
+
[:bar, :trades, :int]
|
20
|
+
class RealTimeBar
|
21
|
+
def bar
|
22
|
+
@bar = IB::Bar.new @data[:bar]
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_human
|
26
|
+
"<RealTimeBar: #{request_id} #{bar}>"
|
27
|
+
end
|
28
|
+
end # RealTimeBar
|
29
|
+
|
30
|
+
end # module Incoming
|
31
|
+
end # module Messages
|
32
|
+
end # module IB
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
|
5
|
+
# This method receives the requested market scanner data results.
|
6
|
+
# ScannerData contains following @data:
|
7
|
+
# :request_id - The ID of the request to which this row is responding
|
8
|
+
# :count - Number of data points returned (size of :results).
|
9
|
+
# :results - an Array of Hashes, each hash contains a set of
|
10
|
+
# data about one scanned Contract:
|
11
|
+
# :contract - a full description of the contract (details).
|
12
|
+
# :distance - Varies based on query.
|
13
|
+
# :benchmark - Varies based on query.
|
14
|
+
# :projection - Varies based on query.
|
15
|
+
# :legs - Describes combo legs when scan is returning EFP.
|
16
|
+
ScannerData = def_message [20, 3],
|
17
|
+
[:request_id, :int], # request id
|
18
|
+
[:count, :int]
|
19
|
+
class ScannerData
|
20
|
+
attr_accessor :results
|
21
|
+
|
22
|
+
def load
|
23
|
+
super
|
24
|
+
|
25
|
+
@results = Array.new(@data[:count]) do |_|
|
26
|
+
{:rank => socket.read_int,
|
27
|
+
:contract =>
|
28
|
+
Contract.build(
|
29
|
+
:con_id => socket.read_int,
|
30
|
+
:symbol => socket.read_string,
|
31
|
+
:sec_type => socket.read_string,
|
32
|
+
:expiry => socket.read_string,
|
33
|
+
:strike => socket.read_decimal,
|
34
|
+
:right => socket.read_string,
|
35
|
+
:exchange => socket.read_string,
|
36
|
+
:currency => socket.read_string,
|
37
|
+
:local_symbol => socket.read_string,
|
38
|
+
:contract_detail =>
|
39
|
+
IB::ContractDetail.new(
|
40
|
+
:market_name => socket.read_string,
|
41
|
+
:trading_class => socket.read_string)),
|
42
|
+
:distance => socket.read_string,
|
43
|
+
:benchmark => socket.read_string,
|
44
|
+
:projection => socket.read_string,
|
45
|
+
:legs => socket.read_string,
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end # ScannerData
|
50
|
+
|
51
|
+
end # module Incoming
|
52
|
+
end # module Messages
|
53
|
+
end # module IB
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# All message classes related to ticks located here
|
2
|
+
module IB
|
3
|
+
module Messages
|
4
|
+
module Incoming
|
5
|
+
|
6
|
+
class AbstractTick < AbstractMessage
|
7
|
+
# Returns Symbol with a meaningful name for received tick type
|
8
|
+
def type
|
9
|
+
TICK_TYPES[@data[:tick_type]]
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_human
|
13
|
+
"<#{self.message_type} #{type}:" +
|
14
|
+
@data.map do |key, value|
|
15
|
+
" #{key} #{value}" unless [:version, :ticker_id, :tick_type].include?(key)
|
16
|
+
end.compact.join(',') + " >"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# The IB code seems to dispatch up to two wrapped objects for this message, a tickPrice
|
21
|
+
# and sometimes a tickSize, which seems to be identical to the TICK_SIZE object.
|
22
|
+
#
|
23
|
+
# Important note from
|
24
|
+
# http://chuckcaplan.com/twsapi/index.php/void%20tickPrice%28%29 :
|
25
|
+
#
|
26
|
+
# "The low you get is NOT the low for the day as you'd expect it
|
27
|
+
# to be. It appears IB calculates the low based on all
|
28
|
+
# transactions after 4pm the previous day. The most inaccurate
|
29
|
+
# results occur when the stock moves up in the 4-6pm aftermarket
|
30
|
+
# on the previous day and then gaps open upward in the
|
31
|
+
# morning. The low you receive from TWS can be easily be several
|
32
|
+
# points different from the actual 9:30am-4pm low for the day in
|
33
|
+
# cases like this. If you require a correct traded low for the
|
34
|
+
# day, you can't get it from the TWS API. One possible source to
|
35
|
+
# help build the right data would be to compare against what Yahoo
|
36
|
+
# lists on finance.yahoo.com/q?s=ticker under the "Day's Range"
|
37
|
+
# statistics (be careful here, because Yahoo will use anti-Denial
|
38
|
+
# of Service techniques to hang your connection if you try to
|
39
|
+
# request too many bytes in a short period of time from them). For
|
40
|
+
# most purposes, a good enough approach would start by replacing
|
41
|
+
# the TWS low for the day with Yahoo's day low when you first
|
42
|
+
# start watching a stock ticker; let's call this time T. Then,
|
43
|
+
# update your internal low if the bid or ask tick you receive is
|
44
|
+
# lower than that for the remainder of the day. You should check
|
45
|
+
# against Yahoo again at time T+20min to handle the occasional
|
46
|
+
# case where the stock set a new low for the day in between
|
47
|
+
# T-20min (the real time your original quote was from, taking into
|
48
|
+
# account the delay) and time T. After that you should have a
|
49
|
+
# correct enough low for the rest of the day as long as you keep
|
50
|
+
# updating based on the bid/ask. It could still get slightly off
|
51
|
+
# in a case where a short transaction setting a new low appears in
|
52
|
+
# between ticks of data that TWS sends you. The high is probably
|
53
|
+
# distorted in the same way the low is, which would throw your
|
54
|
+
# results off if the stock traded after-hours and gapped down. It
|
55
|
+
# should be corrected in a similar way as described above if this
|
56
|
+
# is important to you."
|
57
|
+
#
|
58
|
+
# IB then emits at most 2 events on eWrapper:
|
59
|
+
# tickPrice( tickerId, tickType, price, canAutoExecute)
|
60
|
+
# tickSize( tickerId, sizeTickType, size)
|
61
|
+
TickPrice = def_message [1, 6], AbstractTick,
|
62
|
+
[:ticker_id, :int],
|
63
|
+
[:tick_type, :int],
|
64
|
+
[:price, :decimal],
|
65
|
+
[:size, :int],
|
66
|
+
[:can_auto_execute, :int]
|
67
|
+
|
68
|
+
TickSize = def_message [2, 6], AbstractTick,
|
69
|
+
[:ticker_id, :int],
|
70
|
+
[:tick_type, :int],
|
71
|
+
[:size, :int]
|
72
|
+
|
73
|
+
TickGeneric = def_message [45, 6], AbstractTick,
|
74
|
+
[:ticker_id, :int],
|
75
|
+
[:tick_type, :int],
|
76
|
+
[:value, :decimal]
|
77
|
+
|
78
|
+
TickString = def_message [46, 6], AbstractTick,
|
79
|
+
[:ticker_id, :int],
|
80
|
+
[:tick_type, :int],
|
81
|
+
[:value, :string]
|
82
|
+
|
83
|
+
TickEFP = def_message [47, 6], AbstractTick,
|
84
|
+
[:ticker_id, :int],
|
85
|
+
[:tick_type, :int],
|
86
|
+
[:basis_points, :decimal],
|
87
|
+
[:formatted_basis_points, :string],
|
88
|
+
[:implied_futures_price, :decimal],
|
89
|
+
[:hold_days, :int],
|
90
|
+
[:dividend_impact, :decimal],
|
91
|
+
[:dividends_to_expiry, :decimal]
|
92
|
+
|
93
|
+
# This message is received when the market in an option or its underlier moves.
|
94
|
+
# TWS option model volatilities, prices, and deltas, along with the present
|
95
|
+
# value of dividends expected on that options underlier are received.
|
96
|
+
# TickOption message contains following @data:
|
97
|
+
# :ticker_id - Id that was specified previously in the call to reqMktData()
|
98
|
+
# :tick_type - Specifies the type of option computation (see TICK_TYPES).
|
99
|
+
# :implied_volatility - The implied volatility calculated by the TWS option
|
100
|
+
# modeler, using the specified :tick_type value.
|
101
|
+
# :delta - The option delta value.
|
102
|
+
# :option_price - The option price.
|
103
|
+
# :pv_dividend - The present value of dividends expected on the options underlier
|
104
|
+
# :gamma - The option gamma value.
|
105
|
+
# :vega - The option vega value.
|
106
|
+
# :theta - The option theta value.
|
107
|
+
# :under_price - The price of the underlying.
|
108
|
+
TickOptionComputation = TickOption =
|
109
|
+
def_message([21, 6], AbstractTick,
|
110
|
+
[:ticker_id, :int],
|
111
|
+
[:tick_type, :int],
|
112
|
+
# What is the "not yet computed" indicator:
|
113
|
+
[:implied_volatility, :decimal_limit_1], # -1 and below
|
114
|
+
[:delta, :decimal_limit_2], # -2 and below
|
115
|
+
[:option_price, :decimal_limit_1], # -1 -"-
|
116
|
+
[:pv_dividend, :decimal_limit_1], # -1 -"-
|
117
|
+
[:gamma, :decimal_limit_2], # -2 -"-
|
118
|
+
[:vega, :decimal_limit_2], # -2 -"-
|
119
|
+
[:theta, :decimal_limit_2], # -2 -"-
|
120
|
+
[:under_price, :decimal_limit_1]) do
|
121
|
+
|
122
|
+
"<TickOption #{type} for #{:ticker_id}: underlying @ #{under_price}, "+
|
123
|
+
"option @ #{option_price}, IV #{implied_volatility}%, delta #{delta}, " +
|
124
|
+
"gamma #{gamma}, vega #{vega}, theta #{theta}, pv_dividend #{pv_dividend}>"
|
125
|
+
end
|
126
|
+
|
127
|
+
TickSnapshotEnd = def_message 57, [:ticker_id, :int]
|
128
|
+
|
129
|
+
end # module Incoming
|
130
|
+
end # module Messages
|
131
|
+
end # module IB
|
@@ -0,0 +1,331 @@
|
|
1
|
+
require 'ib/messages/outgoing/abstract_message'
|
2
|
+
|
3
|
+
# TODO: Don't instantiate messages, use their classes as just namespace for .encode/decode
|
4
|
+
|
5
|
+
module IB
|
6
|
+
module Messages
|
7
|
+
|
8
|
+
# Outgoing IB messages (sent to TWS/Gateway)
|
9
|
+
module Outgoing
|
10
|
+
extend Messages # def_message macros
|
11
|
+
|
12
|
+
### Defining (short) Outgoing Message classes for IB:
|
13
|
+
|
14
|
+
## Empty messages (no data)
|
15
|
+
|
16
|
+
# Request the open orders that were placed from THIS client. Each open order
|
17
|
+
# will be fed back through the OpenOrder and OrderStatus messages ONCE.
|
18
|
+
# NB: Client with a client_id of 0 will also receive the TWS-owned open orders.
|
19
|
+
# These orders will be associated with the client and a new orderId will be
|
20
|
+
# generated. This association will persist over multiple API and TWS sessions.
|
21
|
+
RequestOpenOrders = def_message 5
|
22
|
+
|
23
|
+
# Request the open orders placed from all clients and also from TWS. Each open
|
24
|
+
# order will be fed back through the OpenOrder and OrderStatus messages ONCE.
|
25
|
+
# Note this does not re-bind those Orders to requesting Client!
|
26
|
+
# Use RequestAutoOpenOrders to request such re-binding.
|
27
|
+
RequestAllOpenOrders = def_message 16
|
28
|
+
|
29
|
+
# Request that newly created TWS orders be implicitly associated with this client.
|
30
|
+
# When a new TWS order is created, the order will be associated with this client
|
31
|
+
# and automatically fed back through the OpenOrder and OrderStatus messages.
|
32
|
+
# It is a 'continuous' request such that it gets turned 'on' when called with a
|
33
|
+
# TRUE auto_bind parameter. When it's called with FALSE auto_bind, new TWS orders
|
34
|
+
# will not bind to this client going forward. Note that TWS orders can only be
|
35
|
+
# bound to clients with a client_id of 0. TODO: how to properly test this?
|
36
|
+
# data = { :auto_bind => boolean }
|
37
|
+
RequestAutoOpenOrders = def_message 15, :auto_bind
|
38
|
+
|
39
|
+
# Requests an XML document that describes the valid parameters that a scanner
|
40
|
+
# subscription can have (for outgoing RequestScannerSubscription message).
|
41
|
+
RequestScannerParameters = def_message 24
|
42
|
+
|
43
|
+
CancelNewsBulletins = def_message 13
|
44
|
+
RequestManagedAccounts = def_message 17
|
45
|
+
RequestCurrentTime = def_message 49
|
46
|
+
RequestGlobalCancel = def_message 58
|
47
|
+
|
48
|
+
## Data format is: @data = { :id => ticker_id}
|
49
|
+
CancelMarketData = def_message 2
|
50
|
+
CancelMarketDepth = def_message 11
|
51
|
+
CancelScannerSubscription = def_message 23
|
52
|
+
CancelHistoricalData = def_message 25
|
53
|
+
CancelRealTimeBars = def_message 51
|
54
|
+
|
55
|
+
## Data format is: @data = { :id => request_id }
|
56
|
+
CancelFundamentalData = def_message 53
|
57
|
+
CancelCalculateImpliedVolatility = CancelImpliedVolatility = def_message(56)
|
58
|
+
CancelCalculateOptionPrice = CancelOptionPrice = def_message(57)
|
59
|
+
|
60
|
+
## Data format is: @data ={ :id => local_id of order to cancel }
|
61
|
+
CancelOrder = def_message 4
|
62
|
+
|
63
|
+
# Request the next valid ID that can be used when placing an order. Responds with
|
64
|
+
# NextValidId message, and the id returned is that next valid Id for orders.
|
65
|
+
# That ID will reflect any autobinding that has occurred (which generates new
|
66
|
+
# IDs and increments the next valid ID therein).
|
67
|
+
# @data = { :number of ids requested => int } NB: :number option is ignored by TWS!
|
68
|
+
RequestIds = def_message 8, [:number, 1]
|
69
|
+
# data = { :all_messages => boolean }
|
70
|
+
RequestNewsBulletins = def_message 12, :all_messages
|
71
|
+
# data = { :log_level => int }
|
72
|
+
SetServerLoglevel = def_message 14, :log_level
|
73
|
+
# data = { :fa_data_type => int }
|
74
|
+
RequestFA = def_message 18, :fa_data_type
|
75
|
+
# data = { :fa_data_type => int, :xml => String }
|
76
|
+
ReplaceFA = def_message 19, :fa_data_type, :xml
|
77
|
+
# data = { :market_data_type => int }
|
78
|
+
|
79
|
+
# @data = { :subscribe => boolean,
|
80
|
+
# :account_code => Advisor accounts only. Empty ('') for a standard account. }
|
81
|
+
RequestAccountUpdates = RequestAccountData = def_message([6, 2],
|
82
|
+
[:subscribe, true],
|
83
|
+
:account_code)
|
84
|
+
|
85
|
+
# data => { :id => request_id (int), :contract => Contract }
|
86
|
+
#
|
87
|
+
# Special case for options: "wildcards" in the Contract fields retrieve Option chains
|
88
|
+
# strike = 0 means all strikes
|
89
|
+
# right = "" meanns both call and put
|
90
|
+
# expiry = "" means all expiries
|
91
|
+
# expiry = "2013" means all expiries in 2013
|
92
|
+
# expiry = "201311" means all expiries in Nov 2013
|
93
|
+
# You'll get several ContractData (10) messages back if there is more than one match.
|
94
|
+
# When all the matches are delivered you'll get ContractDataEnd (52) message.
|
95
|
+
RequestContractDetails = RequestContractData =
|
96
|
+
def_message([9, 6],
|
97
|
+
[:contract, :serialize_short, [:con_id, :include_expired, :sec_id]])
|
98
|
+
|
99
|
+
# data = { :id => ticker_id (int), :contract => Contract, :num_rows => int }
|
100
|
+
RequestMarketDepth = def_message([10, 3],
|
101
|
+
[:contract, :serialize_short, []],
|
102
|
+
:num_rows)
|
103
|
+
|
104
|
+
# When this message is sent, TWS responds with ExecutionData messages, each
|
105
|
+
# containing the execution report that meets the specified criteria.
|
106
|
+
# @data={:id => int: :request_id,
|
107
|
+
# :client_id => int: Filter the results based on the clientId.
|
108
|
+
# :acct_code => Filter the results based on based on account code.
|
109
|
+
# Note: this is only relevant for Financial Advisor accts.
|
110
|
+
# :sec_type => Filter the results based on the order security type.
|
111
|
+
# :time => Filter the results based on execution reports received
|
112
|
+
# after the specified time - format "yyyymmdd-hh:mm:ss"
|
113
|
+
# :symbol => Filter the results based on the order symbol.
|
114
|
+
# :exchange => Filter the results based on the order exchange
|
115
|
+
# :side => Filter the results based on the order action: BUY/SELL/SSHORT
|
116
|
+
RequestExecutions = def_message([7, 3],
|
117
|
+
:client_id,
|
118
|
+
:acct_code,
|
119
|
+
:time, # Format "yyyymmdd-hh:mm:ss"
|
120
|
+
:symbol,
|
121
|
+
:sec_type,
|
122
|
+
:exchange,
|
123
|
+
:side)
|
124
|
+
|
125
|
+
# data = { :id => ticker_id (int),
|
126
|
+
# :contract => IB::Contract,
|
127
|
+
# :exercise_action => int, 1 = exercise, 2 = lapse
|
128
|
+
# :exercise_quantity => int, The number of contracts to be exercised
|
129
|
+
# :account => string,
|
130
|
+
# :override => int: Specifies whether your setting will override the
|
131
|
+
# system's natural action. For example, if your action
|
132
|
+
# is "exercise" and the option is not in-the-money, by
|
133
|
+
# natural action the option would not exercise. If you
|
134
|
+
# have override set to "yes" the natural action would be
|
135
|
+
# overridden and the out-of-the money option would be
|
136
|
+
# exercised. Values are:
|
137
|
+
# - 0 = do not override
|
138
|
+
# - 1 = override
|
139
|
+
ExerciseOptions = def_message(21,
|
140
|
+
[:contract, :serialize_short],
|
141
|
+
:exercise_action,
|
142
|
+
:exercise_quantity,
|
143
|
+
:account,
|
144
|
+
:override)
|
145
|
+
|
146
|
+
# @data={:id => int: ticker_id - Must be a unique value. When the market data
|
147
|
+
# returns, it will be identified by this tag,
|
148
|
+
# :contract => IB::Contract, requested contract.
|
149
|
+
# :tick_list => String: comma delimited list of requested tick groups:
|
150
|
+
# Group ID - Description - Requested Tick Types
|
151
|
+
# 100 - Option Volume (currently for stocks) - 29, 30
|
152
|
+
# 101 - Option Open Interest (currently for stocks) - 27, 28
|
153
|
+
# 104 - Historical Volatility (currently for stocks) - 23
|
154
|
+
# 106 - Option Implied Volatility (currently for stocks) - 24
|
155
|
+
# 162 - Index Future Premium - 31
|
156
|
+
# 165 - Miscellaneous Stats - 15, 16, 17, 18, 19, 20, 21
|
157
|
+
# 221 - Mark Price (used in TWS P&L computations) - 37
|
158
|
+
# 225 - Auction values (volume, price and imbalance) - 34, 35, 36
|
159
|
+
# 233 - RTVolume - 48
|
160
|
+
# 236 - Shortable - 46
|
161
|
+
# 256 - Inventory - ?
|
162
|
+
# 258 - Fundamental Ratios - 47
|
163
|
+
# 411 - Realtime Historical Volatility - 58
|
164
|
+
# :snapshot => bool: Check to return a single snapshot of market data and
|
165
|
+
# have the market data subscription canceled. Do not enter any
|
166
|
+
# :tick_list values if you use snapshot. }
|
167
|
+
RequestMarketData =
|
168
|
+
def_message([1, 9],
|
169
|
+
[:contract, :serialize_long, [:con_id]],
|
170
|
+
[:contract, :serialize_legs, []],
|
171
|
+
[:contract, :serialize_under_comp, []],
|
172
|
+
[:tick_list, lambda do |tick_list|
|
173
|
+
tick_list.is_a?(Array) ? tick_list.join(',') : (tick_list || '')
|
174
|
+
end, []],
|
175
|
+
[:snapshot, false])
|
176
|
+
|
177
|
+
# The API can receive frozen market data from Trader Workstation. Frozen market
|
178
|
+
# data is the last data recorded in our system. During normal trading hours,
|
179
|
+
# the API receives real-time market data. If you use this function, you are
|
180
|
+
# telling TWS to automatically switch to frozen market data AFTER the close.
|
181
|
+
# Then, before the opening of the next trading day, market data will automatically
|
182
|
+
# switch back to real-time market data.
|
183
|
+
# :market_data_type = 1 for real-time streaming, 2 for frozen market data
|
184
|
+
RequestMarketDataType =
|
185
|
+
def_message 59, [:market_data_type,
|
186
|
+
lambda { |type| MARKET_DATA_TYPES.invert[type] || type }, []]
|
187
|
+
|
188
|
+
# Send this message to receive Reuters global fundamental data. There must be
|
189
|
+
# a subscription to Reuters Fundamental set up in Account Management before
|
190
|
+
# you can receive this data.
|
191
|
+
# data = { :id => int: :request_id,
|
192
|
+
# :contract => Contract,
|
193
|
+
# :report_type => String: one of the following:
|
194
|
+
# 'estimates' - Estimates
|
195
|
+
# 'finstat' - Financial statements
|
196
|
+
# 'snapshot' - Summary }
|
197
|
+
RequestFundamentalData =
|
198
|
+
def_message(52,
|
199
|
+
[:contract, :serialize, [:primary_exchange]],
|
200
|
+
:report_type)
|
201
|
+
|
202
|
+
# data = { :request_id => int, :contract => Contract,
|
203
|
+
# :option_price => double, :under_price => double }
|
204
|
+
RequestCalculateImpliedVolatility = CalculateImpliedVolatility =
|
205
|
+
RequestImpliedVolatility =
|
206
|
+
def_message(54,
|
207
|
+
[:contract, :serialize_long, [:con_id]],
|
208
|
+
:option_price,
|
209
|
+
:under_price)
|
210
|
+
|
211
|
+
# data = { :request_id => int, :contract => Contract,
|
212
|
+
# :volatility => double, :under_price => double }
|
213
|
+
RequestCalculateOptionPrice = CalculateOptionPrice = RequestOptionPrice =
|
214
|
+
def_message(55,
|
215
|
+
[:contract, :serialize_long, [:con_id]],
|
216
|
+
:volatility,
|
217
|
+
:under_price)
|
218
|
+
|
219
|
+
# Start receiving market scanner results through the ScannerData messages.
|
220
|
+
# @data = { :id => ticker_id (int),
|
221
|
+
# :number_of_rows => int: number of rows of data to return for a query.
|
222
|
+
# :instrument => The instrument type for the scan. Values include
|
223
|
+
# 'STK', - US stocks
|
224
|
+
# 'STOCK.HK' - Asian stocks
|
225
|
+
# 'STOCK.EU' - European stocks
|
226
|
+
# :location_code => Legal Values include:
|
227
|
+
# - STK.US - US stocks
|
228
|
+
# - STK.US.MAJOR - US stocks (without pink sheet)
|
229
|
+
# - STK.US.MINOR - US stocks (only pink sheet)
|
230
|
+
# - STK.HK.SEHK - Hong Kong stocks
|
231
|
+
# - STK.HK.ASX - Australian Stocks
|
232
|
+
# - STK.EU - European stocks
|
233
|
+
# :scan_code => The type of the scan, such as HIGH_OPT_VOLUME_PUT_CALL_RATIO.
|
234
|
+
# :above_price => double: Only contracts with a price above this value.
|
235
|
+
# :below_price => double: Only contracts with a price below this value.
|
236
|
+
# :above_volume => int: Only contracts with a volume above this value.
|
237
|
+
# :market_cap_above => double: Only contracts with a market cap above this
|
238
|
+
# :market_cap_below => double: Only contracts with a market cap below this value.
|
239
|
+
# :moody_rating_above => Only contracts with a Moody rating above this value.
|
240
|
+
# :moody_rating_below => Only contracts with a Moody rating below this value.
|
241
|
+
# :sp_rating_above => Only contracts with an S&P rating above this value.
|
242
|
+
# :sp_rating_below => Only contracts with an S&P rating below this value.
|
243
|
+
# :maturity_date_above => Only contracts with a maturity date later than this
|
244
|
+
# :maturity_date_below => Only contracts with a maturity date earlier than this
|
245
|
+
# :coupon_rate_above => double: Only contracts with a coupon rate above this
|
246
|
+
# :coupon_rate_below => double: Only contracts with a coupon rate below this
|
247
|
+
# :exclude_convertible => Exclude convertible bonds.
|
248
|
+
# :scanner_setting_pairs => Used with the scan_code to help further narrow your query.
|
249
|
+
# Scanner Setting Pairs are delimited by slashes, making
|
250
|
+
# this parameter open ended. Example is "Annual,true" -
|
251
|
+
# when used with 'Top Option Implied Vol % Gainers' scan
|
252
|
+
# would return annualized volatilities.
|
253
|
+
# :average_option_volume_above => int: Only contracts with average volume above this
|
254
|
+
# :stock_type_filter => Valid values are:
|
255
|
+
# 'ALL' (excludes nothing)
|
256
|
+
# 'STOCK' (excludes ETFs)
|
257
|
+
# 'ETF' (includes ETFs) }
|
258
|
+
# ------------
|
259
|
+
# To learn all valid parameter values that a scanner subscription can have,
|
260
|
+
# first subscribe to ScannerParameters and send RequestScannerParameters message.
|
261
|
+
# Available scanner parameters values will be listed in received XML document.
|
262
|
+
RequestScannerSubscription =
|
263
|
+
def_message([22, 3],
|
264
|
+
[:number_of_rows, -1], # was: EOL,
|
265
|
+
:instrument,
|
266
|
+
:location_code,
|
267
|
+
:scan_code,
|
268
|
+
:above_price,
|
269
|
+
:below_price,
|
270
|
+
:above_volume,
|
271
|
+
:market_cap_above,
|
272
|
+
:market_cap_below,
|
273
|
+
:moody_rating_above,
|
274
|
+
:moody_rating_below,
|
275
|
+
:sp_rating_above,
|
276
|
+
:sp_rating_below,
|
277
|
+
:maturity_date_above,
|
278
|
+
:maturity_date_below,
|
279
|
+
:coupon_rate_above,
|
280
|
+
:coupon_rate_below,
|
281
|
+
:exclude_convertible,
|
282
|
+
:average_option_volume_above, # ?
|
283
|
+
:scanner_setting_pairs,
|
284
|
+
:stock_type_filter)
|
285
|
+
|
286
|
+
require 'ib/messages/outgoing/place_order'
|
287
|
+
require 'ib/messages/outgoing/bar_requests'
|
288
|
+
|
289
|
+
end # module Outgoing
|
290
|
+
end # module Messages
|
291
|
+
end # module IB
|
292
|
+
|
293
|
+
__END__
|
294
|
+
|
295
|
+
// outgoing msg id's
|
296
|
+
private static final int REQ_MKT_DATA = 1;
|
297
|
+
private static final int CANCEL_MKT_DATA = 2;
|
298
|
+
private static final int PLACE_ORDER = 3;
|
299
|
+
private static final int CANCEL_ORDER = 4;
|
300
|
+
private static final int REQ_OPEN_ORDERS = 5;
|
301
|
+
private static final int REQ_ACCOUNT_DATA = 6;
|
302
|
+
private static final int REQ_EXECUTIONS = 7;
|
303
|
+
private static final int REQ_IDS = 8;
|
304
|
+
private static final int REQ_CONTRACT_DATA = 9;
|
305
|
+
private static final int REQ_MKT_DEPTH = 10;
|
306
|
+
private static final int CANCEL_MKT_DEPTH = 11;
|
307
|
+
private static final int REQ_NEWS_BULLETINS = 12;
|
308
|
+
private static final int CANCEL_NEWS_BULLETINS = 13;
|
309
|
+
private static final int SET_SERVER_LOGLEVEL = 14;
|
310
|
+
private static final int REQ_AUTO_OPEN_ORDERS = 15;
|
311
|
+
private static final int REQ_ALL_OPEN_ORDERS = 16;
|
312
|
+
private static final int REQ_MANAGED_ACCTS = 17;
|
313
|
+
private static final int REQ_FA = 18;
|
314
|
+
private static final int REPLACE_FA = 19;
|
315
|
+
private static final int REQ_HISTORICAL_DATA = 20;
|
316
|
+
private static final int EXERCISE_OPTIONS = 21;
|
317
|
+
private static final int REQ_SCANNER_SUBSCRIPTION = 22;
|
318
|
+
private static final int CANCEL_SCANNER_SUBSCRIPTION = 23;
|
319
|
+
private static final int REQ_SCANNER_PARAMETERS = 24;
|
320
|
+
private static final int CANCEL_HISTORICAL_DATA = 25;
|
321
|
+
private static final int REQ_CURRENT_TIME = 49;
|
322
|
+
private static final int REQ_REAL_TIME_BARS = 50;
|
323
|
+
private static final int CANCEL_REAL_TIME_BARS = 51;
|
324
|
+
private static final int REQ_FUNDAMENTAL_DATA = 52;
|
325
|
+
private static final int CANCEL_FUNDAMENTAL_DATA = 53;
|
326
|
+
private static final int REQ_CALC_IMPLIED_VOLAT = 54;
|
327
|
+
private static final int REQ_CALC_OPTION_PRICE = 55;
|
328
|
+
private static final int CANCEL_CALC_IMPLIED_VOLAT = 56;
|
329
|
+
private static final int CANCEL_CALC_OPTION_PRICE = 57;
|
330
|
+
private static final int REQ_GLOBAL_CANCEL = 58;
|
331
|
+
private static final int REQ_MARKET_DATA_TYPE = 59;
|