ib_ruby_proxy 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.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +77 -0
  3. data/.gitignore +8 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +143 -0
  6. data/.ruby-version +1 -0
  7. data/.travis.yml +7 -0
  8. data/Gemfile +10 -0
  9. data/Gemfile.lock +74 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +130 -0
  12. data/Rakefile +12 -0
  13. data/bin/console +14 -0
  14. data/bin/generate_ruby_classes +13 -0
  15. data/bin/ibproxy +32 -0
  16. data/bin/setup +8 -0
  17. data/docs/diagrams.key +0 -0
  18. data/docs/images/architecture.png +0 -0
  19. data/examples/common.rb +14 -0
  20. data/examples/plain_req_historical_ticks.rb +19 -0
  21. data/examples/req_contract_details.rb +9 -0
  22. data/examples/req_historical_bars_data.rb +10 -0
  23. data/examples/req_historical_ticks.rb +10 -0
  24. data/examples/req_tick_by_tick_data.rb +9 -0
  25. data/ib_ruby_proxy.gemspec +43 -0
  26. data/lib/ib_ruby_proxy.rb +35 -0
  27. data/lib/ib_ruby_proxy/client/callbacks_response_handler.rb +135 -0
  28. data/lib/ib_ruby_proxy/client/client.rb +69 -0
  29. data/lib/ib_ruby_proxy/client/ib/bar.rb +36 -0
  30. data/lib/ib_ruby_proxy/client/ib/combo_leg.rb +36 -0
  31. data/lib/ib_ruby_proxy/client/ib/contract.rb +56 -0
  32. data/lib/ib_ruby_proxy/client/ib/contract_details.rb +100 -0
  33. data/lib/ib_ruby_proxy/client/ib/delta_neutral_contract.rb +26 -0
  34. data/lib/ib_ruby_proxy/client/ib/historical_tick.rb +26 -0
  35. data/lib/ib_ruby_proxy/client/ib/historical_tick_bid_ask.rb +32 -0
  36. data/lib/ib_ruby_proxy/client/ib/historical_tick_last.rb +32 -0
  37. data/lib/ib_ruby_proxy/client/ib/order.rb +262 -0
  38. data/lib/ib_ruby_proxy/client/ib/tick_attrib_bid_ask.rb +24 -0
  39. data/lib/ib_ruby_proxy/client/ib/tick_attrib_last.rb +24 -0
  40. data/lib/ib_ruby_proxy/client/ib_callbacks_observer.rb +25 -0
  41. data/lib/ib_ruby_proxy/config.yml +43 -0
  42. data/lib/ib_ruby_proxy/server/ext/array.rb +22 -0
  43. data/lib/ib_ruby_proxy/server/ext/enum.rb +20 -0
  44. data/lib/ib_ruby_proxy/server/ext/idempotent_types.rb +23 -0
  45. data/lib/ib_ruby_proxy/server/ib/bar.rb +21 -0
  46. data/lib/ib_ruby_proxy/server/ib/combo_leg.rb +21 -0
  47. data/lib/ib_ruby_proxy/server/ib/contract.rb +31 -0
  48. data/lib/ib_ruby_proxy/server/ib/contract_details.rb +53 -0
  49. data/lib/ib_ruby_proxy/server/ib/delta_neutral_contract.rb +16 -0
  50. data/lib/ib_ruby_proxy/server/ib/historical_tick.rb +16 -0
  51. data/lib/ib_ruby_proxy/server/ib/historical_tick_bid_ask.rb +19 -0
  52. data/lib/ib_ruby_proxy/server/ib/historical_tick_last.rb +19 -0
  53. data/lib/ib_ruby_proxy/server/ib/order.rb +134 -0
  54. data/lib/ib_ruby_proxy/server/ib/tick_attrib_bid_ask.rb +15 -0
  55. data/lib/ib_ruby_proxy/server/ib/tick_attrib_last.rb +15 -0
  56. data/lib/ib_ruby_proxy/server/ib_client_adapter.rb +51 -0
  57. data/lib/ib_ruby_proxy/server/ib_proxy_service.rb +85 -0
  58. data/lib/ib_ruby_proxy/server/ib_ruby_class_files_generator.rb +77 -0
  59. data/lib/ib_ruby_proxy/server/ib_ruby_class_source_generator.rb +155 -0
  60. data/lib/ib_ruby_proxy/server/ib_wrapper_adapter.rb +47 -0
  61. data/lib/ib_ruby_proxy/server/reflection/ib_class.rb +62 -0
  62. data/lib/ib_ruby_proxy/server/reflection/ib_field.rb +60 -0
  63. data/lib/ib_ruby_proxy/util/has_logger.rb +10 -0
  64. data/lib/ib_ruby_proxy/util/string_utils.rb +29 -0
  65. data/lib/ib_ruby_proxy/version.rb +3 -0
  66. data/lib/server.rb +4 -0
  67. data/sandbox/drb_performance/client.rb +46 -0
  68. data/sandbox/drb_performance/server.rb +26 -0
  69. data/vendor/TwsApi.jar +0 -0
  70. metadata +226 -0
@@ -0,0 +1,62 @@
1
+ module IbRubyProxy
2
+ module Server
3
+ module Reflection
4
+ # An ib class
5
+ class IbClass
6
+ include IbRubyProxy::Util::StringUtils
7
+
8
+ attr_reader :klass
9
+
10
+ # @param [Class] klass
11
+ def initialize(klass)
12
+ @klass = klass
13
+ end
14
+
15
+ # The class name without including namespaces
16
+ #
17
+ # @return [String]
18
+ def name
19
+ klass.name.split('::').last
20
+ end
21
+
22
+ # The full qualified class name including namespace
23
+ #
24
+ # @return [Object]
25
+ def full_name
26
+ klass.name
27
+ end
28
+
29
+ # List of ib fields that represent properties to interchange
30
+ #
31
+ # @return [Array<IbField>]
32
+ def java_property_fields
33
+ @java_property_fields ||= java_fields.collect { |field| IbField.new(field, self) }
34
+ end
35
+
36
+ # List of ruby properties names that correspond to {#java_property_fields}
37
+ #
38
+ # @return [Array<String>]
39
+ def ruby_property_names
40
+ @ruby_properties ||= java_property_fields.collect do |field|
41
+ to_underscore(field.name)
42
+ end
43
+ end
44
+
45
+ # Return an array of combinations of {#ruby_property_names} and #{java_property_fields}
46
+ #
47
+ # @return [Array<Array<String, IbField>>]
48
+ def zipped_ruby_and_java_properties
49
+ ruby_property_names.zip(java_property_fields)
50
+ end
51
+
52
+ private
53
+
54
+ def java_fields
55
+ @java_property_fields ||= klass.java_class.declared_fields.find_all do |field|
56
+ field.name =~ IbField::IB_FIELD_PREFIX
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,60 @@
1
+ module IbRubyProxy
2
+ module Server
3
+ module Reflection
4
+ # An {IbClass} field
5
+ class IbField
6
+ IB_FIELD_PREFIX = /^m_/.freeze
7
+
8
+ attr_reader :java_field, :ib_class
9
+
10
+ def initialize(java_field, ib_class)
11
+ @java_field = java_field
12
+ @ib_class = ib_class
13
+ end
14
+
15
+ # Default value for the field
16
+ #
17
+ # @return [Object]
18
+ def default_value
19
+ case java_field.type
20
+ when Java::int.java_class, Java::float.java_class, Java::double.java_class
21
+ 0
22
+ when Java::boolean.java_class
23
+ false
24
+ end
25
+ end
26
+
27
+ # {#default_value Default value} as a string
28
+ #
29
+ # @return [String]
30
+ def default_value_as_string
31
+ value = default_value
32
+ if value.nil?
33
+ 'nil'
34
+ else
35
+ value.to_s
36
+ end
37
+ end
38
+
39
+ # Return the name of the accessor method used to access the field
40
+ #
41
+ # @return [String]
42
+ def name
43
+ @name ||= find_name
44
+ end
45
+
46
+ private
47
+
48
+ def find_name
49
+ field_name_without_prefix = java_field.name.gsub(IB_FIELD_PREFIX, '')
50
+ matched_method = ib_class.klass.java_class.declared_instance_methods.find do |method|
51
+ method.name.downcase == field_name_without_prefix.downcase
52
+ end
53
+ raise "No method matching '#{field.name}'?" unless matched_method
54
+
55
+ matched_method.name
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,10 @@
1
+ module IbRubyProxy
2
+ module Util
3
+ # Mixin to add access to the gem logger
4
+ module HasLogger
5
+ def logger
6
+ @logger ||= IbRubyProxy.logger
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,29 @@
1
+ module IbRubyProxy
2
+ module Util
3
+ # String utility methods
4
+ module StringUtils
5
+ extend self
6
+
7
+ # Makes passed string underscored and lowercase
8
+ #
9
+ # @param [String] string
10
+ #
11
+ # Implementation copied from Rails
12
+ # @see https://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-underscore
13
+ def to_underscore(string)
14
+ string.gsub(/::/, '/')
15
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
16
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
17
+ .tr('-', '_')
18
+ .downcase
19
+ end
20
+
21
+ # Converts passed string into camel case syntax
22
+ #
23
+ # @see https://stackoverflow.com/a/11411200/469697
24
+ def to_camel_case(string)
25
+ string.split('_').inject([]) { |buffer, e| buffer.push(buffer.empty? ? e : e.capitalize) }.join
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module IbRubyProxy
2
+ VERSION = '0.0.1'.freeze
3
+ end
@@ -0,0 +1,4 @@
1
+ require 'ib_ruby_proxy/version'
2
+ require_relative '../vendor/TwsApi.jar'
3
+
4
+ Dir["#{__dir__}/ib_ruby_proxy/server/**/*.rb"].each { |file| require file }
@@ -0,0 +1,46 @@
1
+ require 'drb'
2
+ require 'benchmark'
3
+
4
+ # This is a dummy performance test to have an idea of drb throughput. I got it's possible to
5
+ # process 10000 notifications per second with MRI ruby 2.5, which should be enough for real
6
+ # time tick data.
7
+ class ResultCallback
8
+ include DRbUndumped
9
+
10
+ attr_reader :total
11
+
12
+ def initialize
13
+ @total = 0
14
+ end
15
+
16
+ def update(_number1, _number2, result)
17
+ @total += result
18
+ end
19
+ end
20
+
21
+ @server = DRbObject.new(nil, 'druby://localhost:1992')
22
+ DRb.start_service
23
+
24
+ result_callback = ResultCallback.new
25
+ @server.add_observer(result_callback)
26
+
27
+ LOOP_COUNT = 10000
28
+
29
+ drb_benchmark = Benchmark.measure do
30
+ LOOP_COUNT.times do |i|
31
+ @server.add(i, i + 1)
32
+ end
33
+ end
34
+
35
+ total = 0
36
+ ruby_benchmark = Benchmark.measure do
37
+ LOOP_COUNT.times do |i|
38
+ total += (i + (i + 1))
39
+ end
40
+ end
41
+
42
+ puts "With drb: #{result_callback.total}"
43
+ puts drb_benchmark
44
+
45
+ puts "With plain ruby: #{total}"
46
+ puts ruby_benchmark
@@ -0,0 +1,26 @@
1
+ require 'drb'
2
+ require 'drb/observer'
3
+
4
+ class Server
5
+ include DRb::DRbObservable
6
+ attr_accessor :object
7
+
8
+ def initialize
9
+ @object = { id: 'from server side' }
10
+ end
11
+
12
+ def add(numnber1, number2)
13
+ changed
14
+ notify_observers(numnber1, number2, numnber1 + number2)
15
+ end
16
+ end
17
+
18
+ server = Server.new
19
+
20
+ DRb.start_service('druby://localhost:1992', server)
21
+
22
+ begin
23
+ DRb.thread.join
24
+ rescue StandardError
25
+ Process.kill('TERM', Process.pid)
26
+ end
Binary file
metadata ADDED
@@ -0,0 +1,226 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ib_ruby_proxy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jorge Manrubia
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-07-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ name: awesome_print
20
+ prerelease: false
21
+ type: :runtime
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ name: commander
34
+ prerelease: false
35
+ type: :runtime
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ name: concurrent-ruby
48
+ prerelease: false
49
+ type: :runtime
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 2.0.1
61
+ name: bundler
62
+ prerelease: false
63
+ type: :development
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 2.0.1
69
+ - !ruby/object:Gem::Dependency
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ name: impersonator
76
+ prerelease: false
77
+ type: :development
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '10.0'
89
+ name: rake
90
+ prerelease: false
91
+ type: :development
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '10.0'
97
+ - !ruby/object:Gem::Dependency
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: 3.8.0
103
+ name: rspec
104
+ prerelease: false
105
+ type: :development
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 3.8.0
111
+ - !ruby/object:Gem::Dependency
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ name: rspec_junit_formatter
118
+ prerelease: false
119
+ type: :development
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Invoke IB Java API from Ruby
126
+ email:
127
+ - jorge.manrubia@gmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".circleci/config.yml"
133
+ - ".gitignore"
134
+ - ".rspec"
135
+ - ".rubocop.yml"
136
+ - ".ruby-version"
137
+ - ".travis.yml"
138
+ - Gemfile
139
+ - Gemfile.lock
140
+ - LICENSE.txt
141
+ - README.md
142
+ - Rakefile
143
+ - bin/console
144
+ - bin/generate_ruby_classes
145
+ - bin/ibproxy
146
+ - bin/setup
147
+ - docs/diagrams.key
148
+ - docs/images/architecture.png
149
+ - examples/common.rb
150
+ - examples/plain_req_historical_ticks.rb
151
+ - examples/req_contract_details.rb
152
+ - examples/req_historical_bars_data.rb
153
+ - examples/req_historical_ticks.rb
154
+ - examples/req_tick_by_tick_data.rb
155
+ - ib_ruby_proxy.gemspec
156
+ - lib/ib_ruby_proxy.rb
157
+ - lib/ib_ruby_proxy/client/callbacks_response_handler.rb
158
+ - lib/ib_ruby_proxy/client/client.rb
159
+ - lib/ib_ruby_proxy/client/ib/bar.rb
160
+ - lib/ib_ruby_proxy/client/ib/combo_leg.rb
161
+ - lib/ib_ruby_proxy/client/ib/contract.rb
162
+ - lib/ib_ruby_proxy/client/ib/contract_details.rb
163
+ - lib/ib_ruby_proxy/client/ib/delta_neutral_contract.rb
164
+ - lib/ib_ruby_proxy/client/ib/historical_tick.rb
165
+ - lib/ib_ruby_proxy/client/ib/historical_tick_bid_ask.rb
166
+ - lib/ib_ruby_proxy/client/ib/historical_tick_last.rb
167
+ - lib/ib_ruby_proxy/client/ib/order.rb
168
+ - lib/ib_ruby_proxy/client/ib/tick_attrib_bid_ask.rb
169
+ - lib/ib_ruby_proxy/client/ib/tick_attrib_last.rb
170
+ - lib/ib_ruby_proxy/client/ib_callbacks_observer.rb
171
+ - lib/ib_ruby_proxy/config.yml
172
+ - lib/ib_ruby_proxy/server/ext/array.rb
173
+ - lib/ib_ruby_proxy/server/ext/enum.rb
174
+ - lib/ib_ruby_proxy/server/ext/idempotent_types.rb
175
+ - lib/ib_ruby_proxy/server/ib/bar.rb
176
+ - lib/ib_ruby_proxy/server/ib/combo_leg.rb
177
+ - lib/ib_ruby_proxy/server/ib/contract.rb
178
+ - lib/ib_ruby_proxy/server/ib/contract_details.rb
179
+ - lib/ib_ruby_proxy/server/ib/delta_neutral_contract.rb
180
+ - lib/ib_ruby_proxy/server/ib/historical_tick.rb
181
+ - lib/ib_ruby_proxy/server/ib/historical_tick_bid_ask.rb
182
+ - lib/ib_ruby_proxy/server/ib/historical_tick_last.rb
183
+ - lib/ib_ruby_proxy/server/ib/order.rb
184
+ - lib/ib_ruby_proxy/server/ib/tick_attrib_bid_ask.rb
185
+ - lib/ib_ruby_proxy/server/ib/tick_attrib_last.rb
186
+ - lib/ib_ruby_proxy/server/ib_client_adapter.rb
187
+ - lib/ib_ruby_proxy/server/ib_proxy_service.rb
188
+ - lib/ib_ruby_proxy/server/ib_ruby_class_files_generator.rb
189
+ - lib/ib_ruby_proxy/server/ib_ruby_class_source_generator.rb
190
+ - lib/ib_ruby_proxy/server/ib_wrapper_adapter.rb
191
+ - lib/ib_ruby_proxy/server/reflection/ib_class.rb
192
+ - lib/ib_ruby_proxy/server/reflection/ib_field.rb
193
+ - lib/ib_ruby_proxy/util/has_logger.rb
194
+ - lib/ib_ruby_proxy/util/string_utils.rb
195
+ - lib/ib_ruby_proxy/version.rb
196
+ - lib/server.rb
197
+ - sandbox/drb_performance/client.rb
198
+ - sandbox/drb_performance/server.rb
199
+ - vendor/TwsApi.jar
200
+ homepage: https://github.com/jorgemanrubia/ib_ruby_proxy
201
+ licenses:
202
+ - MIT
203
+ metadata:
204
+ homepage_uri: https://github.com/jorgemanrubia/ib_ruby_proxy
205
+ source_code_uri: https://github.com/jorgemanrubia/ib_ruby_proxy
206
+ post_install_message:
207
+ rdoc_options: []
208
+ require_paths:
209
+ - lib
210
+ required_ruby_version: !ruby/object:Gem::Requirement
211
+ requirements:
212
+ - - ">="
213
+ - !ruby/object:Gem::Version
214
+ version: '0'
215
+ required_rubygems_version: !ruby/object:Gem::Requirement
216
+ requirements:
217
+ - - ">="
218
+ - !ruby/object:Gem::Version
219
+ version: '0'
220
+ requirements: []
221
+ rubyforge_project:
222
+ rubygems_version: 2.7.9
223
+ signing_key:
224
+ specification_version: 4
225
+ summary: Invoke IB Java API from Ruby
226
+ test_files: []