ib-api 10.33.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 (161) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +52 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +7 -0
  5. data/CLAUDE.md +131 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +17 -0
  8. data/Gemfile.lock +120 -0
  9. data/Guardfile +24 -0
  10. data/LICENSE +674 -0
  11. data/LLM_GUIDE.md +388 -0
  12. data/README.md +114 -0
  13. data/Rakefile +11 -0
  14. data/VERSION +1 -0
  15. data/api.gemspec +50 -0
  16. data/bin/console +96 -0
  17. data/bin/console.yml +3 -0
  18. data/bin/setup +8 -0
  19. data/bin/simple +91 -0
  20. data/changelog.md +32 -0
  21. data/conditions/ib/execution_condition.rb +31 -0
  22. data/conditions/ib/margin_condition.rb +28 -0
  23. data/conditions/ib/order_condition.rb +29 -0
  24. data/conditions/ib/percent_change_condition.rb +34 -0
  25. data/conditions/ib/price_condition.rb +44 -0
  26. data/conditions/ib/time_condition.rb +42 -0
  27. data/conditions/ib/volume_condition.rb +36 -0
  28. data/lib/class_extensions.rb +167 -0
  29. data/lib/ib/base.rb +109 -0
  30. data/lib/ib/base_properties.rb +178 -0
  31. data/lib/ib/connection.rb +573 -0
  32. data/lib/ib/constants.rb +402 -0
  33. data/lib/ib/contract.rb +30 -0
  34. data/lib/ib/errors.rb +52 -0
  35. data/lib/ib/messages/abstract_message.rb +68 -0
  36. data/lib/ib/messages/incoming/abstract_message.rb +116 -0
  37. data/lib/ib/messages/incoming/abstract_tick.rb +25 -0
  38. data/lib/ib/messages/incoming/account_message.rb +26 -0
  39. data/lib/ib/messages/incoming/alert.rb +34 -0
  40. data/lib/ib/messages/incoming/contract_data.rb +105 -0
  41. data/lib/ib/messages/incoming/contract_message.rb +13 -0
  42. data/lib/ib/messages/incoming/delta_neutral_validation.rb +23 -0
  43. data/lib/ib/messages/incoming/execution_data.rb +50 -0
  44. data/lib/ib/messages/incoming/histogram_data.rb +30 -0
  45. data/lib/ib/messages/incoming/historical_data.rb +65 -0
  46. data/lib/ib/messages/incoming/historical_data_update.rb +50 -0
  47. data/lib/ib/messages/incoming/managed_accounts.rb +21 -0
  48. data/lib/ib/messages/incoming/market_depth.rb +34 -0
  49. data/lib/ib/messages/incoming/market_depth_l2.rb +15 -0
  50. data/lib/ib/messages/incoming/next_valid_id.rb +19 -0
  51. data/lib/ib/messages/incoming/open_order.rb +290 -0
  52. data/lib/ib/messages/incoming/order_status.rb +85 -0
  53. data/lib/ib/messages/incoming/portfolio_value.rb +47 -0
  54. data/lib/ib/messages/incoming/position_data.rb +21 -0
  55. data/lib/ib/messages/incoming/positions_multi.rb +15 -0
  56. data/lib/ib/messages/incoming/real_time_bar.rb +32 -0
  57. data/lib/ib/messages/incoming/receive_fa.rb +30 -0
  58. data/lib/ib/messages/incoming/scanner_data.rb +54 -0
  59. data/lib/ib/messages/incoming/tick_by_tick.rb +77 -0
  60. data/lib/ib/messages/incoming/tick_efp.rb +18 -0
  61. data/lib/ib/messages/incoming/tick_generic.rb +12 -0
  62. data/lib/ib/messages/incoming/tick_option.rb +60 -0
  63. data/lib/ib/messages/incoming/tick_price.rb +60 -0
  64. data/lib/ib/messages/incoming/tick_size.rb +55 -0
  65. data/lib/ib/messages/incoming/tick_string.rb +13 -0
  66. data/lib/ib/messages/incoming.rb +292 -0
  67. data/lib/ib/messages/outgoing/abstract_message.rb +84 -0
  68. data/lib/ib/messages/outgoing/bar_request_message.rb +247 -0
  69. data/lib/ib/messages/outgoing/new-place-order.rb +193 -0
  70. data/lib/ib/messages/outgoing/old-place-order.rb +147 -0
  71. data/lib/ib/messages/outgoing/place_order.rb +149 -0
  72. data/lib/ib/messages/outgoing/request_account_summary.rb +79 -0
  73. data/lib/ib/messages/outgoing/request_historical_data.rb +182 -0
  74. data/lib/ib/messages/outgoing/request_market_data.rb +102 -0
  75. data/lib/ib/messages/outgoing/request_market_depth.rb +57 -0
  76. data/lib/ib/messages/outgoing/request_real_time_bars.rb +48 -0
  77. data/lib/ib/messages/outgoing/request_scanner_subscription.rb +73 -0
  78. data/lib/ib/messages/outgoing/request_tick_by_tick_data.rb +21 -0
  79. data/lib/ib/messages/outgoing.rb +410 -0
  80. data/lib/ib/messages.rb +139 -0
  81. data/lib/ib/order_condition.rb +26 -0
  82. data/lib/ib/plugins.rb +27 -0
  83. data/lib/ib/prepare_data.rb +61 -0
  84. data/lib/ib/raw_message_parser.rb +99 -0
  85. data/lib/ib/socket.rb +83 -0
  86. data/lib/ib/support.rb +236 -0
  87. data/lib/ib/version.rb +6 -0
  88. data/lib/ib-api.rb +44 -0
  89. data/lib/server_versions.rb +145 -0
  90. data/lib/support/array_function.rb +28 -0
  91. data/lib/support/logging.rb +45 -0
  92. data/models/ib/account.rb +72 -0
  93. data/models/ib/account_value.rb +33 -0
  94. data/models/ib/bag.rb +55 -0
  95. data/models/ib/bar.rb +31 -0
  96. data/models/ib/combo_leg.rb +127 -0
  97. data/models/ib/contract.rb +411 -0
  98. data/models/ib/contract_detail.rb +118 -0
  99. data/models/ib/execution.rb +67 -0
  100. data/models/ib/forex.rb +12 -0
  101. data/models/ib/future.rb +64 -0
  102. data/models/ib/index.rb +14 -0
  103. data/models/ib/option.rb +149 -0
  104. data/models/ib/option_detail.rb +84 -0
  105. data/models/ib/order.rb +720 -0
  106. data/models/ib/order_state.rb +155 -0
  107. data/models/ib/portfolio_value.rb +86 -0
  108. data/models/ib/spread.rb +176 -0
  109. data/models/ib/stock.rb +25 -0
  110. data/models/ib/underlying.rb +32 -0
  111. data/plugins/ib/advanced-account.rb +442 -0
  112. data/plugins/ib/alerts/base-alert.rb +125 -0
  113. data/plugins/ib/alerts/gateway-alerts.rb +15 -0
  114. data/plugins/ib/alerts/order-alerts.rb +73 -0
  115. data/plugins/ib/auto-adjust.rb +0 -0
  116. data/plugins/ib/connection-tools.rb +122 -0
  117. data/plugins/ib/eod.rb +326 -0
  118. data/plugins/ib/greeks.rb +102 -0
  119. data/plugins/ib/managed-accounts.rb +274 -0
  120. data/plugins/ib/market-price.rb +150 -0
  121. data/plugins/ib/option-chain.rb +167 -0
  122. data/plugins/ib/order-flow.rb +157 -0
  123. data/plugins/ib/order-prototypes/abstract.rb +67 -0
  124. data/plugins/ib/order-prototypes/adaptive.rb +40 -0
  125. data/plugins/ib/order-prototypes/all-in-one.rb +46 -0
  126. data/plugins/ib/order-prototypes/combo.rb +46 -0
  127. data/plugins/ib/order-prototypes/forex.rb +40 -0
  128. data/plugins/ib/order-prototypes/limit.rb +193 -0
  129. data/plugins/ib/order-prototypes/market.rb +116 -0
  130. data/plugins/ib/order-prototypes/pegged.rb +169 -0
  131. data/plugins/ib/order-prototypes/premarket.rb +31 -0
  132. data/plugins/ib/order-prototypes/stop.rb +202 -0
  133. data/plugins/ib/order-prototypes/volatility.rb +39 -0
  134. data/plugins/ib/order-prototypes.rb +118 -0
  135. data/plugins/ib/probability-of-expiring.rb +109 -0
  136. data/plugins/ib/process-orders.rb +155 -0
  137. data/plugins/ib/roll.rb +86 -0
  138. data/plugins/ib/spread-prototypes/butterfly.rb +77 -0
  139. data/plugins/ib/spread-prototypes/calendar.rb +97 -0
  140. data/plugins/ib/spread-prototypes/stock-spread.rb +56 -0
  141. data/plugins/ib/spread-prototypes/straddle.rb +70 -0
  142. data/plugins/ib/spread-prototypes/strangle.rb +93 -0
  143. data/plugins/ib/spread-prototypes/vertical.rb +83 -0
  144. data/plugins/ib/spread-prototypes.rb +70 -0
  145. data/plugins/ib/symbols/abstract.rb +136 -0
  146. data/plugins/ib/symbols/bonds.rb +28 -0
  147. data/plugins/ib/symbols/cfd.rb +19 -0
  148. data/plugins/ib/symbols/combo.rb +46 -0
  149. data/plugins/ib/symbols/commodity.rb +17 -0
  150. data/plugins/ib/symbols/forex.rb +41 -0
  151. data/plugins/ib/symbols/futures.rb +127 -0
  152. data/plugins/ib/symbols/index.rb +43 -0
  153. data/plugins/ib/symbols/options.rb +99 -0
  154. data/plugins/ib/symbols/stocks.rb +44 -0
  155. data/plugins/ib/symbols/version.rb +5 -0
  156. data/plugins/ib/symbols.rb +118 -0
  157. data/plugins/ib/verify.rb +226 -0
  158. data/symbols/w20.yml +210 -0
  159. data/t.txt +20 -0
  160. data/update.md +71 -0
  161. metadata +327 -0
data/LLM_GUIDE.md ADDED
@@ -0,0 +1,388 @@
1
+ # LLM Guide for ib-api
2
+
3
+ **Purpose**: This guide is optimized for LLMs (Large Language Models) to understand and work with the ib-api codebase efficiently.
4
+
5
+ ---
6
+
7
+ ## QUICK MENTAL MODEL
8
+
9
+ **What is this?**: A Ruby gem that provides a programmatic interface to Interactive Brokers' trading platform (TWS/Gateway).
10
+
11
+ **Core pattern**: You create a `Connection` object → it opens a TCP socket to IB → you send/recv messages → events trigger callbacks → data flows through plugins.
12
+
13
+ **Key insight**: Everything is message-driven. Connection manages a state machine, plugins extend functionality, and models represent trading objects.
14
+
15
+ ---
16
+
17
+ ## FILE MAP (WHERE THINGS LIVE)
18
+
19
+ ```
20
+ lib/ib/
21
+ ├── connection.rb # CORE: Main Connection class, workflow state machine
22
+ ├── plugins.rb # Plugin activation system
23
+ ├── messages/
24
+ │ ├── outgoing/ # Messages sent TO IB (requests)
25
+ │ └── incoming/ # Messages received FROM IB (responses)
26
+ └── constants.rb # IB API enums/constants
27
+
28
+ models/ib/ # Zeiteerk-loaded models
29
+ ├── contract.rb # Base class for all instruments
30
+ ├── stock.rb, option.rb, future.rb, etc. # Specific contract types
31
+ ├── order.rb # Order objects
32
+ └── bar.rb # OHLCV market data
33
+
34
+ plugins/ib/ # Plugin implementations (extend Connection)
35
+ ├── verify.rb # Contract verification
36
+ ├── market-price.rb # Current price fetching
37
+ ├── managed-accounts.rb # Account/portfolio management
38
+ └── ...
39
+
40
+ spec/
41
+ ├── spec_helper.rb # Test config, loads spec.yml
42
+ ├── spec.yml # IB connection settings (REQUIRED for tests)
43
+ └── howto.md # Guide for implementing new messages
44
+ ```
45
+
46
+ ---
47
+
48
+ ## THE CONNECTION OBJECT (CENTRAL HUB)
49
+
50
+ ```ruby
51
+ require 'ib-api'
52
+
53
+ # Create connection (does NOT connect yet)
54
+ ib = IB::Connection.new(host: '127.0.0.1', port: 7497)
55
+
56
+ # Connect (triggers workflow state transition)
57
+ ib.try_connection! # or use the event: ib.try_connection
58
+
59
+ # The connection is globally accessible
60
+ IB::Connection.current == ib # => true
61
+ ```
62
+
63
+ **Connection attributes**:
64
+ - `socket`: TCP connection to IB
65
+ - `next_local_id`: Next available order ID
66
+ - `received`: Hash of received messages (by type)
67
+ - `plugins`: Array of activated plugin names
68
+ - `workflow_state`: Current state (virgin, ready, gateway_mode, etc.)
69
+
70
+ ---
71
+
72
+ ## WORKFLOW STATE MACHINE
73
+
74
+ **States (linear progression typical)**:
75
+
76
+ ```
77
+ virgin (initial)
78
+
79
+ ├─→ try_connection! → ready
80
+
81
+ ├─→ activate_managed_accounts! → gateway_mode
82
+
83
+ └─→ collect_data! → lean_mode
84
+
85
+ ready
86
+
87
+ ├─→ initialize_managed_accounts! → account_based_operations
88
+
89
+ └─→ disconnect! → disconnected
90
+
91
+ account_based_operations
92
+
93
+ └─→ initialize_order_handling! → account_based_orderflow
94
+ ```
95
+
96
+ **State meanings**:
97
+ - `virgin`: No connection
98
+ - `ready`: Connected, basic functionality
99
+ - `gateway_mode`: Multi-account gateway access
100
+ - `lean_mode`: Minimal data collection
101
+ - `account_based_operations`: Account/portfolio data loaded
102
+ - `account_based_orderflow`: Order processing active
103
+
104
+ ---
105
+
106
+ ## MESSAGE SYSTEM (THE PROTOCOL)
107
+
108
+ **Sending messages**:
109
+ ```ruby
110
+ # Method 1: Send symbol
111
+ ib.send_message :PlaceOrder, order: my_order, contract: my_contract
112
+
113
+ # Method 2: Send class
114
+ ib.send_message IB::Messages::Outgoing::PlaceOrder, order: my_order, contract: my_contract
115
+
116
+ # Method 3: Use instance
117
+ msg = IB::Messages::Outgoing::PlaceOrder.new(order: my_order, contract: my_contract)
118
+ ib.send_message msg
119
+ ```
120
+
121
+ **Receiving messages** (subscribe to events):
122
+ ```ruby
123
+ # Subscribe to a message type
124
+ subscription_id = ib.subscribe(:OrderStatus) do |msg|
125
+ puts "Order #{msg.order_id}: #{msg.status}"
126
+ end
127
+
128
+ # Wait for a specific message type
129
+ ib.wait_for :OrderStatus, timeout: 5
130
+
131
+ # Access received messages
132
+ ib.received[:OrderStatus].each { |msg| ... }
133
+ ```
134
+
135
+ **Message structure**:
136
+ - Outgoing messages: defined in `lib/ib/messages/outgoing/`
137
+ - Incoming messages: defined in `lib/ib/messages/incoming/`
138
+ - Messages use `def_message` macro to generate classes
139
+ - Each message has an ID and version for protocol compatibility
140
+
141
+ ---
142
+
143
+ ## PLUGIN SYSTEM (EXTENSIBILITY)
144
+
145
+ **What plugins do**: Extend `IB::Connection` with additional methods by reopening the module.
146
+
147
+ **How to use**:
148
+ ```ruby
149
+ # Activate plugin(s)
150
+ ib.activate_plugin :verify, :market_price, :connection_tools
151
+
152
+ # Now methods from those plugins are available
153
+ contract = IB::Stock.new(symbol: 'GE')
154
+ verified = contract.verify # provided by :verify plugin
155
+ price = contract.market_price # provided by :market_price plugin
156
+ ```
157
+
158
+ **How plugins are written**:
159
+ ```ruby
160
+ # plugins/ib/my_plugin.rb
161
+ module IB
162
+ module Connection
163
+ def my_custom_method
164
+ # Can access @socket, send_message, etc.
165
+ send_message :SomeRequest
166
+ end
167
+ end
168
+ end
169
+ ```
170
+
171
+ **Common plugins**:
172
+ - `connection-tools`: Ensures active connection
173
+ - `verify`: Fetch contract details from TWS
174
+ - `managed-accounts`: Fetch account/portfolio data
175
+ - `market-price`: Get current market price
176
+ - `advanced-account`: Account-based trading operations
177
+ - `greeks`: Option risk calculations
178
+ - `option-chain`: Build option chains
179
+
180
+ ---
181
+
182
+ ## MODELS (DATA STRUCTURES)
183
+
184
+ **Contracts** (base: `IB::Contract`):
185
+ ```ruby
186
+ stock = IB::Stock.new(symbol: 'GE', exchange: 'SMART', currency: 'USD')
187
+ option = IB::Option.new(symbol: 'GE', strike: 50, right: 'CALL', expiry: '20240120')
188
+ future = IB::Future.new(symbol: 'ES', expiry: '202403')
189
+ ```
190
+
191
+ **Orders**:
192
+ ```ruby
193
+ order = IB::Order.new(
194
+ total_quantity: 100,
195
+ action: :buy,
196
+ order_type: 'LMT',
197
+ limit_price: 35.0
198
+ )
199
+
200
+ # Place order
201
+ local_id = ib.place_order(order, stock)
202
+ ```
203
+
204
+ **Order methods on Connection**:
205
+ - `place_order(order, contract)`: Place new order
206
+ - `modify_order(order, contract)`: Modify existing order
207
+ - `cancel_order(*local_ids)`: Cancel order(s)
208
+
209
+ ---
210
+
211
+ ## TESTING PATTERNS
212
+
213
+ **Test setup**:
214
+ ```ruby
215
+ # spec/spec_helper.rb loads:
216
+ require 'spec_helper'
217
+
218
+ # Constants available:
219
+ OPTS[:connection] # Hash from spec.yml
220
+ ACCOUNT # Account ID from spec.yml
221
+ SAMPLE # IB::Stock from spec.yml
222
+
223
+ # Example test:
224
+ describe IB::Stock do
225
+ subject { IB::Stock.new(symbol: 'GE') }
226
+
227
+ it "verifies contract" do
228
+ verified = subject.verify
229
+ expect(verified).to be_truthy
230
+ end
231
+ end
232
+ ```
233
+
234
+ **Running tests**:
235
+ ```bash
236
+ # All tests
237
+ bundle exec rspec
238
+
239
+ # Single file
240
+ bundle exec rspec spec/ib/contract_spec.rb
241
+
242
+ # Focused (only tests with :focus tag or fit/fdescribe)
243
+ bundle exec rspec --tag focus
244
+ ```
245
+
246
+ **IMPORTANT**: Tests require valid IB credentials in `spec/spec.yml`:
247
+ ```yaml
248
+ :connection:
249
+ :port: 4002
250
+ :host: 127.0.0.1
251
+ :account: DU123456 # Your paper account ID
252
+ ```
253
+
254
+ ---
255
+
256
+ ## CONSOLE USAGE
257
+
258
+ ```bash
259
+ # Start console (connects to Gateway by default)
260
+ ./console g # or ./console t for TWS
261
+
262
+ # In console:
263
+ C # => IB::Connection.current instance
264
+ C.received # => Hash of received messages
265
+ C.plugins # => Array of active plugins
266
+
267
+ # Example session:
268
+ > contract = IB::Stock.new(symbol: 'GE')
269
+ > contract.verify
270
+ > contract.market_price
271
+ ```
272
+
273
+ ---
274
+
275
+ ## CODE PATTERNS TO RECOGNIZE
276
+
277
+ **1. Event subscription pattern**:
278
+ ```ruby
279
+ ib.subscribe(:MessageName) { |msg| ... }
280
+ ```
281
+
282
+ **2. Wait for response pattern**:
283
+ ```ruby
284
+ ib.send_message :Request
285
+ ib.wait_for :Response
286
+ ```
287
+
288
+ **3. Plugin activation pattern**:
289
+ ```ruby
290
+ ib.activate_plugin :plugin_name
291
+ ```
292
+
293
+ **4. Connection state transitions**:
294
+ ```ruby
295
+ ib.try_connection! # Connect
296
+ ib.initialize_managed_accounts! # Load account data
297
+ ```
298
+
299
+ **5. Order placement**:
300
+ ```ruby
301
+ local_id = ib.place_order(order, contract)
302
+ ib.wait_for :OpenOrder
303
+ ```
304
+
305
+ ---
306
+
307
+ ## COMMON OPERATIONS
308
+
309
+ **Get contract details**:
310
+ ```ruby
311
+ ib.activate_plugin :verify
312
+ contract = IB::Stock.new(symbol: 'GE')
313
+ details = contract.verify # Returns array of Contract objects
314
+ ```
315
+
316
+ **Get current price**:
317
+ ```ruby
318
+ ib.activate_plugin :market_price
319
+ contract = IB::Stock.new(symbol: 'GE')
320
+ price = contract.market_price
321
+ ```
322
+
323
+ **Place order**:
324
+ ```ruby
325
+ contract = IB::Stock.new(symbol: 'GE')
326
+ order = IB::Order.new(limit_price: 35.0, order_type: 'LMT', total_quantity: 100, action: :buy)
327
+ ib.place_order(order, contract)
328
+ ```
329
+
330
+ **Get account/portfolio data**:
331
+ ```ruby
332
+ ib.activate_plugin :managed_accounts
333
+ ib.get_account_data
334
+ ib.portfolio_values # Hash of portfolio positions
335
+ ```
336
+
337
+ ---
338
+
339
+ ## DEBUGGING NEW MESSAGES
340
+
341
+ When implementing a new message type:
342
+
343
+ 1. Uncomment line 37 in `lib/ib/messages/incoming/abstract_message.rb` to see raw TWS output
344
+ 2. Use the console (`./console`) to test
345
+ 3. Send the request and inspect `C.received[:MessageName]`
346
+ 4. Check the buffer attribute for unparsed data
347
+
348
+ ---
349
+
350
+ ## KEY DEPENDENCIES
351
+
352
+ - **Zeitwerk**: Modern Ruby autoloading (models in `models/ib/` are autoloaded)
353
+ - **ActiveModel**: Base for data models
354
+ - **Workflow**: State machine for Connection
355
+ - **RSpec**: Testing framework
356
+ - **Ox**: XML parsing for some messages
357
+
358
+ ---
359
+
360
+ ## API VERSIONS
361
+
362
+ - Client version: 66 (API 9.71+)
363
+ - Server version: 165+ (TWS 10.19+)
364
+ - Protocol supports multiple IB API versions via message versioning
365
+
366
+ ---
367
+
368
+ ## MENTAL CHECKLIST FOR TASKS
369
+
370
+ **Before modifying**:
371
+ 1. Read the relevant model or message definition first
372
+ 2. Check if a plugin already provides the functionality
373
+ 3. Understand the current workflow state
374
+
375
+ **When adding new messages**:
376
+ 1. Define in `lib/ib/messages/outgoing/` (request) or `incoming/` (response)
377
+ 2. Use `def_message` macro with proper ID and version
378
+ 3. Test in console first, then write spec
379
+
380
+ **When adding plugins**:
381
+ 1. Create file in `plugins/ib/`
382
+ 2. Reopen `IB::Connection` module
383
+ 3. Activate via `ib.activate_plugin :plugin_name`
384
+
385
+ **When writing tests**:
386
+ 1. Ensure `spec/spec.yml` has valid credentials
387
+ 2. Use `SAMPLE` constant for test data
388
+ 3. Use `ib.wait_for` to wait for async responses
data/README.md ADDED
@@ -0,0 +1,114 @@
1
+ # ib-api
2
+ Ruby interface to Interactive Brokers' TWS API
3
+
4
+ Reimplementation of ib-ruby
5
+
6
+ ---
7
+ __STATUS: Gem-Release is still pending
8
+
9
+ ---
10
+
11
+ * Zeitwerk integration.
12
+ * Plugin's to ease automations
13
+ ---
14
+
15
+ __Documentation: [https://ib-ruby.github.io/ib-doc/](https://ib-ruby.github.io/ib-doc/)__ (_work in progress_)
16
+
17
+ ----
18
+ `ib-api` offers a modular access to the TWS-API-Interface of Interactive Brokers.
19
+
20
+ ----
21
+
22
+ Install in the usual way
23
+
24
+ ```
25
+ $ gem install ib-api
26
+ ```
27
+
28
+ In its plain vanilla usage, it just exchanges messages with the TWS. Any response is stored in the `received-array`.
29
+
30
+ It needs just a few lines of code to place an order
31
+
32
+ ```ruby
33
+ require 'ib-api'
34
+ # connect with default parameters
35
+ ib = IB::Connection.new
36
+
37
+ # define a contract to deal with
38
+ the_stock = IB::Stock.new symbol: 'TAP'
39
+
40
+ # order 100 shares for 35 $
41
+ limit_order = IB::Order.new limit_price: 35, order_type: 'LMT', total_quantity: 100, action: :buy
42
+ ib.send_message :PlaceOrder,
43
+ :order => limit_order,
44
+ :contract => the_stock,
45
+ :local_id => ib.next_local_id
46
+
47
+ # wait until the orderstate message returned
48
+ ib.wait_for :OrderStatus
49
+
50
+ # print the Orderstatus
51
+ puts ib.recieved[:OrderStatus].to_human
52
+
53
+ # => ["<OrderState: Submitted #17/1528367295 from 2000 filled 0.0/100.0 at 0.0/0.0 why_held >"]
54
+
55
+ ```
56
+
57
+ ## Plugins
58
+
59
+ **IB-API** ships with simple plugins to facilitate automations
60
+
61
+ ```ruby
62
+ require 'ib-api'
63
+ # connect with default parameters
64
+ ib = IB::Connection.new do | c |
65
+ c.activate_plugin "verify"
66
+ end
67
+
68
+ g = IB::Stock.new symbol: 'GE'
69
+ puts g.verify.first.attributes
70
+ {:symbol=>"GE", :sec_type=>"STK", :last_trading_day=>"", :strike=>0.0, :right=>"", :exchange=>"SMART", :currency=>"USD", :local_symbol=>"GE", :trading_class=>"GE", :con_id=>498843743, :multiplier=>0, :primary_exchange=>"NYSE", }
71
+ ```
72
+
73
+ Currently implemented plugins
74
+
75
+ * connection-tools: ensure that a connection is established and active
76
+ * verify: get contract details from the tws
77
+ * symbols: use predefined symbols
78
+ * managed-accounts: fetch and organize account- and portfoliovalues
79
+ * advanced-account: perform account-based previewing, opening, modifying and closing of Positions
80
+ * process-orders: account-based bookkeeping of orders
81
+ * auto-adjust: properly adjust the orderprice to the next valid min-tick of the contract
82
+ * market-price: fetch the current market-price of a contract
83
+ * eod: retrieve EOD-Data for the given contract
84
+ * greeks: read current option greeks
85
+ * roll: easy rolling of futures and options
86
+ * option-chain: build option-chains for given strikes and expiries
87
+ * spread-prototypes: create limit, stop, market, etc. orders through prototypes
88
+ * probability-of-expiring: calculate the probability of expiring for the option-contract
89
+
90
+
91
+ ## Minimal TWS-Version
92
+
93
+ `ib-api` is tested via the _stable IB-Gateway_ (Version 10.33) and should work with any current tws-installation.
94
+
95
+ ## Tests
96
+
97
+ are invoked by
98
+
99
+ ```
100
+ bundle exec guard
101
+ # or
102
+ bundle exec rake spec
103
+ ```
104
+ Integration tests on order-placements are not included. To run the test suite its thus safe to use a _real Account_.
105
+ You have to edit `spec/spec.yml` and replace the `:account`-Setting with your own `AccountID`, even if you connect to a single account.
106
+
107
+
108
+ ## Contributing
109
+
110
+ Bug reports and pull requests are welcome. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
111
+
112
+ ## Code of Conduct
113
+
114
+ Everyone interacting in the Core project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/ib-api/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require "rake"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec) do |t|
7
+ t.pattern = Dir.glob("spec/**/*_spec.rb")
8
+ t.rspec_opts = "--format documentation"
9
+ end
10
+
11
+ task default: :spec
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 10.33.1
data/api.gemspec ADDED
@@ -0,0 +1,50 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "ib/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ib-api"
8
+ spec.version = IB::VERSION
9
+ spec.authors = ["Hartmut Bischoff"]
10
+ spec.email = ["topofocus@gmail.com"]
11
+ spec.license = "MIT"
12
+
13
+ spec.summary = %q{Ruby Implementation of the Interactive Brokers TWS API}
14
+ spec.description = %q{Ruby Implementation of the Interactive Brokers TWS API}
15
+ spec.homepage = "https://github.com/ib-ruby"
16
+ spec.required_ruby_version = ">= 3.0"
17
+
18
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
19
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
20
+ if spec.respond_to?(:metadata)
21
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
22
+
23
+ spec.metadata["homepage_uri"] = spec.homepage
24
+ spec.metadata["source_code_uri"] = "https://github.com/ib-ruby/ib-api"
25
+ # spec.metadata["changelog_uri"] = "https://github.com/ib-ruby/ib-api/CHANGELOG.md"
26
+ else
27
+ raise "RubyGems 2.0 or newer is required to protect against " \
28
+ "public gem pushes."
29
+ end
30
+
31
+ # Specify which files should be added to the gem when it is released.
32
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
33
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
34
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
35
+ end
36
+ spec.bindir = "exe"
37
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
38
+ spec.require_paths = ["lib"]
39
+
40
+ spec.add_development_dependency "bundler", "~> 2.0"
41
+ spec.add_development_dependency "rake", "~> 13.0"
42
+ spec.add_development_dependency "rspec", "~> 3.0"
43
+ spec.add_dependency 'activesupport', '~> 6.0'
44
+ spec.add_dependency 'activemodel', '~> 7.0'
45
+ spec.add_dependency 'ox', '~> 2.14'
46
+ spec.add_dependency 'terminal-table', '~> 3.0'
47
+ spec.add_dependency 'zeitwerk', '~> 2.6'
48
+ spec.add_dependency 'workflow', '~> 3.1'
49
+
50
+ end
data/bin/console ADDED
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env ruby
2
+ ### loads the active-orient environment
3
+ ### and starts an interactive shell
4
+ ###
5
+ ### Parameter: t)ws | g)ateway (or number of port ) Default: Gateway ,
6
+ ### client_id , Default 2000
7
+ ###
8
+ ### Define Parameter in file console.yml
9
+ ###
10
+ require 'bundler/setup'
11
+ require 'yaml'
12
+
13
+ require 'ib-api'
14
+
15
+ class Array
16
+ # enables calling members of an array. which are hashes by it name
17
+ # i.e
18
+ #
19
+ # 2.5.0 :006 > C.received[:OpenOrder].local_id
20
+ # => [16, 17, 21, 20, 19, 8, 7]
21
+ # 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
+ #
24
+ # its included only in the console, for inspection purposes
25
+
26
+ def method_missing(method, *key)
27
+ unless method == :to_hash || method == :to_str #|| method == :to_int
28
+ return self.map{|x| x.public_send(method, *key)}
29
+ end
30
+
31
+ end
32
+ end # Array
33
+
34
+ class Object
35
+ def inspect
36
+ respond_to?(:to_human) ? to_human : super
37
+ end
38
+ end
39
+
40
+ # read items from console.yml
41
+ read_yml = -> (key) do
42
+ YAML::load_file( File.expand_path('../console.yml',__FILE__))[key]
43
+ end
44
+
45
+ puts
46
+ puts ">> IB-API Interactive Console <<"
47
+ puts '-'* 45
48
+ puts
49
+ puts "Namespace is IB ! "
50
+ puts
51
+ puts '-'* 45
52
+ include IB
53
+ require 'irb'
54
+ client_id = ARGV[1] || read_yml[:client_id]
55
+ specified_host = ARGV[0] || 'Gateway'
56
+ host = case specified_host
57
+ when /^[gG]/
58
+ read_yml[:gateway]
59
+ when /^[Tt]/
60
+ read_yml[:tws]
61
+ else
62
+ raise "Specify target from console.yml: `g|t` instead of #{specified_host}"
63
+ end
64
+ ARGV.clear
65
+
66
+ C = Connection.new client_id: client_id, host: host
67
+ C.logger.level = Logger::WARN
68
+
69
+ C.subscribe(:Alert){ |m| puts "A: "+ m.message }
70
+ C.subscribe(:AccountUpdateTime){ }
71
+
72
+ C.received = true
73
+ C.activate_plugin :connection_tools, :symbols, :market_price,
74
+ "order-prototypes", "spread-prototypes",
75
+ "advanced_account", 'process_orders'
76
+ C.logger.level = Logger::INFO
77
+ puts C.workflow_state
78
+ C.get_account_data
79
+ C.request_open_orders
80
+ C.logger.level = Logger::ERROR
81
+ puts "Connection established on #{host}"
82
+
83
+ unless C.received[:OpenOrder].blank?
84
+ puts "---------------------------------------- OpenOrders -------------------------------------------"
85
+ puts C.clients.map{ |c| c.orders.map &:to_human }.flatten.join("\n")
86
+ end
87
+ puts ""
88
+ puts Terminal::Table.new title: 'Active Plugins',
89
+ rows: C.plugins.delete_if{ |x| x =~ /\// }.sort.each_slice(4),
90
+ style: { border: :unicode }
91
+ puts
92
+ puts "----> C points to the connection-instance"
93
+ puts
94
+ puts '-'* 45
95
+
96
+ IRB.start(__FILE__)
data/bin/console.yml ADDED
@@ -0,0 +1,3 @@
1
+ :gateway: "localhost:4002"
2
+ :tws: "tws:7496"
3
+ :client_id: 2000
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here