ib-api 972.1 → 972.5
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 +4 -4
- data/Gemfile.lock +29 -29
- data/VERSION +1 -1
- data/api.gemspec +1 -1
- data/bin/console +4 -8
- data/changelog.md +2 -1
- data/lib/ib/connection.rb +19 -17
- data/lib/ib/logger.rb +1 -1
- data/lib/ib/messages/incoming/abstract_message.rb +7 -7
- data/lib/ib/messages/incoming/account_value.rb +5 -1
- data/lib/ib/messages/incoming/historical_data.rb +25 -5
- data/lib/ib/messages/outgoing/abstract_message.rb +3 -3
- data/lib/ib/messages/outgoing/bar_requests.rb +4 -5
- data/lib/ib/support.rb +34 -17
- data/lib/logging.rb +45 -0
- data/lib/models/ib/bag.rb +6 -0
- data/lib/models/ib/bar.rb +1 -1
- data/lib/models/ib/combo_leg.rb +22 -0
- data/lib/models/ib/contract.rb +32 -38
- data/lib/models/ib/option.rb +3 -1
- data/lib/models/ib/order.rb +5 -0
- data/lib/models/ib/spread.rb +29 -20
- metadata +8 -20
- data/example/README.md +0 -76
- data/example/account_info +0 -54
- data/example/account_positions +0 -30
- data/example/account_summary +0 -88
- data/example/cancel_orders +0 -74
- data/example/fa_accounts +0 -25
- data/example/fundamental_data +0 -40
- data/example/historic_data_cli +0 -186
- data/example/list_orders +0 -45
- data/example/portfolio_csv +0 -81
- data/example/scanner_data +0 -62
- data/example/template +0 -19
- data/example/tick_data +0 -28
data/lib/ib/support.rb
CHANGED
@@ -28,13 +28,13 @@ module IBSupport
|
|
28
28
|
|
29
29
|
## Values -1 and below indicate: Not computed (TickOptionComputation)
|
30
30
|
def read_decimal_limit_1
|
31
|
-
i=
|
31
|
+
i= read_float
|
32
32
|
i <= -1 ? nil : i
|
33
33
|
end
|
34
34
|
|
35
35
|
## Values -2 and below indicate: Not computed (TickOptionComputation)
|
36
36
|
def read_decimal_limit_2
|
37
|
-
i=
|
37
|
+
i= read_float
|
38
38
|
i <= -2 ? nil : i
|
39
39
|
end
|
40
40
|
|
@@ -62,7 +62,7 @@ module IBSupport
|
|
62
62
|
|
63
63
|
def read_int_date
|
64
64
|
t= read_int
|
65
|
-
|
65
|
+
s= Time.at(t.to_i)
|
66
66
|
# s.year == 1970 --> data is most likely a date-string
|
67
67
|
s.year == 1970 ? Date.parse(t.to_s) : s
|
68
68
|
end
|
@@ -139,20 +139,37 @@ module IBSupport
|
|
139
139
|
end
|
140
140
|
#
|
141
141
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
142
|
+
def read_contract # read a standard contract and return als hash
|
143
|
+
{ con_id: read_int,
|
144
|
+
symbol: read_string,
|
145
|
+
sec_type: read_string,
|
146
|
+
expiry: read_string,
|
147
|
+
strike: read_decimal,
|
148
|
+
right: read_string,
|
149
|
+
multiplier: read_int,
|
150
|
+
exchange: read_string,
|
151
|
+
currency: read_string,
|
152
|
+
local_symbol: read_string,
|
153
|
+
trading_class: read_string } # new Version 8
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
def read_bar # read a Historical data bar
|
158
|
+
# ** historicalDataUpdate: time open close high low ** covered hier
|
159
|
+
# historicalData time open high low close <- covered in messages/incomming
|
160
|
+
{ :time => read_int_date, # conversion of epoche-time-integer to Dateime
|
161
|
+
# requires format_date in request to be "2"
|
162
|
+
# (outgoing/bar_requests # RequestHistoricalData#Encoding)
|
163
|
+
:open => read_float,
|
164
|
+
:close => read_float,
|
165
|
+
:high => read_float,
|
166
|
+
:low => read_float,
|
167
|
+
:wap => read_float,
|
168
|
+
:volume => read_int,
|
169
|
+
# :has_gaps => read_string, # only in ServerVersion < 124
|
170
|
+
:trades => read_int }
|
171
|
+
|
172
|
+
end
|
156
173
|
|
157
174
|
|
158
175
|
alias read_bool read_boolean
|
data/lib/logging.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
#module Kernel
|
2
|
+
# private
|
3
|
+
# def this_method_name
|
4
|
+
# caller[0] =~ /`([^']*)'/ and $1
|
5
|
+
# end
|
6
|
+
# see also __method__ and __callee__
|
7
|
+
#end
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
module Support
|
12
|
+
module Logging
|
13
|
+
def self.included(base)
|
14
|
+
base.extend ClassMethods
|
15
|
+
base.send :define_method, :logger do
|
16
|
+
base.logger
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module ClassMethods
|
21
|
+
def logger
|
22
|
+
@logger
|
23
|
+
end
|
24
|
+
|
25
|
+
def logger=(logger)
|
26
|
+
@logger = logger
|
27
|
+
end
|
28
|
+
|
29
|
+
def configure_logger(log=nil)
|
30
|
+
if log
|
31
|
+
@logger = log
|
32
|
+
else
|
33
|
+
@logger = Logger.new(STDOUT)
|
34
|
+
@logger.level = Logger::INFO
|
35
|
+
@logger.formatter = proc do |severity, datetime, progname, msg|
|
36
|
+
# "#{datetime.strftime("%d.%m.(%X)")}#{"%5s" % severity}->#{msg}\n"
|
37
|
+
"#{"%5s" % severity}::#{msg}\n"
|
38
|
+
end
|
39
|
+
@logger.debug "------------------------------ start logging ----------------------------"
|
40
|
+
end # branch
|
41
|
+
end # def
|
42
|
+
end # module ClassMethods
|
43
|
+
end # module Logging
|
44
|
+
end # module Support
|
45
|
+
|
data/lib/models/ib/bag.rb
CHANGED
@@ -2,6 +2,12 @@
|
|
2
2
|
|
3
3
|
module IB
|
4
4
|
|
5
|
+
if defined?(Bag)
|
6
|
+
puts "Bag already a #{defined?(Bag)}"
|
7
|
+
|
8
|
+
# puts Bag.ancestors
|
9
|
+
IB.send(:remove_const, 'Bag')
|
10
|
+
end
|
5
11
|
# "BAG" is not really a contract, but a combination (combo) of securities.
|
6
12
|
# AKA basket or bag of securities. Individual securities in combo are represented
|
7
13
|
# by ComboLeg objects.
|
data/lib/models/ib/bar.rb
CHANGED
@@ -22,7 +22,7 @@ module IB
|
|
22
22
|
validates_numericality_of :open, :high, :low, :close, :volume
|
23
23
|
|
24
24
|
def to_human
|
25
|
-
|
25
|
+
"<Bar: #{time.strftime("(%d.%m.%y)%X")} wap #{wap.round(3)} OHLC #{open} #{high} #{low} #{close} " +
|
26
26
|
(trades ? "trades #{trades}" : "") + " vol #{volume}>"
|
27
27
|
end
|
28
28
|
|
data/lib/models/ib/combo_leg.rb
CHANGED
@@ -83,6 +83,28 @@ module IB
|
|
83
83
|
].flatten
|
84
84
|
end
|
85
85
|
|
86
|
+
|
87
|
+
# fields are generated by serialize(:extended)
|
88
|
+
# i.e.
|
89
|
+
# z= Strangle.build from: Symbols::Index.stoxx, p: 3700, c: 4000, expiry: 202106
|
90
|
+
# zc= z.combo_legs.serialize :extended
|
91
|
+
# => [[321584786, 1, "BUY", "DTB", 0, 0, "", -1], [321584637, 1, "BUY", "DTB", 0, 0, "", -1]]
|
92
|
+
# nz = zc.map{|o| ComboLeg.build *o }
|
93
|
+
# zc.map{|o| ComboLeg.build o } => # is equivalent
|
94
|
+
# => [#<IB::ComboLeg:0x0000000001c36bc0 @attributes={:con_id=>321584786, :ratio=>1, :side=>"B", :exchange=>"DTB", ...
|
95
|
+
# nz.first == z.combo_legs.first => true
|
96
|
+
#
|
97
|
+
def self.build *fields
|
98
|
+
self.new Hash[[:con_id,
|
99
|
+
:ratio,
|
100
|
+
:side, # reverse to_sup?
|
101
|
+
:exchange,
|
102
|
+
:open_close,
|
103
|
+
:short_sale_slot,
|
104
|
+
:designated_location,
|
105
|
+
:exempt_code].zip fields]
|
106
|
+
end
|
107
|
+
|
86
108
|
def to_human
|
87
109
|
"<ComboLeg: #{side} #{ratio} con_id #{con_id} at #{exchange}>"
|
88
110
|
end
|
data/lib/models/ib/contract.rb
CHANGED
@@ -6,7 +6,8 @@ require 'models/ib/underlying'
|
|
6
6
|
module IB
|
7
7
|
|
8
8
|
if defined?(Contract)
|
9
|
-
|
9
|
+
#Connection.current.logger.warn "Contract already a #{defined?(Contract)}"
|
10
|
+
|
10
11
|
# puts Contract.ancestors
|
11
12
|
# IB.send(:remove_const, 'Contract')
|
12
13
|
end
|
@@ -119,7 +120,7 @@ module IB
|
|
119
120
|
|
120
121
|
def default_attributes # :nodoc:
|
121
122
|
super.merge :con_id => 0,
|
122
|
-
:strike =>
|
123
|
+
:strike => "",
|
123
124
|
:right => :none, # Not an option
|
124
125
|
# :exchange => 'SMART',
|
125
126
|
:include_expired => false
|
@@ -136,13 +137,13 @@ module IB
|
|
136
137
|
|
137
138
|
def serialize *fields # :nodoc:
|
138
139
|
print_default = ->(field, default="") { field.blank? ? default : field }
|
139
|
-
print_not_zero = ->(field, default="") { field.to_i.zero? ? default : field }
|
140
140
|
[(con_id.present? && !con_id.is_a?(Symbol) && con_id.to_i > 0 ? con_id : ""),
|
141
141
|
print_default[symbol],
|
142
142
|
print_default[self[:sec_type]],
|
143
143
|
( fields.include?(:option) ?
|
144
144
|
[ print_default[expiry],
|
145
|
-
|
145
|
+
## a Zero-Strike-Option has to be defined with «strike: -1 »
|
146
|
+
strike.present? && ( strike.is_a?(Numeric) && !strike.zero? && strike > 0 ) ? strike : strike<0 ? 0 : "",
|
146
147
|
print_default[self[:right]],
|
147
148
|
print_default[multiplier]] : nil ),
|
148
149
|
print_default[exchange],
|
@@ -217,20 +218,18 @@ module IB
|
|
217
218
|
# the link to contract-details is __not__ maintained.
|
218
219
|
def essential
|
219
220
|
|
220
|
-
|
221
|
-
the_attributes = [ :symbol , :con_id, :exchange, :right,
|
221
|
+
the_attributes = [ :sec_type, :symbol , :con_id, :exchange, :right,
|
222
222
|
:currency, :expiry, :strike, :local_symbol, :last_trading_day,
|
223
|
-
:multiplier, :primary_exchange, :trading_class ]
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
self.class.new the_hash.merge( self_attributes.map{|x| y = self.send(x); [x,y] unless y == :none }.compact.to_h )
|
223
|
+
:multiplier, :primary_exchange, :trading_class, :description ]
|
224
|
+
new_contract= self.class.new invariant_attributes.select{|k,_| the_attributes.include? k }.compact
|
225
|
+
new_contract[:description] = if @description.present?
|
226
|
+
@description
|
227
|
+
elsif contract_detail.present?
|
228
|
+
contract_detail.long_name
|
229
|
+
else
|
230
|
+
""
|
231
|
+
end
|
232
|
+
new_contract # return contract
|
234
233
|
end
|
235
234
|
|
236
235
|
|
@@ -381,6 +380,7 @@ In places where these terms are used to indicate a concept, we have left them as
|
|
381
380
|
|
382
381
|
|
383
382
|
### Now let's deal with Contract subclasses
|
383
|
+
begin
|
384
384
|
|
385
385
|
require_relative 'option'
|
386
386
|
require 'models/ib/bag'
|
@@ -388,14 +388,25 @@ In places where these terms are used to indicate a concept, we have left them as
|
|
388
388
|
require 'models/ib/future'
|
389
389
|
require 'models/ib/stock'
|
390
390
|
require 'models/ib/index'
|
391
|
+
### walkaraound to enable spreads with orientdb
|
392
|
+
if IB::const_defined? :Spread
|
393
|
+
IB::send(:remove_const, :Spread)
|
394
|
+
#puts "Spread already defined"
|
395
|
+
#puts "erasing"
|
396
|
+
end
|
397
|
+
require 'models/ib/spread.rb'
|
398
|
+
end
|
399
|
+
|
400
|
+
|
391
401
|
|
392
402
|
class Contract
|
393
403
|
# Contract subclasses representing specialized security types.
|
404
|
+
using IBSupport
|
394
405
|
|
395
406
|
Subclasses = Hash.new(Contract)
|
396
407
|
Subclasses[:bag] = IB::Bag
|
397
408
|
Subclasses[:option] = IB::Option
|
398
|
-
Subclasses[:
|
409
|
+
Subclasses[:futures_option] = IB::FutureOption
|
399
410
|
Subclasses[:future] = IB::Future
|
400
411
|
Subclasses[:stock] = IB::Stock
|
401
412
|
Subclasses[:forex] = IB::Forex
|
@@ -403,31 +414,14 @@ In places where these terms are used to indicate a concept, we have left them as
|
|
403
414
|
|
404
415
|
|
405
416
|
# This builds an appropriate Contract subclass based on its type
|
406
|
-
|
407
|
-
|
417
|
+
#
|
418
|
+
# the method is also used to copy Contract.values to new instances
|
408
419
|
def self.build opts = {}
|
409
420
|
subclass =( VALUES[:sec_type][opts[:sec_type]] || opts['sec_type'] || opts[:sec_type]).to_sym
|
410
421
|
Contract::Subclasses[subclass].new opts
|
411
422
|
end
|
412
423
|
|
413
|
-
|
414
|
-
def self.from_ib_ruby
|
415
|
-
keys = [:con_id, :symbol, :sec_type, :expiry, :strike, :right, :multiplier,
|
416
|
-
:exchange, :primary_exchange, :currency, :local_symbol]
|
417
|
-
props = Hash[keys.zip(string.split(":"))]
|
418
|
-
props.delete_if { |k, v| v.nil? || v.empty? }
|
419
|
-
Contract.build props
|
420
|
-
end
|
424
|
+
|
421
425
|
end # class Contract
|
422
426
|
end # module IB
|
423
427
|
|
424
|
-
class String
|
425
|
-
def to_contract
|
426
|
-
keys = [:con_id, :symbol, :sec_type, :expiry, :strike, :right, :multiplier,
|
427
|
-
:exchange, :primary_exchange, :currency, :local_symbol]
|
428
|
-
props = Hash[keys.zip(split(":"))]
|
429
|
-
props.delete_if { |k, v| v.nil? || v.empty? }
|
430
|
-
IB::Contract.build props
|
431
|
-
|
432
|
-
end
|
433
|
-
end
|
data/lib/models/ib/option.rb
CHANGED
data/lib/models/ib/order.rb
CHANGED
@@ -514,6 +514,11 @@ Format of serialisation
|
|
514
514
|
(account ? "/#{account}" : '') +
|
515
515
|
(commission ? " fee #{commission}" : '') + ">"
|
516
516
|
end
|
517
|
+
def serialize_rabbit
|
518
|
+
{ 'Contract' => contract.present? ? contract.serialize( :option, :trading_class ): '' ,
|
519
|
+
'Order' => self,
|
520
|
+
'OrderState' => order_state}
|
521
|
+
end
|
517
522
|
|
518
523
|
end # class Order
|
519
524
|
end # module IB
|
data/lib/models/ib/spread.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
|
-
#require 'ib/verify'
|
1
|
+
# require 'ib/verify'
|
2
2
|
module IB
|
3
|
-
|
3
|
+
if defined?(Spread)
|
4
|
+
puts "Bag already a #{defined?(Spread)}"
|
5
|
+
|
6
|
+
# puts Spread.ancestors
|
7
|
+
IB.send(:remove_const, 'Spread')
|
8
|
+
end
|
9
|
+
class Spread < Bag
|
4
10
|
has_many :legs
|
5
11
|
|
6
12
|
using IBSupport
|
@@ -63,14 +69,6 @@ Adds (or substracts) relative (back) measures to the front month, just passes ab
|
|
63
69
|
end
|
64
70
|
|
65
71
|
|
66
|
-
|
67
|
-
def serialize_rabbit
|
68
|
-
{ "Spread" => serialize( :option, :trading_class ),
|
69
|
-
'legs' => legs.map{ |y| y.serialize :option, :trading_class }, 'combo_legs' => combo_legs.map(&:serialize),
|
70
|
-
'misc' => [description]
|
71
|
-
}
|
72
|
-
end
|
73
|
-
|
74
72
|
# adds a leg to any spread
|
75
73
|
#
|
76
74
|
# Parameter:
|
@@ -90,7 +88,7 @@ Adds (or substracts) relative (back) measures to the front month, just passes ab
|
|
90
88
|
the_leg= ComboLeg.new( nc.attributes.slice( :con_id, :exchange )
|
91
89
|
.merge( leg_params ))
|
92
90
|
self.combo_legs << the_leg
|
93
|
-
self.description = description
|
91
|
+
self.description = "#{description.nil? ? "": description} added #{nc.to_human}" rescue "Spread: #{nc.to_human}"
|
94
92
|
self.legs << nc
|
95
93
|
end
|
96
94
|
self # return value to enable chaining
|
@@ -109,18 +107,28 @@ Adds (or substracts) relative (back) measures to the front month, just passes ab
|
|
109
107
|
self
|
110
108
|
end
|
111
109
|
|
112
|
-
|
110
|
+
# essentail
|
111
|
+
# effectivley clones the object
|
112
|
+
#
|
113
113
|
def essential
|
114
|
-
|
115
|
-
|
114
|
+
the_es = self.class.new invariant_attributes
|
115
|
+
the_es.legs = legs.map{|y| IB::Contract.build y.invariant_attributes}
|
116
|
+
the_es.combo_legs = combo_legs.map{|y| IB::ComboLeg.new y.invariant_attributes }
|
117
|
+
the_es.description = description
|
118
|
+
the_es # return
|
116
119
|
end
|
120
|
+
|
117
121
|
def multiplier
|
118
122
|
(legs.map(&:multiplier).sum/legs.size).to_i
|
119
123
|
end
|
120
124
|
|
121
|
-
# provide a negative con_id
|
125
|
+
# provide a negative con_id
|
122
126
|
def con_id
|
123
|
-
|
127
|
+
if attributes[:con_id].present? && attributes[] < 0
|
128
|
+
attributes[:con_id]
|
129
|
+
else
|
130
|
+
-legs.map{ |x| x.is_a?(String) ? x.expand.con_id : x.con_id}.sum
|
131
|
+
end
|
124
132
|
end
|
125
133
|
|
126
134
|
|
@@ -146,13 +154,14 @@ Adds (or substracts) relative (back) measures to the front month, just passes ab
|
|
146
154
|
:exchange => a.read_string
|
147
155
|
|
148
156
|
end
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
157
|
+
object= self.new container['Spread'].clone.read_contract
|
158
|
+
object.legs = container['legs'].map{|x| IB::Contract.build x.clone.read_contract}
|
159
|
+
object.combo_legs = container['combo_legs'].map{ |x| read_leg[ x.clone ] }
|
160
|
+
object.description = container['misc'].clone.read_string
|
153
161
|
object
|
154
162
|
|
155
163
|
end
|
164
|
+
|
156
165
|
end
|
157
166
|
|
158
167
|
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ib-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '972.
|
4
|
+
version: '972.5'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hartmut Bischoff
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-06-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -103,19 +103,6 @@ files:
|
|
103
103
|
- bin/console.yml
|
104
104
|
- bin/setup
|
105
105
|
- changelog.md
|
106
|
-
- example/README.md
|
107
|
-
- example/account_info
|
108
|
-
- example/account_positions
|
109
|
-
- example/account_summary
|
110
|
-
- example/cancel_orders
|
111
|
-
- example/fa_accounts
|
112
|
-
- example/fundamental_data
|
113
|
-
- example/historic_data_cli
|
114
|
-
- example/list_orders
|
115
|
-
- example/portfolio_csv
|
116
|
-
- example/scanner_data
|
117
|
-
- example/template
|
118
|
-
- example/tick_data
|
119
106
|
- lib/extensions/class-extensions.rb
|
120
107
|
- lib/ib-api.rb
|
121
108
|
- lib/ib/base.rb
|
@@ -155,6 +142,7 @@ files:
|
|
155
142
|
- lib/ib/socket.rb
|
156
143
|
- lib/ib/support.rb
|
157
144
|
- lib/ib/version.rb
|
145
|
+
- lib/logging.rb
|
158
146
|
- lib/models/ib/account.rb
|
159
147
|
- lib/models/ib/account_value.rb
|
160
148
|
- lib/models/ib/bag.rb
|
@@ -197,7 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
197
185
|
- !ruby/object:Gem::Version
|
198
186
|
version: '0'
|
199
187
|
requirements: []
|
200
|
-
rubygems_version: 3.
|
188
|
+
rubygems_version: 3.2.3
|
201
189
|
signing_key:
|
202
190
|
specification_version: 4
|
203
191
|
summary: Ruby Implementation of the Interactive Brokers TWS API
|