ib_ruby_proxy 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.circleci/config.yml +77 -0
- data/.gitignore +8 -0
- data/.rspec +1 -0
- data/.rubocop.yml +143 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +74 -0
- data/LICENSE.txt +21 -0
- data/README.md +130 -0
- data/Rakefile +12 -0
- data/bin/console +14 -0
- data/bin/generate_ruby_classes +13 -0
- data/bin/ibproxy +32 -0
- data/bin/setup +8 -0
- data/docs/diagrams.key +0 -0
- data/docs/images/architecture.png +0 -0
- data/examples/common.rb +14 -0
- data/examples/plain_req_historical_ticks.rb +19 -0
- data/examples/req_contract_details.rb +9 -0
- data/examples/req_historical_bars_data.rb +10 -0
- data/examples/req_historical_ticks.rb +10 -0
- data/examples/req_tick_by_tick_data.rb +9 -0
- data/ib_ruby_proxy.gemspec +43 -0
- data/lib/ib_ruby_proxy.rb +35 -0
- data/lib/ib_ruby_proxy/client/callbacks_response_handler.rb +135 -0
- data/lib/ib_ruby_proxy/client/client.rb +69 -0
- data/lib/ib_ruby_proxy/client/ib/bar.rb +36 -0
- data/lib/ib_ruby_proxy/client/ib/combo_leg.rb +36 -0
- data/lib/ib_ruby_proxy/client/ib/contract.rb +56 -0
- data/lib/ib_ruby_proxy/client/ib/contract_details.rb +100 -0
- data/lib/ib_ruby_proxy/client/ib/delta_neutral_contract.rb +26 -0
- data/lib/ib_ruby_proxy/client/ib/historical_tick.rb +26 -0
- data/lib/ib_ruby_proxy/client/ib/historical_tick_bid_ask.rb +32 -0
- data/lib/ib_ruby_proxy/client/ib/historical_tick_last.rb +32 -0
- data/lib/ib_ruby_proxy/client/ib/order.rb +262 -0
- data/lib/ib_ruby_proxy/client/ib/tick_attrib_bid_ask.rb +24 -0
- data/lib/ib_ruby_proxy/client/ib/tick_attrib_last.rb +24 -0
- data/lib/ib_ruby_proxy/client/ib_callbacks_observer.rb +25 -0
- data/lib/ib_ruby_proxy/config.yml +43 -0
- data/lib/ib_ruby_proxy/server/ext/array.rb +22 -0
- data/lib/ib_ruby_proxy/server/ext/enum.rb +20 -0
- data/lib/ib_ruby_proxy/server/ext/idempotent_types.rb +23 -0
- data/lib/ib_ruby_proxy/server/ib/bar.rb +21 -0
- data/lib/ib_ruby_proxy/server/ib/combo_leg.rb +21 -0
- data/lib/ib_ruby_proxy/server/ib/contract.rb +31 -0
- data/lib/ib_ruby_proxy/server/ib/contract_details.rb +53 -0
- data/lib/ib_ruby_proxy/server/ib/delta_neutral_contract.rb +16 -0
- data/lib/ib_ruby_proxy/server/ib/historical_tick.rb +16 -0
- data/lib/ib_ruby_proxy/server/ib/historical_tick_bid_ask.rb +19 -0
- data/lib/ib_ruby_proxy/server/ib/historical_tick_last.rb +19 -0
- data/lib/ib_ruby_proxy/server/ib/order.rb +134 -0
- data/lib/ib_ruby_proxy/server/ib/tick_attrib_bid_ask.rb +15 -0
- data/lib/ib_ruby_proxy/server/ib/tick_attrib_last.rb +15 -0
- data/lib/ib_ruby_proxy/server/ib_client_adapter.rb +51 -0
- data/lib/ib_ruby_proxy/server/ib_proxy_service.rb +85 -0
- data/lib/ib_ruby_proxy/server/ib_ruby_class_files_generator.rb +77 -0
- data/lib/ib_ruby_proxy/server/ib_ruby_class_source_generator.rb +155 -0
- data/lib/ib_ruby_proxy/server/ib_wrapper_adapter.rb +47 -0
- data/lib/ib_ruby_proxy/server/reflection/ib_class.rb +62 -0
- data/lib/ib_ruby_proxy/server/reflection/ib_field.rb +60 -0
- data/lib/ib_ruby_proxy/util/has_logger.rb +10 -0
- data/lib/ib_ruby_proxy/util/string_utils.rb +29 -0
- data/lib/ib_ruby_proxy/version.rb +3 -0
- data/lib/server.rb +4 -0
- data/sandbox/drb_performance/client.rb +46 -0
- data/sandbox/drb_performance/server.rb +26 -0
- data/vendor/TwsApi.jar +0 -0
- metadata +226 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f15e4170756014f9696cc4e11069c47ca7bc343b1a892cc165e8b5e333bb8698
|
4
|
+
data.tar.gz: 2bfe95f6d33fe103fc6fb871a926da3a89b344438b25dfa8cd3d793bac7242f5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 271d3a9ca6b05dd81ad07909aeac6c583840ac211f903d6a5b45477423709f75de16744044d92c8bca9f8734bc5d48d39aac7183318d25de8e0d978ebc114861
|
7
|
+
data.tar.gz: c2c80be2097ccfeb0c8c9f2d1877b877ebd501d0098a566f709eb2e80c4086c0faba2850adbc439adcf96dddec53cd4aafb52c45b427591f906a0a4ce3016a0b
|
@@ -0,0 +1,77 @@
|
|
1
|
+
version: 2.1
|
2
|
+
defaults: &defaults
|
3
|
+
working_directory: ~/ib_ruby_proxy
|
4
|
+
docker:
|
5
|
+
- image: circleci/jruby:9.2.7.0-jdk-node-browsers
|
6
|
+
environment:
|
7
|
+
BUNDLE_PATH: vendor/bundle
|
8
|
+
PGHOST: 127.0.0.1
|
9
|
+
PGUSER: ib_ruby_proxy
|
10
|
+
commands:
|
11
|
+
prepare:
|
12
|
+
description: "Common preparation steps"
|
13
|
+
steps:
|
14
|
+
- checkout
|
15
|
+
|
16
|
+
- restore_cache:
|
17
|
+
keys:
|
18
|
+
- v1-dependencies-{{ checksum "Gemfile.lock" }}
|
19
|
+
# fallback to using the latest cache if no exact match is found
|
20
|
+
- v1-dependencies-
|
21
|
+
- run:
|
22
|
+
name: install bundler
|
23
|
+
command: |
|
24
|
+
gem install bundler
|
25
|
+
|
26
|
+
- run:
|
27
|
+
name: install dependencies
|
28
|
+
command: |
|
29
|
+
bundle install --jobs=4 --retry=3 --path vendor/bundle
|
30
|
+
|
31
|
+
- save_cache:
|
32
|
+
paths:
|
33
|
+
- ./vendor/bundle
|
34
|
+
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
|
35
|
+
|
36
|
+
jobs:
|
37
|
+
tests:
|
38
|
+
<<: *defaults
|
39
|
+
steps:
|
40
|
+
- prepare
|
41
|
+
- run:
|
42
|
+
name: run tests
|
43
|
+
command: |
|
44
|
+
mkdir /tmp/test-results
|
45
|
+
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
|
46
|
+
|
47
|
+
bundle exec rspec --format progress \
|
48
|
+
--format RspecJunitFormatter \
|
49
|
+
--out /tmp/test-results/rspec.xml \
|
50
|
+
--tag ~type:performance \
|
51
|
+
--format progress \
|
52
|
+
$TEST_FILES
|
53
|
+
|
54
|
+
# collect reports
|
55
|
+
- store_test_results:
|
56
|
+
path: /tmp/test-results
|
57
|
+
- store_artifacts:
|
58
|
+
path: /tmp/test-results
|
59
|
+
destination: test-results
|
60
|
+
rubocop:
|
61
|
+
<<: *defaults
|
62
|
+
steps:
|
63
|
+
- prepare
|
64
|
+
- run:
|
65
|
+
name: Rubocop
|
66
|
+
command: bundle exec rubocop
|
67
|
+
workflows:
|
68
|
+
version: 2
|
69
|
+
pipeline:
|
70
|
+
jobs:
|
71
|
+
- tests
|
72
|
+
- rubocop
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
require: rubocop-rspec
|
2
|
+
|
3
|
+
Style/FrozenStringLiteralComment:
|
4
|
+
Enabled: false
|
5
|
+
|
6
|
+
Metrics/LineLength:
|
7
|
+
Max: 105
|
8
|
+
|
9
|
+
Metrics/AbcSize:
|
10
|
+
Enabled: false
|
11
|
+
|
12
|
+
Security/Eval:
|
13
|
+
Enabled: false
|
14
|
+
|
15
|
+
Metrics/CyclomaticComplexity:
|
16
|
+
Enabled: false
|
17
|
+
|
18
|
+
Metrics/BlockLength:
|
19
|
+
Enabled: false
|
20
|
+
|
21
|
+
RSpec/MultipleExpectations:
|
22
|
+
Enabled: false
|
23
|
+
|
24
|
+
Style/ClassAndModuleChildren:
|
25
|
+
Enabled: false
|
26
|
+
|
27
|
+
Naming/BinaryOperatorParameterName:
|
28
|
+
Enabled: false
|
29
|
+
|
30
|
+
Metrics/ParameterLists:
|
31
|
+
Enabled: false
|
32
|
+
|
33
|
+
Style/Documentation:
|
34
|
+
Enabled: false
|
35
|
+
|
36
|
+
Naming/UncommunicativeMethodParamName:
|
37
|
+
Enabled: false
|
38
|
+
|
39
|
+
RSpec/ExampleLength:
|
40
|
+
Enabled: false
|
41
|
+
|
42
|
+
Naming/VariableNumber:
|
43
|
+
Enabled: false
|
44
|
+
|
45
|
+
Metrics/MethodLength:
|
46
|
+
Enabled: false
|
47
|
+
|
48
|
+
RSpec/EmptyExampleGroup:
|
49
|
+
Enabled: false
|
50
|
+
|
51
|
+
RSpec/FilePath:
|
52
|
+
Enabled: false
|
53
|
+
|
54
|
+
Lint/UselessAccessModifier:
|
55
|
+
Enabled: false
|
56
|
+
|
57
|
+
Metrics/ModuleLength:
|
58
|
+
Enabled: false
|
59
|
+
|
60
|
+
RSpec/SubjectStub:
|
61
|
+
Enabled: false
|
62
|
+
|
63
|
+
RSpec/MessageSpies:
|
64
|
+
Enabled: false
|
65
|
+
|
66
|
+
RSpec/VerifiedDoubles:
|
67
|
+
Enabled: false
|
68
|
+
|
69
|
+
RSpec/DescribeClass:
|
70
|
+
Enabled: false
|
71
|
+
|
72
|
+
Style/NumericLiterals:
|
73
|
+
Enabled: false
|
74
|
+
|
75
|
+
Naming/MemoizedInstanceVariableName:
|
76
|
+
Enabled: false
|
77
|
+
|
78
|
+
RSpec/LetSetup:
|
79
|
+
Enabled: false
|
80
|
+
|
81
|
+
# Replace some legits include? usages
|
82
|
+
RSpec/PredicateMatcher:
|
83
|
+
Enabled: false
|
84
|
+
|
85
|
+
# For some algo tests we do want to use instance_vars to capture data within algos
|
86
|
+
RSpec/InstanceVariable:
|
87
|
+
Enabled: false
|
88
|
+
|
89
|
+
Style/ModuleFunction:
|
90
|
+
Enabled: false
|
91
|
+
|
92
|
+
Lint/HandleExceptions:
|
93
|
+
Enabled: false
|
94
|
+
|
95
|
+
RSpec/BeforeAfterAll:
|
96
|
+
Enabled: false
|
97
|
+
|
98
|
+
Lint/Loop:
|
99
|
+
Enabled: false
|
100
|
+
|
101
|
+
Style/NumericPredicate:
|
102
|
+
Enabled: false
|
103
|
+
|
104
|
+
Metrics/ClassLength:
|
105
|
+
Enabled: false
|
106
|
+
|
107
|
+
RSpec/NestedGroups:
|
108
|
+
Enabled: false
|
109
|
+
|
110
|
+
Metrics/PerceivedComplexity:
|
111
|
+
Enabled: false
|
112
|
+
|
113
|
+
Style/GuardClause:
|
114
|
+
Enabled: false
|
115
|
+
|
116
|
+
Naming/RescuedExceptionsVariableName:
|
117
|
+
Enabled: false
|
118
|
+
|
119
|
+
Lint/UnusedMethodArgument:
|
120
|
+
AllowUnusedKeywordArguments: true
|
121
|
+
IgnoreEmptyMethods: true
|
122
|
+
|
123
|
+
Lint/NestedMethodDefinition:
|
124
|
+
Enabled: false
|
125
|
+
|
126
|
+
Style/MethodMissingSuper:
|
127
|
+
Enabled: false
|
128
|
+
|
129
|
+
RSpec/MultipleDescribes:
|
130
|
+
Enabled: false
|
131
|
+
|
132
|
+
AllCops:
|
133
|
+
Exclude:
|
134
|
+
- "**/*.sql"
|
135
|
+
- "recipes/**/*"
|
136
|
+
- "db/**/*"
|
137
|
+
- "tmp/**/*"
|
138
|
+
- "vendor/**/*"
|
139
|
+
- "bin/**/*"
|
140
|
+
- "log/**/*"
|
141
|
+
- "ansible/**/*"
|
142
|
+
- "lib/ib_ruby_proxy/client/ib/*"
|
143
|
+
- "lib/ib_ruby_proxy/server/ib/*"
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
jruby-9.2.7.0
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
ruby '2.5.3', engine: 'jruby', engine_version: '~> 9.2'
|
3
|
+
|
4
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
5
|
+
|
6
|
+
gem 'rubocop'
|
7
|
+
gem 'rubocop-rspec'
|
8
|
+
gem 'rufo', require: false # for linting after generating code
|
9
|
+
|
10
|
+
gemspec
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
ib_ruby_proxy (0.0.1)
|
5
|
+
awesome_print
|
6
|
+
commander
|
7
|
+
concurrent-ruby
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
ast (2.4.0)
|
13
|
+
awesome_print (1.8.0)
|
14
|
+
commander (4.4.7)
|
15
|
+
highline (~> 2.0.0)
|
16
|
+
concurrent-ruby (1.1.5)
|
17
|
+
diff-lcs (1.3)
|
18
|
+
highline (2.0.2)
|
19
|
+
impersonator (0.1.2)
|
20
|
+
zeitwerk (~> 2.1.6)
|
21
|
+
jaro_winkler (1.5.3-java)
|
22
|
+
parallel (1.17.0)
|
23
|
+
parser (2.6.3.0)
|
24
|
+
ast (~> 2.4.0)
|
25
|
+
rainbow (3.0.0)
|
26
|
+
rake (10.5.0)
|
27
|
+
rspec (3.8.0)
|
28
|
+
rspec-core (~> 3.8.0)
|
29
|
+
rspec-expectations (~> 3.8.0)
|
30
|
+
rspec-mocks (~> 3.8.0)
|
31
|
+
rspec-core (3.8.0)
|
32
|
+
rspec-support (~> 3.8.0)
|
33
|
+
rspec-expectations (3.8.2)
|
34
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
35
|
+
rspec-support (~> 3.8.0)
|
36
|
+
rspec-mocks (3.8.0)
|
37
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
38
|
+
rspec-support (~> 3.8.0)
|
39
|
+
rspec-support (3.8.0)
|
40
|
+
rspec_junit_formatter (0.4.1)
|
41
|
+
rspec-core (>= 2, < 4, != 2.12.0)
|
42
|
+
rubocop (0.72.0)
|
43
|
+
jaro_winkler (~> 1.5.1)
|
44
|
+
parallel (~> 1.10)
|
45
|
+
parser (>= 2.6)
|
46
|
+
rainbow (>= 2.2.2, < 4.0)
|
47
|
+
ruby-progressbar (~> 1.7)
|
48
|
+
unicode-display_width (>= 1.4.0, < 1.7)
|
49
|
+
rubocop-rspec (1.33.0)
|
50
|
+
rubocop (>= 0.60.0)
|
51
|
+
ruby-progressbar (1.10.1)
|
52
|
+
rufo (0.4.2)
|
53
|
+
unicode-display_width (1.6.0)
|
54
|
+
zeitwerk (2.1.8)
|
55
|
+
|
56
|
+
PLATFORMS
|
57
|
+
java
|
58
|
+
|
59
|
+
DEPENDENCIES
|
60
|
+
bundler (~> 2.0.1)
|
61
|
+
ib_ruby_proxy!
|
62
|
+
impersonator
|
63
|
+
rake (~> 10.0)
|
64
|
+
rspec (~> 3.8.0)
|
65
|
+
rspec_junit_formatter
|
66
|
+
rubocop
|
67
|
+
rubocop-rspec
|
68
|
+
rufo
|
69
|
+
|
70
|
+
RUBY VERSION
|
71
|
+
ruby 2.5.3p0 (jruby 9.2.7.0)
|
72
|
+
|
73
|
+
BUNDLED WITH
|
74
|
+
2.0.2
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2019 Jorge Manrubia
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
# ib_ruby_proxy
|
2
|
+
|
3
|
+
[![CircleCI](https://circleci.com/gh/jorgemanrubia/ib_ruby_proxy.svg?style=svg)](https://circleci.com/gh/jorgemanrubia/ib_ruby_proxy)
|
4
|
+
|
5
|
+
Service for invoking [Interactive Brokers (IB) api](https://www.interactivebrokers.com/en/index.php?f=5041) from Ruby.
|
6
|
+
|
7
|
+
`ib_ruby_proxy` acts as a mediator between your Ruby code and the IB software making the API calls ([Gateway](https://www.interactivebrokers.com/en/index.php?f=16457) or [TWS](https://www.interactivebrokers.com/en/index.php?f=16457)). Internally, it invokes the official IB Java API and translates objects between Ruby and Java worlds. It also translates method and callback names so that you can use Ruby convention (underscore) instead of Java's (camelcase).
|
8
|
+
|
9
|
+
By design, `ib_ruby_proxy` mimics the IB API design where one entity is used to make all the API calls `EClientSocket` and another entity is used to receive all the callback responses (`EWrapper`). Also, `ib_ruby_proxy` relies on the official [IB Java API implementation](https://interactivebrokers.github.io). Both decisions aim to increase robustness, instead of making lower level API invocations through sockets or elaborated abstractions over how the API works.
|
10
|
+
|
11
|
+
The `ib_ruby_proxy` service needs JRuby installed. Clients of the service can use any standard Ruby distribution. Internally, it uses [DRb](https://ruby-doc.org/stdlib-2.6.3/libdoc/drb/rdoc/DRb.html) to communicate client and server.
|
12
|
+
|
13
|
+
![ib_ruby_proxy architecture](docs/images/architecture.png)
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
### `ib_ruby_proxy` service
|
18
|
+
|
19
|
+
The service requires JRuby 9.2 or higher available in the system.
|
20
|
+
|
21
|
+
```
|
22
|
+
gem install ib_ruby_proxy
|
23
|
+
```
|
24
|
+
|
25
|
+
Start the process:
|
26
|
+
|
27
|
+
`ibproxy`
|
28
|
+
|
29
|
+
By default, it will connect to the IB Gateway software at port `4002` and expose a DRb connection for clients at port `1992`. You can configure both with options `--ib-port` and `--drb-port`. Use `ibproxy help` to see the options available.
|
30
|
+
|
31
|
+
### Clients
|
32
|
+
|
33
|
+
Clients can use any Ruby distribution supporting DRb, including MRI and JRuby. To use in your app add this to your `Gemfile`:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
gem 'ib_ruby_proxy'
|
37
|
+
```
|
38
|
+
|
39
|
+
#### Plain approach
|
40
|
+
|
41
|
+
First, you instantiate a client object to make the API calls:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
client = IbRubyProxy::Client::Client.from_drb
|
45
|
+
```
|
46
|
+
|
47
|
+
Now you can use `client` to invoke API methods. It will use Ruby conventions so, for example, it would be `req_historical_ticks` instead of `reqHistoricalTicks`.
|
48
|
+
|
49
|
+
To receive callbacks, use an `IbRubyProxy::Client::IbCallbacksObserver` implementing the callback methods you want to handle. Again, callback names will use Ruby conventions.
|
50
|
+
|
51
|
+
For example, say you want to get the historical ticks for Apple (AAPL). IB API supports this with its [api method `reqHistoricalTicks` and a callback `historical_ticks` to receive the ticks](https://interactivebrokers.github.io/tws-api/historical_time_and_sales.html). The full example with `ib_ruby_proxy` looks like this:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
client = IbRubyProxy::Client::Client.from_drb
|
55
|
+
|
56
|
+
class CallbacksObserver < IbRubyProxy::Client::IbCallbacksObserver
|
57
|
+
def historical_ticks(_request_id, ticks, _done)
|
58
|
+
pp ticks
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
aapl = IbRubyProxy::Client::Ib::Contract.new symbol: 'AAPL',
|
63
|
+
sec_type: 'STK',
|
64
|
+
exchange: 'ISLAND'
|
65
|
+
|
66
|
+
client.add_ib_callbacks_observer CallbacksObserver.new
|
67
|
+
client.req_historical_ticks(18009, aapl, '20190304 12:00:00', nil, 100,
|
68
|
+
'MIDPOINT', 1, false, nil)
|
69
|
+
```
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
#### Mapped callbacks
|
74
|
+
|
75
|
+
`ib_ruby_proxy` support passing a block to the API methods and have this block invoked with the corresponding received callbacks. The yielded params will include the callback name and the list of arguments accepted by the callback.
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
client.req_historical_ticks(18009, aapl, nil, '20190304 17:00:00', 100,
|
79
|
+
'MIDPOINT', 1, false, nil) do |_callback, _request_id, ticks, _done|
|
80
|
+
pp ticks
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
This feature is currently under development, and not all the mappings have been configured yet. Please check section *Add custom mappings* if you want to contribute new mappings (pull requests welcomed).
|
85
|
+
|
86
|
+
## Development
|
87
|
+
|
88
|
+
### Generated Ruby representations of Java IB classes
|
89
|
+
|
90
|
+
The IB API defines several [value object](https://martinfowler.com/bliki/ValueObject.html) classes to represent the interchanged data. For example, `com.ib.client.Bar` represents a candlestick of market data.
|
91
|
+
|
92
|
+
`ib_ruby_proxy` includes a code generation utility that analyzes the IB Java classes and generates:
|
93
|
+
|
94
|
+
- For the client side, a Ruby representation of each IB class. These classes contain all the data properties and, also, a method for converting them into their Java counterparts.
|
95
|
+
- For the server side, a Ruby extension to the Java class to add a method to turn them into their Ruby counterparts. This is meant for internal use when invoking API methods.
|
96
|
+
|
97
|
+
The list of generated classes is defined by the property `classes` of `lib/ib_ruby_proxy/config.yml`.
|
98
|
+
|
99
|
+
To execute the code generation script run:
|
100
|
+
|
101
|
+
```
|
102
|
+
bin/generate_ruby_classes
|
103
|
+
```
|
104
|
+
|
105
|
+
### Custom mappings
|
106
|
+
|
107
|
+
The *mapped callbacks* can be configured in the section *mapped_callbacks* of `lib/ib_ruby_proxy/config.yml`.
|
108
|
+
|
109
|
+
Each entry includes the name of the API method and a list of the callback methods related to that API call. The optional property `discriminate_by_argument_nth` is used for associating callbacks and methods based on the value of a given argument. This will be the *request identifier* in most cases.
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
req_historical_ticks:
|
113
|
+
callbacks:
|
114
|
+
- historical_ticks
|
115
|
+
- historical_ticks_bid_ask
|
116
|
+
- historical_ticks_last
|
117
|
+
discriminate_by_argument_nth: 0
|
118
|
+
```
|
119
|
+
|
120
|
+
## Difference with ib-ruby
|
121
|
+
|
122
|
+
[ib-ruby](https://github.com/ib-ruby/ib-ruby) is a mature Ruby alternative for using Interactive Brokers that uses a different approach: it interacts with IB software by using lower level messages interchanges via sockets. It also offers a higher-level abstraction of the IB API. I prefer the approach of `ib_ruby_proxy` (I wouldn't have created it otherwise), but `ib-ruby` has been around for a long time, it is well maintained and eliminates the dependency of JRuby. You should definitely give it a try if you are thinking in invoking IB from Ruby.
|
123
|
+
|
124
|
+
## Contributing
|
125
|
+
|
126
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/jorgemanrubia/ib_ruby_proxy.
|
127
|
+
|
128
|
+
## License
|
129
|
+
|
130
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|