ib-api 972.0
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/.gitignore +50 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +105 -0
- data/Guardfile +24 -0
- data/LICENSE +674 -0
- data/README.md +65 -0
- data/Rakefile +11 -0
- data/VERSION +1 -0
- data/api.gemspec +43 -0
- data/bin/console +95 -0
- data/bin/console.yml +3 -0
- data/bin/setup +8 -0
- data/changelog.md +7 -0
- data/example/README.md +76 -0
- data/example/account_info +54 -0
- data/example/account_positions +30 -0
- data/example/account_summary +88 -0
- data/example/cancel_orders +74 -0
- data/example/fa_accounts +25 -0
- data/example/fundamental_data +40 -0
- data/example/historic_data_cli +186 -0
- data/example/list_orders +45 -0
- data/example/portfolio_csv +81 -0
- data/example/scanner_data +62 -0
- data/example/template +19 -0
- data/example/tick_data +28 -0
- data/lib/extensions/class-extensions.rb +87 -0
- data/lib/ib-api.rb +7 -0
- data/lib/ib/base.rb +103 -0
- data/lib/ib/base_properties.rb +160 -0
- data/lib/ib/connection.rb +450 -0
- data/lib/ib/constants.rb +393 -0
- data/lib/ib/errors.rb +44 -0
- data/lib/ib/logger.rb +26 -0
- data/lib/ib/messages.rb +99 -0
- data/lib/ib/messages/abstract_message.rb +101 -0
- data/lib/ib/messages/incoming.rb +251 -0
- data/lib/ib/messages/incoming/abstract_message.rb +116 -0
- data/lib/ib/messages/incoming/account_value.rb +78 -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 +50 -0
- data/lib/ib/messages/incoming/historical_data.rb +84 -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 +277 -0
- data/lib/ib/messages/incoming/order_status.rb +85 -0
- data/lib/ib/messages/incoming/portfolio_value.rb +78 -0
- data/lib/ib/messages/incoming/real_time_bar.rb +32 -0
- data/lib/ib/messages/incoming/scanner_data.rb +54 -0
- data/lib/ib/messages/incoming/ticks.rb +268 -0
- data/lib/ib/messages/outgoing.rb +437 -0
- data/lib/ib/messages/outgoing/abstract_message.rb +88 -0
- data/lib/ib/messages/outgoing/account_requests.rb +112 -0
- data/lib/ib/messages/outgoing/bar_requests.rb +250 -0
- data/lib/ib/messages/outgoing/place_order.rb +209 -0
- data/lib/ib/messages/outgoing/request_marketdata.rb +99 -0
- data/lib/ib/messages/outgoing/request_tick_data.rb +21 -0
- data/lib/ib/model.rb +4 -0
- data/lib/ib/models.rb +14 -0
- data/lib/ib/server_versions.rb +114 -0
- data/lib/ib/socket.rb +185 -0
- data/lib/ib/support.rb +160 -0
- data/lib/ib/version.rb +6 -0
- data/lib/models/ib/account.rb +85 -0
- data/lib/models/ib/account_value.rb +33 -0
- data/lib/models/ib/bag.rb +55 -0
- data/lib/models/ib/bar.rb +31 -0
- data/lib/models/ib/combo_leg.rb +105 -0
- data/lib/models/ib/condition.rb +245 -0
- data/lib/models/ib/contract.rb +415 -0
- data/lib/models/ib/contract_detail.rb +108 -0
- data/lib/models/ib/execution.rb +67 -0
- data/lib/models/ib/forex.rb +13 -0
- data/lib/models/ib/future.rb +15 -0
- data/lib/models/ib/index.rb +15 -0
- data/lib/models/ib/option.rb +78 -0
- data/lib/models/ib/option_detail.rb +55 -0
- data/lib/models/ib/order.rb +519 -0
- data/lib/models/ib/order_state.rb +152 -0
- data/lib/models/ib/portfolio_value.rb +64 -0
- data/lib/models/ib/stock.rb +16 -0
- data/lib/models/ib/underlying.rb +34 -0
- data/lib/models/ib/vertical.rb +96 -0
- data/lib/requires.rb +12 -0
- metadata +203 -0
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'ib/messages/abstract_message'
|
2
|
+
require 'ib/support'
|
3
|
+
require 'ox'
|
4
|
+
module IB
|
5
|
+
module Messages
|
6
|
+
module Incoming
|
7
|
+
using IBSupport # refine Array-method for decoding of IB-Messages
|
8
|
+
|
9
|
+
|
10
|
+
# Container for specific message classes, keyed by their message_ids
|
11
|
+
Classes = {}
|
12
|
+
|
13
|
+
class AbstractMessage < IB::Messages::AbstractMessage
|
14
|
+
|
15
|
+
attr_accessor :buffer # is an array
|
16
|
+
|
17
|
+
def version # Per message, received messages may have the different versions
|
18
|
+
@data[:version]
|
19
|
+
end
|
20
|
+
|
21
|
+
def check_version actual, expected
|
22
|
+
unless actual == expected || expected.is_a?(Array) && expected.include?(actual)
|
23
|
+
puts self.class.name
|
24
|
+
error "Unsupported version #{actual} received, expected #{expected}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Create incoming message from a given source (IB Socket or data Hash)
|
29
|
+
def initialize source
|
30
|
+
@created_at = Time.now
|
31
|
+
if source.is_a?(Hash) # Source is a @data Hash
|
32
|
+
@data = source
|
33
|
+
@buffer =[] # initialize empty buffer, indicates a successfull initializing
|
34
|
+
else
|
35
|
+
@buffer = source
|
36
|
+
### DEBUG DEBUG DEBUG RAW STREAM ###############
|
37
|
+
# if uncommented, the raw-input from the tws is included in the logging
|
38
|
+
# puts "BUFFER :> #{buffer.inspect} "
|
39
|
+
### DEBUG DEBUG DEBUG RAW STREAM ###############
|
40
|
+
@data = Hash.new
|
41
|
+
self.load
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def valid?
|
46
|
+
@buffer.empty?
|
47
|
+
end
|
48
|
+
|
49
|
+
## more recent messages omit the transmission of a version
|
50
|
+
## thus just load the parameter-map
|
51
|
+
def simple_load
|
52
|
+
load_map *self.class.data_map
|
53
|
+
rescue IB::Error => e
|
54
|
+
error "Reading #{self.class}: #{e.class}: #{e.message}", :load, e.backtrace
|
55
|
+
end
|
56
|
+
# Every message loads received message version first
|
57
|
+
# Override the load method in your subclass to do actual reading into @data.
|
58
|
+
def load
|
59
|
+
unless self.class.version.zero?
|
60
|
+
@data[:version] = buffer.read_int
|
61
|
+
check_version @data[:version], self.class.version
|
62
|
+
end
|
63
|
+
simple_load
|
64
|
+
end
|
65
|
+
|
66
|
+
# Load @data from the buffer according to the given data map.
|
67
|
+
#
|
68
|
+
# map is a series of Arrays in the format of
|
69
|
+
# [ :name, :type ], [ :group, :name, :type]
|
70
|
+
# type identifiers must have a corresponding read_type method on the buffer-class (read_int, etc.).
|
71
|
+
# group is used to lump together aggregates, such as Contract or Order fields
|
72
|
+
def load_map(*map)
|
73
|
+
map.each do |instruction|
|
74
|
+
# We determine the function of the first element
|
75
|
+
head = instruction.first
|
76
|
+
case head
|
77
|
+
when Integer # >= Version condition: [ min_version, [map]]
|
78
|
+
load_map *instruction.drop(1) if version >= head
|
79
|
+
|
80
|
+
when Proc # Callable condition: [ condition, [map]]
|
81
|
+
load_map *instruction.drop(1) if head.call
|
82
|
+
|
83
|
+
when true # Pre-condition already succeeded!
|
84
|
+
load_map *instruction.drop(1)
|
85
|
+
|
86
|
+
when nil, false # Pre-condition already failed! Do nothing...
|
87
|
+
|
88
|
+
when Symbol # Normal map
|
89
|
+
group, name, type, block =
|
90
|
+
if instruction[2].nil? || instruction[2].is_a?(Proc) # lambda's are Proc's
|
91
|
+
[nil] + instruction # No group, [ :name, :type, (:block) ]
|
92
|
+
else
|
93
|
+
instruction # [ :group, :name, :type, (:block)]
|
94
|
+
end
|
95
|
+
begin
|
96
|
+
data = @buffer.__send__("read_#{type}", &block)
|
97
|
+
rescue IB::LoadError, NoMethodError => e
|
98
|
+
error "Reading #{self.class}: #{e.class}: #{e.message} --> Instruction: #{name}" , :reader, false
|
99
|
+
end
|
100
|
+
# debug puts data.inspect
|
101
|
+
if group
|
102
|
+
@data[group] ||= {}
|
103
|
+
@data[group][name] = data
|
104
|
+
else
|
105
|
+
@data[name] = data
|
106
|
+
end
|
107
|
+
else
|
108
|
+
error "Unrecognized instruction #{instruction}"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end # class AbstractMessage
|
114
|
+
end # module Incoming
|
115
|
+
end # module Messages
|
116
|
+
end # module IB
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
|
5
|
+
AccountUpdateTime = def_message 8, [:time_stamp, :string]
|
6
|
+
|
7
|
+
ManagedAccounts =
|
8
|
+
def_message 15, [:accounts_list, :string]
|
9
|
+
|
10
|
+
class ManagedAccounts
|
11
|
+
def accounts
|
12
|
+
accounts_list.split(',').map{|a| Account.new account: a}
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_human
|
16
|
+
"< ManagedAccounts: #{accounts.map(&:account).join(" - ")}>"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Receives previously requested FA configuration information from TWS.
|
21
|
+
ReceiveFA =
|
22
|
+
def_message 16, [:type, :int], # type of Financial Advisor configuration data
|
23
|
+
# being received from TWS. Valid values include:
|
24
|
+
# 1 = GROUPS, 2 = PROFILE, 3 = ACCOUNT ALIASES
|
25
|
+
[:xml, :xml] # XML string with requested FA configuration information.
|
26
|
+
|
27
|
+
class ReceiveFA
|
28
|
+
def accounts
|
29
|
+
xml[:ListOfAccountAliases][:AccountAlias].map{|x| Account.new x }
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_human
|
33
|
+
"<FA: #{accounts.map(&:to_human).join(" - ")}>"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
class AccountMessage < AbstractMessage
|
40
|
+
def account_value
|
41
|
+
@account_value = IB::AccountValue.new @data[:account_value]
|
42
|
+
end
|
43
|
+
def account_name
|
44
|
+
@account_name = @data[:account]
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_human
|
48
|
+
"<AccountValue: #{account_name}, #{account_value}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
AccountSummary = def_message(63, AccountMessage,
|
52
|
+
[:request_id, :int],
|
53
|
+
[ :account, :string ],
|
54
|
+
[:account_value, :key, :symbol],
|
55
|
+
[:account_value, :value, :string],
|
56
|
+
[:account_value, :currency, :string]
|
57
|
+
)
|
58
|
+
AccountSummaryEnd = def_message(64)
|
59
|
+
|
60
|
+
AccountValue = def_message([6, 2], AccountMessage,
|
61
|
+
[:account_value, :key, :symbol],
|
62
|
+
[:account_value, :value, :string],
|
63
|
+
[:account_value, :currency, :string],
|
64
|
+
[:account, :string])
|
65
|
+
|
66
|
+
|
67
|
+
AccountUpdatesMulti = def_message( 73,
|
68
|
+
[ :request_id, :int ],
|
69
|
+
[ :account , :string ],
|
70
|
+
[ :model, :string ],
|
71
|
+
[ :key , :string ],
|
72
|
+
[ :value , :decimal],
|
73
|
+
[ :currency, :string ])
|
74
|
+
|
75
|
+
AccountUpdatesMultiEnd = def_message 74
|
76
|
+
end # module Incoming
|
77
|
+
end # module Messages
|
78
|
+
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,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], ## next the major contract-fields
|
12
|
+
[:contract, :sec_type, :string], ## are transmitted
|
13
|
+
[:contract, :last_trading_day, :date], ## difference to the array.get_contract
|
14
|
+
[:contract, :strike, :decimal], ## method: con_id is transmitted
|
15
|
+
[:contract, :right, :string], ## AFTER the main fields
|
16
|
+
[:contract, :exchange, :string], ##
|
17
|
+
[:contract, :currency, :string], ## thus we have to read the fields separately
|
18
|
+
[:contract, :local_symbol, :string],
|
19
|
+
[:contract_detail, :market_name, :string], ## extended
|
20
|
+
[:contract, :trading_class, :string], ## new Version 8
|
21
|
+
[:contract, :con_id, :int],
|
22
|
+
[:contract_detail, :min_tick, :decimal],
|
23
|
+
[:contract_detail, :md_size_multiplier, :int],
|
24
|
+
[:contract, :multiplier, :int],
|
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
|
+
[:contract_detail, :sec_id_list,:hash],
|
41
|
+
[:contract_detail, :agg_group, :int ],
|
42
|
+
[:contract_detail, :under_symbol, :string ],
|
43
|
+
[:contract_detail, :under_sec_type, :string ],
|
44
|
+
[:contract_detail, :market_rule_ids, :string ],
|
45
|
+
[:contract_detail, :real_expiration_date, :date ]
|
46
|
+
)
|
47
|
+
#
|
48
|
+
#
|
49
|
+
class ContractData
|
50
|
+
using IBSupport # defines tws-method for Array (socket.rb)
|
51
|
+
def contract
|
52
|
+
@contract = IB::Contract.build @data[:contract].merge(:contract_detail => contract_detail)
|
53
|
+
end
|
54
|
+
|
55
|
+
def contract_detail
|
56
|
+
@contract_detail = IB::ContractDetail.new @data[:contract_detail]
|
57
|
+
end
|
58
|
+
|
59
|
+
alias contract_details contract_detail
|
60
|
+
|
61
|
+
def to_human
|
62
|
+
"<Contract #{contract.to_human} #{contract_detail.to_human}>"
|
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,50 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
|
5
|
+
ExecutionData =
|
6
|
+
def_message [11, 0] , # [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, :contract],
|
11
|
+
[:execution, :exec_id, :string], # Weird format
|
12
|
+
[:execution, :time, :datetime],
|
13
|
+
[:execution, :account_name, :string],
|
14
|
+
[:execution, :exchange, :string],
|
15
|
+
[:execution, :side, :string],
|
16
|
+
[:execution, :quantity, :decimal],
|
17
|
+
[:execution, :price, :decimal],
|
18
|
+
[:execution, :perm_id, :int],
|
19
|
+
[:execution, :client_id, :int],
|
20
|
+
[:execution, :liquidation, :int],
|
21
|
+
[:execution, :cumulative_quantity, :int],
|
22
|
+
[:execution, :average_price, :decimal],
|
23
|
+
[:execution, :order_ref, :string],
|
24
|
+
[:execution, :ev_rule, :string],
|
25
|
+
[:execution, :ev_multiplier, :decimal],
|
26
|
+
[:execution, :model_code, :string],
|
27
|
+
[:execution, :last_liquidity, :int]
|
28
|
+
|
29
|
+
class ExecutionData
|
30
|
+
|
31
|
+
def load
|
32
|
+
simple_load
|
33
|
+
end
|
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 to_human
|
44
|
+
"<ExecutionData #{request_id}: #{contract.to_human}, #{execution}>"
|
45
|
+
end
|
46
|
+
|
47
|
+
end # ExecutionData
|
48
|
+
end # module Incoming
|
49
|
+
end # module Messages
|
50
|
+
end # module IB
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module IB
|
2
|
+
module Messages
|
3
|
+
module Incoming
|
4
|
+
|
5
|
+
# HistoricalData contains following @data:
|
6
|
+
#
|
7
|
+
# _General_:
|
8
|
+
#
|
9
|
+
# - request_id - The ID of the request to which this is responding
|
10
|
+
# - count - Number of Historical data points returned (size of :results).
|
11
|
+
# - results - an Array of Historical Data Bars
|
12
|
+
# - start_date - beginning of returned Historical data period
|
13
|
+
# - end_date - end of returned Historical data period
|
14
|
+
#
|
15
|
+
# Each returned Bar in @data[:results] Array contains this data:
|
16
|
+
# - date - The date-time stamp of the start of the bar. The format is set to sec since EPOCHE
|
17
|
+
# in outgoing/bar_requests ReqHistoricalData.
|
18
|
+
# - open - The bar opening price.
|
19
|
+
# - high - The high price during the time covered by the bar.
|
20
|
+
# - low - The low price during the time covered by the bar.
|
21
|
+
# - close - The bar closing price.
|
22
|
+
# - volume - The volume during the time covered by the bar.
|
23
|
+
# - trades - When TRADES historical data is returned, represents number of trades
|
24
|
+
# that occurred during the time period the bar covers
|
25
|
+
# - wap - The weighted average price during the time covered by the bar.
|
26
|
+
|
27
|
+
|
28
|
+
HistoricalData = def_message [17,0],
|
29
|
+
[:request_id, :int],
|
30
|
+
[:start_date, :datetime],
|
31
|
+
[:end_date, :datetime],
|
32
|
+
[:count, :int]
|
33
|
+
class HistoricalData
|
34
|
+
attr_accessor :results
|
35
|
+
using IBSupport # extended Array-Class from abstract_message
|
36
|
+
|
37
|
+
def load
|
38
|
+
super
|
39
|
+
|
40
|
+
@results = Array.new(@data[:count]) do |_|
|
41
|
+
IB::Bar.new :time => buffer.read_int_date, # conversion of epoche-time-integer to Dateime
|
42
|
+
# requires format_date in request to be "2"
|
43
|
+
# (outgoing/bar_requests # RequestHistoricalData#Encoding)
|
44
|
+
:open => buffer.read_decimal,
|
45
|
+
:high => buffer.read_decimal,
|
46
|
+
:low => buffer.read_decimal,
|
47
|
+
:close => buffer.read_decimal,
|
48
|
+
:volume => buffer.read_int,
|
49
|
+
:wap => buffer.read_decimal,
|
50
|
+
# :has_gaps => buffer.read_string, # only in ServerVersion < 124
|
51
|
+
:trades => buffer.read_int
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_human
|
56
|
+
"<HistoricalData: #{request_id}, #{count} items, #{start_date} to #{end_date}>"
|
57
|
+
end
|
58
|
+
end # HistoricalData
|
59
|
+
|
60
|
+
|
61
|
+
HistogramData = def_message( [89,0],
|
62
|
+
[:request_id, :int],
|
63
|
+
[ :number_of_points , :int ]) do
|
64
|
+
# to human
|
65
|
+
"<HistogramData: #{request_id}, #{number_of_points} read>"
|
66
|
+
end
|
67
|
+
|
68
|
+
class HistogramData
|
69
|
+
attr_accessor :results
|
70
|
+
using IBSupport # extended Array-Class from abstract_message
|
71
|
+
|
72
|
+
def load
|
73
|
+
super
|
74
|
+
|
75
|
+
@results = Array.new(@data[:number_of_points]) do |_|
|
76
|
+
{ price: buffer.read_decimal,
|
77
|
+
count: buffer.read_int }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end # module Incoming
|
83
|
+
end # module Messages
|
84
|
+
end # module IB
|