ib-api 972.2 → 972.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c55a18237300e1d54915e0fd71dc9a51766be578b8f25d73dd70a115961ed935
4
- data.tar.gz: f9aed73cec7a0959145d384f655dfbdd9f8416e6b0ddd4e21200ef30d458e149
3
+ metadata.gz: b8adaf6267b470da6c3e9918f11209d0ad63797a4facb61d2f561291a5435be4
4
+ data.tar.gz: 90ae6945b0cfa5dfc4c18b49d4d7fc65296a1b360abbf6e22a6a360c1ecebdb0
5
5
  SHA512:
6
- metadata.gz: 9a0fdbf9030c14c83b164531967ff130af078a3a1bdd6cf44697cb26887012d176ac929279eb8608b2920a2b4dd48b6434a129daf88cfdd1cb65a78014e35db9
7
- data.tar.gz: 64fa9394bd0a90c6a4c8abdc0c0a798816d913f5d25fd40fa67032db459cefb5bd296a1a7827ee05817f887c1b989ada9719494dfd6f348e25c45d0f4d7f37cd
6
+ metadata.gz: d9000425dd681aa181d70c81f6ab02705aba623d0c20fa124fabc652d0a9061ffd655980cc7ae307a9db8412ccb795149dcca4ebcb0239c7051da979298c25e5
7
+ data.tar.gz: 182b84997e82f20134187f4879f3157ad744aa3dd08bc909b6b901beab5817d90d973626b7a67be3da02ee495e4562bf479de635d8ab3897a9b073d5aaa8e33a
data/VERSION CHANGED
@@ -1 +1 @@
1
- 972.2
1
+ 972.3
data/lib/ib/connection.rb CHANGED
@@ -4,6 +4,11 @@ require 'ib/socket'
4
4
  require 'ib/logger'
5
5
  require 'ib/messages'
6
6
 
7
+ module TechnicalAnalysis
8
+ module Signals
9
+ end
10
+ end
11
+
7
12
  module IB
8
13
  # Encapsulates API connection to TWS or Gateway
9
14
  class Connection
@@ -100,7 +105,7 @@ module IB
100
105
  def update_next_order_id
101
106
  i,finish = 0, false
102
107
  sub = self.subscribe(:NextValidID) { finish = true }
103
- connected? ? self.send_message( :RequestIds ) : open()
108
+ connected? ? self.send_message( :RequestIds ) : open()
104
109
  Timeout::timeout(1, IB::TransmissionError,"Could not get NextValidId" ) do
105
110
  loop { sleep 0.1; break if finish }
106
111
  end
@@ -186,7 +191,13 @@ module IB
186
191
  when what.is_a?(Class) && what < Messages::Incoming::AbstractMessage
187
192
  [what]
188
193
  when what.is_a?(Symbol)
189
- [Messages::Incoming.const_get(what)]
194
+ if Messages::Incoming.const_defined?(what)
195
+ [Messages::Incoming.const_get(what)]
196
+ elsif TechnicalAnalysis::Signals.const_defined?(what)
197
+ [TechnicalAnalysis::Signals.const_get?(what)]
198
+ else
199
+ error "#{what} is no IB::Messages or TechnicalAnalyis::Signals class"
200
+ end
190
201
  when what.is_a?(Regexp)
191
202
  Messages::Incoming::Classes.values.find_all { |klass| klass.to_s =~ what }
192
203
  else
@@ -26,7 +26,11 @@ module IB
26
26
 
27
27
  class ReceiveFA
28
28
  def accounts
29
- xml[:ListOfAccountAliases][:AccountAlias].map{|x| Account.new x }
29
+ if( a= xml[:ListOfAccountAliases][:AccountAlias]).is_a? Array
30
+ a.map{|x| Account.new x }
31
+ elsif a.is_a? Hash ## only one account (soley financial advisor)
32
+ [ Account.new( a ) ]
33
+ end
30
34
  end
31
35
 
32
36
  def to_human
@@ -41,12 +41,12 @@ module IB
41
41
  IB::Bar.new :time => buffer.read_int_date, # conversion of epoche-time-integer to Dateime
42
42
  # requires format_date in request to be "2"
43
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,
44
+ :open => buffer.read_float,
45
+ :high => buffer.read_float,
46
+ :low => buffer.read_float,
47
+ :close => buffer.read_float,
48
48
  :volume => buffer.read_int,
49
- :wap => buffer.read_decimal,
49
+ :wap => buffer.read_float,
50
50
  # :has_gaps => buffer.read_string, # only in ServerVersion < 124
51
51
  :trades => buffer.read_int
52
52
  end
@@ -79,6 +79,26 @@ module IB
79
79
  end
80
80
  end
81
81
 
82
+ HistoricalDataUpdate = def_message [90, 0] ,
83
+ [:request_id, :int] ,
84
+ [:count, :int],
85
+ [:bar, :bar] # defined in support.rb
86
+
87
+ class HistoricalDataUpdate
88
+ attr_accessor :results
89
+ using IBSupport # extended Array-Class from abstract_message
90
+
91
+ def bar
92
+ @bar = IB::Bar.new @data[:bar]
93
+ end
94
+
95
+ def to_human
96
+ "<HistDataUpdate #{request_id} #{bar}>"
97
+ end
98
+ end
99
+
100
+
101
+
82
102
  end # module Incoming
83
103
  end # module Messages
84
104
  end # module IB
@@ -18,11 +18,10 @@ module IB
18
18
  # unless BAR_SIZES.keys.include?(bar_size)
19
19
  # error ":bar_size must be one of #{BAR_SIZES.inspect}", :args
20
20
  # end
21
-
22
- contract = data[:contract].is_a?(IB::Contract) ?
23
- data[:contract] : IB::Contract.from_ib_ruby(data[:contract])
24
-
25
- [data_type, nil, contract]
21
+ unless data[:contract].is_a? IB::Contract
22
+ error "contract must be a valid IB::Contract" , :args
23
+ end
24
+ [data_type, nil, data[:contract]]
26
25
  end
27
26
  end
28
27
 
data/lib/ib/support.rb CHANGED
@@ -62,7 +62,7 @@ module IBSupport
62
62
 
63
63
  def read_int_date
64
64
  t= read_int
65
- s= Time.at(t)
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,35 @@ module IBSupport
139
139
  end
140
140
  #
141
141
 
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
-
155
- end
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 standard bar (Historical data bars)
158
+ { :time => read_int_date, # conversion of epoche-time-integer to Dateime
159
+ # requires format_date in request to be "2"
160
+ # (outgoing/bar_requests # RequestHistoricalData#Encoding)
161
+ :open => read_float,
162
+ :high => read_float,
163
+ :low => read_float,
164
+ :close => read_float,
165
+ :wap => read_float,
166
+ :volume => read_int,
167
+ # :has_gaps => read_string, # only in ServerVersion < 124
168
+ :trades => read_int }
169
+
170
+ end
156
171
 
157
172
 
158
173
  alias read_bool read_boolean
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
- "<Bar: #{time} wap #{wap} OHLC #{open} #{high} #{low} #{close} " +
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
 
@@ -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
@@ -6,7 +6,8 @@ require 'models/ib/underlying'
6
6
  module IB
7
7
 
8
8
  if defined?(Contract)
9
- puts "Contract already a #{defined?(Contract)}"
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 => 0.0,
123
+ :strike => "",
123
124
  :right => :none, # Not an option
124
125
  # :exchange => 'SMART',
125
126
  :include_expired => false
@@ -136,15 +137,13 @@ module IB
136
137
 
137
138
  def serialize *fields # :nodoc:
138
139
  print_default = ->(field, default="") { field.blank? ? default : field }
139
- ## Non numeric entries are passed untouched, only 0 is converted to the default value
140
- ## Thus: a Zero-Strike-Option has to be defined with «strike: "0"»
141
- print_not_zero = ->(field, default="") { field.is_a?(Numeric) && field.zero? ? default : field }
142
140
  [(con_id.present? && !con_id.is_a?(Symbol) && con_id.to_i > 0 ? con_id : ""),
143
141
  print_default[symbol],
144
142
  print_default[self[:sec_type]],
145
143
  ( fields.include?(:option) ?
146
144
  [ print_default[expiry],
147
- print_default[strike],
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 : "",
148
147
  print_default[self[:right]],
149
148
  print_default[multiplier]] : nil ),
150
149
  print_default[exchange],
@@ -219,20 +218,18 @@ module IB
219
218
  # the link to contract-details is __not__ maintained.
220
219
  def essential
221
220
 
222
- self_attributes = [ :sec_type]
223
- the_attributes = [ :symbol , :con_id, :exchange, :right,
221
+ the_attributes = [ :sec_type, :symbol , :con_id, :exchange, :right,
224
222
  :currency, :expiry, :strike, :local_symbol, :last_trading_day,
225
- :multiplier, :primary_exchange, :trading_class ]
226
- the_hash= the_attributes.map{|x| y= self.send(x); [x,y] if y.present? }.compact.to_h
227
- the_hash[:description] =
228
- if @description.present?
229
- @description
230
- elsif contract_detail.present?
231
- contract_detail.long_name
232
- else
233
- ""
234
- end
235
- 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
236
233
  end
237
234
 
238
235
 
@@ -383,6 +380,7 @@ In places where these terms are used to indicate a concept, we have left them as
383
380
 
384
381
 
385
382
  ### Now let's deal with Contract subclasses
383
+ begin
386
384
 
387
385
  require_relative 'option'
388
386
  require 'models/ib/bag'
@@ -390,9 +388,20 @@ In places where these terms are used to indicate a concept, we have left them as
390
388
  require 'models/ib/future'
391
389
  require 'models/ib/stock'
392
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
+
393
401
 
394
402
  class Contract
395
403
  # Contract subclasses representing specialized security types.
404
+ using IBSupport
396
405
 
397
406
  Subclasses = Hash.new(Contract)
398
407
  Subclasses[:bag] = IB::Bag
@@ -405,31 +414,14 @@ In places where these terms are used to indicate a concept, we have left them as
405
414
 
406
415
 
407
416
  # This builds an appropriate Contract subclass based on its type
408
- #
409
- # the method is also used to copy Contract.values to new instances
417
+ #
418
+ # the method is also used to copy Contract.values to new instances
410
419
  def self.build opts = {}
411
420
  subclass =( VALUES[:sec_type][opts[:sec_type]] || opts['sec_type'] || opts[:sec_type]).to_sym
412
421
  Contract::Subclasses[subclass].new opts
413
422
  end
414
423
 
415
- # This returns a Contract initialized from the serialize_ib_ruby format string.
416
- def self.from_ib_ruby
417
- keys = [:con_id, :symbol, :sec_type, :expiry, :strike, :right, :multiplier,
418
- :exchange, :primary_exchange, :currency, :local_symbol]
419
- props = Hash[keys.zip(string.split(":"))]
420
- props.delete_if { |k, v| v.nil? || v.empty? }
421
- Contract.build props
422
- end
424
+
423
425
  end # class Contract
424
426
  end # module IB
425
427
 
426
- class String
427
- def to_contract
428
- keys = [:con_id, :symbol, :sec_type, :expiry, :strike, :right, :multiplier,
429
- :exchange, :primary_exchange, :currency, :local_symbol]
430
- props = Hash[keys.zip(split(":"))]
431
- props.delete_if { |k, v| v.nil? || v.empty? }
432
- IB::Contract.build props
433
-
434
- end
435
- end
@@ -1,6 +1,12 @@
1
- #require 'ib/verify'
1
+ # require 'ib/verify'
2
2
  module IB
3
- class Spread < Bag
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 + " added #{nc.to_human}" rescue "Spread: #{nc.to_human}"
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,9 +107,15 @@ 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
- invariant_attributes
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
115
119
  end
116
120
 
117
121
  def multiplier
@@ -150,13 +154,14 @@ Adds (or substracts) relative (back) measures to the front month, just passes ab
150
154
  :exchange => a.read_string
151
155
 
152
156
  end
153
- object= self.new container['Spread'].read_contract
154
- object.legs = container['legs'].map{|x| IB::Contract.build x.read_contract}
155
- object.combo_legs = container['combo_legs'].map{ |x| read_leg[ x ] }
156
- object.description = container['misc'].read_string
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
157
161
  object
158
162
 
159
163
  end
164
+
160
165
  end
161
166
 
162
167