ib-api 972.5.1 → 972.5.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f7b56c267d93f567d8e601e801d98a90018fddb5e87f876c8eef2d89bd1a3e45
4
- data.tar.gz: 23da0add2599afc4928e7008a9cf4bf3ed9f2c93a1cfd7d4e0bc8eeb3ebc6d4f
3
+ metadata.gz: 25eeaf6f08e2fd29800c3ed6d1ec94adfa5a61fecd2c9a37bfdc9a692f6cbaf9
4
+ data.tar.gz: aac0683bb11a8d7326a95a69b9e728321a70d70be072ee6d133d09dce6724251
5
5
  SHA512:
6
- metadata.gz: 57bf9b6cf7c2350e60c62b1d574e46a8d9fb0be5ec3ec2fc225ca9208ae0fa913fa15ad890715b6675f10b67248e04c60945008022368935339ac41a468b9d79
7
- data.tar.gz: 5b1d1168ae20163ea5ab1693bce66c731183ffb63db81640458290810c2e225973bd10a51a6efa8f326cdd8dadc2747b02ba4a07529d3d7226b577d901cee1e9
6
+ metadata.gz: 7b28db7e5ee4aa73942e724caf8c65e07df46516eca725868fc7279f31238124d7fee05da3fe8a43737a820b43079790f3f1a77f0ff662600d89fdfcbf0c9734
7
+ data.tar.gz: ec8e9b32fd01c212249c3fb4da3c7d86b503d0d1cc6cf3854c25a03b98933e0b8a26981c56c45e1cd1799ce352053f3601ea0bef68c3297c41eb15e7c5847048
data/Gemfile.lock CHANGED
@@ -1,39 +1,34 @@
1
- GIT
2
- remote: https://github.com/ohler55/ox.git
3
- revision: 67ce6ecb45a0d1354e1f8ed9a155826ba986e21e
4
- specs:
5
- ox (2.13.4)
6
-
7
1
  PATH
8
2
  remote: .
9
3
  specs:
10
- ib-api (972.2)
4
+ ib-api (972.5.2)
11
5
  activemodel
12
6
  activesupport (>= 6.0)
7
+ ox
8
+ terminal-table
13
9
 
14
10
  GEM
15
11
  remote: https://rubygems.org/
16
12
  specs:
17
- activemodel (6.1.2.1)
18
- activesupport (= 6.1.2.1)
19
- activesupport (6.1.2.1)
13
+ activemodel (7.0.4.2)
14
+ activesupport (= 7.0.4.2)
15
+ activesupport (7.0.4.2)
20
16
  concurrent-ruby (~> 1.0, >= 1.0.2)
21
17
  i18n (>= 1.6, < 2)
22
18
  minitest (>= 5.1)
23
19
  tzinfo (~> 2.0)
24
- zeitwerk (~> 2.3)
25
20
  coderay (1.1.3)
26
- concurrent-ruby (1.1.8)
27
- diff-lcs (1.4.4)
28
- ffi (1.13.1)
29
- formatador (0.2.5)
30
- guard (2.16.2)
21
+ concurrent-ruby (1.2.2)
22
+ diff-lcs (1.5.0)
23
+ ffi (1.15.5)
24
+ formatador (1.1.0)
25
+ guard (2.18.0)
31
26
  formatador (>= 0.2.4)
32
27
  listen (>= 2.7, < 4.0)
33
28
  lumberjack (>= 1.0.12, < 2.0)
34
29
  nenv (~> 0.1)
35
30
  notiffany (~> 0.0)
36
- pry (>= 0.9.12)
31
+ pry (>= 0.13.0)
37
32
  shellany (~> 0.0)
38
33
  thor (>= 0.18.1)
39
34
  guard-compat (1.2.1)
@@ -41,64 +36,64 @@ GEM
41
36
  guard (~> 2.1)
42
37
  guard-compat (~> 1.1)
43
38
  rspec (>= 2.99.0, < 4.0)
44
- i18n (1.8.9)
39
+ i18n (1.12.0)
45
40
  concurrent-ruby (~> 1.0)
46
- listen (3.2.1)
41
+ listen (3.8.0)
47
42
  rb-fsevent (~> 0.10, >= 0.10.3)
48
43
  rb-inotify (~> 0.9, >= 0.9.10)
49
44
  lumberjack (1.2.8)
50
45
  method_source (1.0.0)
51
- minitest (5.14.3)
46
+ minitest (5.17.0)
52
47
  nenv (0.3.0)
53
48
  notiffany (0.1.3)
54
49
  nenv (~> 0.1)
55
50
  shellany (~> 0.0)
56
- pry (0.13.1)
51
+ ox (2.14.14)
52
+ pry (0.14.2)
57
53
  coderay (~> 1.1)
58
54
  method_source (~> 1.0)
59
- rake (13.0.1)
60
- rb-fsevent (0.10.4)
55
+ rake (13.0.6)
56
+ rb-fsevent (0.11.2)
61
57
  rb-inotify (0.10.1)
62
58
  ffi (~> 1.0)
63
- rspec (3.9.0)
64
- rspec-core (~> 3.9.0)
65
- rspec-expectations (~> 3.9.0)
66
- rspec-mocks (~> 3.9.0)
59
+ rspec (3.12.0)
60
+ rspec-core (~> 3.12.0)
61
+ rspec-expectations (~> 3.12.0)
62
+ rspec-mocks (~> 3.12.0)
67
63
  rspec-collection_matchers (1.2.0)
68
64
  rspec-expectations (>= 2.99.0.beta1)
69
- rspec-core (3.9.3)
70
- rspec-support (~> 3.9.3)
71
- rspec-expectations (3.9.2)
65
+ rspec-core (3.12.1)
66
+ rspec-support (~> 3.12.0)
67
+ rspec-expectations (3.12.2)
72
68
  diff-lcs (>= 1.2.0, < 2.0)
73
- rspec-support (~> 3.9.0)
69
+ rspec-support (~> 3.12.0)
74
70
  rspec-its (1.3.0)
75
71
  rspec-core (>= 3.0.0)
76
72
  rspec-expectations (>= 3.0.0)
77
- rspec-mocks (3.9.1)
73
+ rspec-mocks (3.12.3)
78
74
  diff-lcs (>= 1.2.0, < 2.0)
79
- rspec-support (~> 3.9.0)
80
- rspec-support (3.9.3)
75
+ rspec-support (~> 3.12.0)
76
+ rspec-support (3.12.0)
81
77
  shellany (0.0.1)
82
- thor (1.0.1)
83
- tzinfo (2.0.4)
78
+ terminal-table (3.0.2)
79
+ unicode-display_width (>= 1.1.1, < 3)
80
+ thor (1.2.1)
81
+ tzinfo (2.0.6)
84
82
  concurrent-ruby (~> 1.0)
85
- value_semantics (3.6.0)
86
- zeitwerk (2.4.2)
83
+ unicode-display_width (2.4.2)
87
84
 
88
85
  PLATFORMS
89
- ruby
86
+ x86_64-linux
90
87
 
91
88
  DEPENDENCIES
92
89
  bundler
93
90
  guard
94
91
  guard-rspec
95
92
  ib-api!
96
- ox!
97
93
  rake (~> 13.0)
98
94
  rspec
99
95
  rspec-collection_matchers
100
96
  rspec-its
101
- value_semantics
102
97
 
103
98
  BUNDLED WITH
104
- 1.17.3
99
+ 2.3.22
data/VERSION CHANGED
@@ -1 +1 @@
1
- 972.5.1
1
+ 972.5.2
data/bin/console CHANGED
@@ -1,6 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
- ### loads the active-orient environment
3
- ### and starts an interactive shell
4
2
  ###
5
3
  ### Parameter: t)ws | g)ateway (or number of port ) Default: Gateway ,
6
4
  ### client_id , Default 2000
@@ -17,10 +15,10 @@ class Array
17
15
  # i.e
18
16
  #
19
17
  # 2.5.0 :006 > C.received[:OpenOrder].local_id
20
- # => [16, 17, 21, 20, 19, 8, 7]
18
+ # => [16, 17, 21, 20, 19, 8, 7]
21
19
  # 2.5.0 :007 > C.received[:OpenOrder].contract.to_human
22
- # => ["<Bag: IECombo SMART USD legs: >", "<Stock: GE USD>", "<Stock: GE USD>", "<Stock: GE USD>", "<Stock: GE USD>", "<Stock: WFC USD>", "<Stock: WFC USD>"]
23
- #
20
+ # => ["<Bag: IECombo SMART USD legs: >", "<Stock: GE USD>", "<Stock: GE USD>", "<Stock: GE USD>", "<Stock: GE USD>", "<Stock: WFC USD>", "<Stock: WFC USD>"]
21
+
24
22
  # its included only in the console, for inspection purposes
25
23
 
26
24
  def method_missing(method, *key)
@@ -32,16 +30,16 @@ class Array
32
30
  end # Array
33
31
 
34
32
 
35
- # read items from console.yml
33
+ # read items from console.yml
36
34
  read_yml = -> (key) do
37
35
  YAML::load_file( File.expand_path('../console.yml',__FILE__))[key]
38
36
  end
39
37
 
40
38
 
41
- puts
42
- puts ">> IB-Core Interactive Console <<"
39
+ puts
40
+ puts ">> IB-Core Interactive Console <<"
43
41
  puts '-'* 45
44
- puts
42
+ puts
45
43
  puts "Namespace is IB ! "
46
44
  puts
47
45
  puts '-'* 45
@@ -59,23 +57,23 @@ read_yml = -> (key) do
59
57
  end
60
58
 
61
59
  ARGV.clear
62
-
60
+
63
61
  ## The Block takes instructions which are executed after initializing all instance-variables
64
62
  ## and prior to the connection-process
65
- ## Here we just subscribe to some events
66
- C = Connection.new client_id: client_id, port: port do |c| # future use__ , optional_capacities: "+PACEAPI" do |c|
63
+ ## Here we just subscribe to some events
64
+ C = Connection.new client_id: client_id, port: port do |c| # future use__ , optional_capacities: "+PACEAPI" do |c|
67
65
 
68
66
  c.subscribe( :ContractData, :BondContractData) { |msg| c.logger.info { msg.contract.to_human } }
69
67
  c.subscribe( :Alert, :ContractDataEnd, :ManagedAccounts, :OrderStatus ) {| m| c.logger.info { m.to_human } }
70
68
  c.subscribe( :PortfolioValue, :AccountValue, :OrderStatus, :OpenOrderEnd, :ExecutionData ) {| m| c.logger.info { m.to_human }}
71
69
  # c.subscribe :ManagedAccounts do |msg|
72
- # puts "------------------------------- Managed Accounts ----------------------------------"
73
- # puts "Detected Accounts: #{msg.accounts.account.join(' -- ')} "
70
+ # puts "------------------------------ Managed Accounts ----------------------------------"
71
+ # puts "Detected Accounts: #{msg.acounts.account.join(' -- ')} "
74
72
  # puts
75
73
  # end
76
74
 
77
- c.subscribe( :OpenOrder){ |msg| "Open Order detected and stored: C.received[:OpenOrders] " }
78
- end
75
+ c.subscribe( :OpenOrder){ |msg| puts "Open Order detected and stored: C.received[:OpenOrders] " }
76
+ end
79
77
  #C.logger.level = Logger::FATAL
80
78
  unless C.received[:OpenOrder].blank?
81
79
  puts "------------------------------- OpenOrders ----------------------------------"
data/bin/console.yml CHANGED
@@ -1,3 +1,3 @@
1
1
  :gateway: 4002
2
2
  :tws: 7496
3
- :client_id: 2000
3
+ :client_id: 205600
data/lib/ib/connection.rb CHANGED
@@ -182,7 +182,7 @@ module IB
182
182
  when what.is_a?(Symbol)
183
183
  if Messages::Incoming.const_defined?(what)
184
184
  [Messages::Incoming.const_get(what)]
185
- elsif TechnicalAnalysis::Signals.const_defined?(what)
185
+ elsif defined?( TechnicalAnalysis ) && TechnicalAnalysis::Signals.const_defined?(what)
186
186
  [TechnicalAnalysis::Signals.const_get?(what)]
187
187
  else
188
188
  error "#{what} is no IB::Messages or TechnicalAnalyis::Signals class"
@@ -284,22 +284,27 @@ module IB
284
284
  begin
285
285
  while (time_left = time_out - Time.now) > 0
286
286
  # If socket is readable, process single incoming message
287
- #process_message if select [socket], nil, nil, time_left
287
+ if RUBY_PLATFORM.match(/cygwin|mswin|mingw|bccwin|wince|emx/)
288
+ process_message if select [socket], nil, nil, time_left
289
+
290
+
288
291
  # the following checks for shutdown of TWS side; ensures we don't run in a spin loop.
289
292
  # unfortunately, it raises Errors in windows environment
290
- if select [socket], nil, nil, time_left
291
- # # Peek at the message from the socket; if it's blank then the
292
- # # server side of connection (TWS) has likely shut down.
293
- socket_likely_shutdown = socket.recvmsg(100, Socket::MSG_PEEK)[0] == ""
294
- #
295
- # # We go ahead process messages regardless (a no-op if socket_likely_shutdown).
296
- process_message
297
- #
298
- # # After processing, if socket has shut down we sleep for 100ms
299
- # # to avoid spinning in a tight loop. If the server side somehow
300
- # # comes back up (gets reconnedted), normal processing
301
- # # (without the 100ms wait) should happen.
302
- sleep(0.1) if socket_likely_shutdown
293
+ else
294
+ if select [socket], nil, nil, time_left
295
+ # # Peek at the message from the socket; if it's blank then the
296
+ # # server side of connection (TWS) has likely shut down.
297
+ socket_likely_shutdown = socket.recvmsg(100, Socket::MSG_PEEK)[0] == ""
298
+ #
299
+ # # We go ahead process messages regardless (a no-op if socket_likely_shutdown).
300
+ process_message
301
+ #
302
+ # # After processing, if socket has shut down we sleep for 100ms
303
+ # # to avoid spinning in a tight loop. If the server side somehow
304
+ # # comes back up (gets reconnedted), normal processing
305
+ # # (without the 100ms wait) should happen.
306
+ sleep(0.1) if socket_likely_shutdown
307
+ end
303
308
  end
304
309
  end
305
310
  rescue Errno::ECONNRESET => e
@@ -307,7 +312,7 @@ module IB
307
312
  if e.message =~ /Connection reset by peer/
308
313
  logger.fatal "Is another client listening on the same port?"
309
314
  error "try reconnecting with a different client-id", :reader
310
- else
315
+ else
311
316
  logger.fatal "Aborting"
312
317
  Kernel.exit
313
318
  end
@@ -417,14 +422,17 @@ module IB
417
422
  msg_id = the_decoded_message.shift.to_i
418
423
 
419
424
  # Debug:
420
- # logger.debug { "Got message #{msg_id} (#{Messages::Incoming::Classes[msg_id]})"}
425
+ logger.debug { "Got message #{msg_id} (#{Messages::Incoming::Classes[msg_id]})"}
421
426
 
422
427
  # Create new instance of the appropriate message type,
423
428
  # and have it read the message from socket.
424
429
  # NB: Failure here usually means unsupported message type received
425
- logger.error { "Got unsupported message #{msg_id}" } unless Messages::Incoming::Classes[msg_id]
426
- error "Something strange happened - Reader has to be restarted" , :reader, true if msg_id.to_i.zero?
427
- msg = Messages::Incoming::Classes[msg_id].new(the_decoded_message)
430
+ unless Messages::Incoming::Classes[msg_id]
431
+ logger.error { "Got unsupported message #{msg_id}" }
432
+ error "Something strange happened - Reader has to be restarted" , :reader, true if msg_id.to_i.zero?
433
+ else
434
+ msg = Messages::Incoming::Classes[msg_id].new(the_decoded_message)
435
+ end
428
436
 
429
437
  # Deliver message to all registered subscribers, alert if no subscribers
430
438
  # Ruby 2.0 and above: Hashes are ordered.
@@ -62,7 +62,7 @@ module IB
62
62
  bar_size,
63
63
  data_type.to_s.upcase,
64
64
  @data[:use_rth] ,
65
- "XYZ" # not suported realtimebars option string
65
+ "" # not suported realtimebars option string
66
66
  ]
67
67
  end
68
68
  end # RequestRealTimeBars
@@ -189,7 +189,7 @@ module IB
189
189
  2 , # @data[:format_date], format-date is hard-coded as int_date in incoming/historicalData
190
190
  contract.serialize_legs ,
191
191
  @data[:keep_up_todate], # 0 / 1
192
- 'XYZ' # chartOptions:TagValueList - For internal use only. Use default value XYZ.
192
+ '' # chartOptions:TagValueList - For internal use only. Use default value XYZ.
193
193
  ]
194
194
  end
195
195
  end # RequestHistoricalData
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IB
4
+ # Convert data passed in from a TCP socket stream, and convert into
5
+ # raw messages. The messages
6
+ class RawMessageParser
7
+ HEADER_LNGTH = 4
8
+ def initialize(socket)
9
+ @socket = socket
10
+ @data = String.new
11
+ end
12
+
13
+ def each
14
+ while true
15
+ append_new_data
16
+
17
+ next unless length_data?
18
+ next unless enough_data?
19
+
20
+ length = next_msg_length
21
+ validate_data_header(length)
22
+
23
+ raw = grab_message(length)
24
+ validate_message_footer(raw, length)
25
+ msg = parse_message(raw, length)
26
+ remove_message
27
+ yield msg
28
+ end
29
+ end
30
+
31
+ # extract message and convert to
32
+ # an array split by null characters.
33
+ def grab_message(length)
34
+ @data.byteslice(HEADER_LNGTH, length)
35
+ end
36
+
37
+ def parse_message(raw, length)
38
+ raw.unpack1("A#{length}").split("\0")
39
+ end
40
+
41
+ def remove_message
42
+ length = next_msg_length
43
+ leftovers = @data.byteslice(length + HEADER_LNGTH..-1)
44
+ @data = if leftovers.nil?
45
+ String.new
46
+ else
47
+ leftovers
48
+ end
49
+ end
50
+
51
+ def enough_data?
52
+ actual_lngth = next_msg_length + HEADER_LNGTH
53
+ echo 'too little data' if next_msg_length.nil?
54
+ return false if next_msg_length.nil?
55
+ @data.bytesize >= actual_lngth
56
+ end
57
+
58
+ def length_data?
59
+ @data.bytesize > HEADER_LNGTH
60
+ end
61
+
62
+ def next_msg_length
63
+ #can't check length if first 4 bytes don't exist
64
+ length = @data.byteslice(0..3).unpack1('N')
65
+ return 0 if length.nil?
66
+ length
67
+ end
68
+
69
+ def append_new_data
70
+ @data += @socket.recv_from
71
+ end
72
+
73
+ def validate_message_footer(msg,length)
74
+ last = msg.bytesize
75
+ last_byte = msg.byteslice(last-1,last)
76
+ raise 'Could not validate last byte' if last_byte.nil?
77
+ raise "Message has an invalid last byte. expecting \0, received: #{last_byte}" if last_byte != "\0"
78
+ end
79
+
80
+ def validate_data_header(length)
81
+ return true if length <= 5000
82
+ raise 'Message is longer than sane max length'
83
+ end
84
+ end
85
+ end
data/lib/logging.rb CHANGED
@@ -26,20 +26,21 @@ module Support
26
26
  @logger = logger
27
27
  end
28
28
 
29
- def configure_logger(log=nil)
30
- if log
29
+ def configure_logger(log= STDOUT)
30
+ if log.is_a? Logger
31
31
  @logger = log
32
32
  else
33
- @logger = Logger.new(STDOUT)
34
- @logger.level = Logger::INFO
35
- @logger.formatter = proc do |severity, datetime, progname, msg|
33
+ @logger = Logger.new log
34
+ end
35
+ @logger.level = Logger::INFO
36
+ @logger.formatter = proc do |severity, datetime, progname, msg|
36
37
  # "#{datetime.strftime("%d.%m.(%X)")}#{"%5s" % severity}->#{msg}\n"
37
38
  "#{"%1s" % severity[0]}: #{msg}\n"
38
39
  end
39
- @logger.debug "------------------------------ start logging ----------------------------"
40
- end # branch
40
+ @logger.debug "------------------------------ start logging ----------------------------"
41
41
  end # def
42
42
  end # module ClassMethods
43
43
  end # module Logging
44
44
  end # module Support
45
45
 
46
+ # source: https://github.com/jondot/sneakers/blob/master/lib/sneakers/concerns/logging.rb
@@ -5,7 +5,7 @@ require 'models/ib/underlying'
5
5
 
6
6
  module IB
7
7
 
8
- if defined?(Contract)
8
+ if defined?(Contract)
9
9
  #Connection.current.logger.warn "Contract already a #{defined?(Contract)}"
10
10
 
11
11
  # puts Contract.ancestors
@@ -537,5 +537,11 @@ Format of serialisation
537
537
  'OrderState' => order_state}
538
538
  end
539
539
 
540
+ # expell uncommon attributes
541
+ def invariant_attributes
542
+ attributes.reject{ |x| [ :designated_location, :display_size, :etrade_only, :exempt_code, :ext_operator, :random_size, :random_price, :firm_quote_only, :scale_auto_reset, :scale_random_percent, :scale_table, :short_sale_slot, :solicided, :created_at, :modified_at ].include? x }
543
+
544
+ end
545
+
540
546
  end # class Order
541
547
  end # module IB
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ib-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 972.5.1
4
+ version: 972.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hartmut Bischoff
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-01-15 00:00:00.000000000 Z
11
+ date: 2023-03-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -165,6 +165,7 @@ files:
165
165
  - lib/ib/messages/outgoing/request_tick_data.rb
166
166
  - lib/ib/model.rb
167
167
  - lib/ib/models.rb
168
+ - lib/ib/raw_message.rb
168
169
  - lib/ib/server_versions.rb
169
170
  - lib/ib/socket.rb
170
171
  - lib/ib/support.rb