async-rithmic 1.0.0__tar.gz

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 (94) hide show
  1. async_rithmic-1.0.0/LICENSE +21 -0
  2. async_rithmic-1.0.0/MANIFEST.in +5 -0
  3. async_rithmic-1.0.0/PKG-INFO +308 -0
  4. async_rithmic-1.0.0/README.md +280 -0
  5. async_rithmic-1.0.0/pyproject.toml +3 -0
  6. async_rithmic-1.0.0/setup.cfg +8 -0
  7. async_rithmic-1.0.0/setup.py +50 -0
  8. async_rithmic-1.0.0/src/async_rithmic.egg-info/PKG-INFO +308 -0
  9. async_rithmic-1.0.0/src/async_rithmic.egg-info/SOURCES.txt +93 -0
  10. async_rithmic-1.0.0/src/async_rithmic.egg-info/dependency_links.txt +1 -0
  11. async_rithmic-1.0.0/src/async_rithmic.egg-info/requires.txt +9 -0
  12. async_rithmic-1.0.0/src/async_rithmic.egg-info/top_level.txt +1 -0
  13. async_rithmic-1.0.0/src/rithmic/__init__.py +5 -0
  14. async_rithmic-1.0.0/src/rithmic/certificates/rithmic_ssl_cert_auth_params +34 -0
  15. async_rithmic-1.0.0/src/rithmic/client.py +104 -0
  16. async_rithmic-1.0.0/src/rithmic/enums.py +32 -0
  17. async_rithmic-1.0.0/src/rithmic/event.py +21 -0
  18. async_rithmic-1.0.0/src/rithmic/logger.py +20 -0
  19. async_rithmic-1.0.0/src/rithmic/plants/__init__.py +4 -0
  20. async_rithmic-1.0.0/src/rithmic/plants/base.py +341 -0
  21. async_rithmic-1.0.0/src/rithmic/plants/history.py +205 -0
  22. async_rithmic-1.0.0/src/rithmic/plants/order.py +261 -0
  23. async_rithmic-1.0.0/src/rithmic/plants/pnl.py +77 -0
  24. async_rithmic-1.0.0/src/rithmic/plants/ticker.py +87 -0
  25. async_rithmic-1.0.0/src/rithmic/protocol_buffers/__init__.py +13 -0
  26. async_rithmic-1.0.0/src/rithmic/protocol_buffers/account_pnl_position_update_pb2.py +26 -0
  27. async_rithmic-1.0.0/src/rithmic/protocol_buffers/base_pb2.py +26 -0
  28. async_rithmic-1.0.0/src/rithmic/protocol_buffers/best_bid_offer_pb2.py +28 -0
  29. async_rithmic-1.0.0/src/rithmic/protocol_buffers/exchange_order_notification_pb2.py +38 -0
  30. async_rithmic-1.0.0/src/rithmic/protocol_buffers/instrument_pnl_position_update_pb2.py +26 -0
  31. async_rithmic-1.0.0/src/rithmic/protocol_buffers/last_trade_pb2.py +30 -0
  32. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_account_list_pb2.py +28 -0
  33. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_account_rms_info_pb2.py +28 -0
  34. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_bracket_order_pb2.py +42 -0
  35. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_cancel_order_pb2.py +28 -0
  36. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_front_month_contract_pb2.py +26 -0
  37. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_heartbeat_pb2.py +26 -0
  38. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_login_info_pb2.py +26 -0
  39. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_login_pb2.py +28 -0
  40. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_logout_pb2.py +26 -0
  41. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_market_data_update_pb2.py +30 -0
  42. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_modify_order_pb2.py +34 -0
  43. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_new_order_pb2.py +38 -0
  44. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_pnl_position_snapshot_pb2.py +26 -0
  45. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_pnl_position_updates_pb2.py +28 -0
  46. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_product_rms_info_pb2.py +26 -0
  47. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_reference_data_pb2.py +26 -0
  48. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_rithmic_system_info_pb2.py +26 -0
  49. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_search_symbols_pb2.py +30 -0
  50. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_show_order_history_detail_pb2.py +26 -0
  51. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_show_orders_pb2.py +26 -0
  52. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_subscribe_for_order_updates_pb2.py +26 -0
  53. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_subscribe_to_bracket_updates_pb2.py +26 -0
  54. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_tick_bar_replay_pb2.py +34 -0
  55. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_tick_bar_update_pb2.py +32 -0
  56. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_time_bar_replay_pb2.py +32 -0
  57. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_time_bar_update_pb2.py +30 -0
  58. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_trade_routes_pb2.py +26 -0
  59. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_update_stop_bracket_level_pb2.py +26 -0
  60. async_rithmic-1.0.0/src/rithmic/protocol_buffers/request_update_target_bracket_level_pb2.py +26 -0
  61. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_account_list_pb2.py +26 -0
  62. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_account_rms_info_pb2.py +30 -0
  63. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_bracket_order_pb2.py +26 -0
  64. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_cancel_order_pb2.py +26 -0
  65. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_front_month_contract_pb2.py +26 -0
  66. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_heartbeat_pb2.py +26 -0
  67. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_login_info_pb2.py +28 -0
  68. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_login_pb2.py +26 -0
  69. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_logout_pb2.py +26 -0
  70. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_market_data_update_pb2.py +26 -0
  71. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_modify_order_pb2.py +26 -0
  72. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_new_order_pb2.py +26 -0
  73. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_pnl_position_snapshot_pb2.py +26 -0
  74. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_pnl_position_updates_pb2.py +26 -0
  75. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_product_rms_info_pb2.py +28 -0
  76. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_reference_data_pb2.py +28 -0
  77. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_rithmic_system_info_pb2.py +26 -0
  78. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_search_symbols_pb2.py +26 -0
  79. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_show_order_history_detail_pb2.py +26 -0
  80. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_show_orders_pb2.py +26 -0
  81. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_subscribe_for_order_updates_pb2.py +26 -0
  82. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_tick_bar_replay_pb2.py +30 -0
  83. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_tick_bar_update_pb2.py +26 -0
  84. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_time_bar_replay_pb2.py +28 -0
  85. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_time_bar_update_pb2.py +26 -0
  86. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_trade_routes_pb2.py +26 -0
  87. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_update_stop_bracket_level_pb2.py +26 -0
  88. async_rithmic-1.0.0/src/rithmic/protocol_buffers/response_update_target_bracket_level_pb2.py +26 -0
  89. async_rithmic-1.0.0/src/rithmic/protocol_buffers/rithmic_order_notification_pb2.py +38 -0
  90. async_rithmic-1.0.0/src/rithmic/protocol_buffers/tick_bar_pb2.py +30 -0
  91. async_rithmic-1.0.0/src/rithmic/protocol_buffers/time_bar_pb2.py +28 -0
  92. async_rithmic-1.0.0/src/rithmic/protocol_buffers/trade_route_pb2.py +26 -0
  93. async_rithmic-1.0.0/tests/test_base.py +104 -0
  94. async_rithmic-1.0.0/tests/test_ticker.py +12 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Mickael Burguet
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 all
13
+ 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 THE
21
+ SOFTWARE.
@@ -0,0 +1,5 @@
1
+ include pyproject.toml
2
+ include *.md
3
+ include LICENSE
4
+ include src/rithmic/certificates/rithmic_ssl_cert_auth_params
5
+ recursive-include tests test*.py
@@ -0,0 +1,308 @@
1
+ Metadata-Version: 2.1
2
+ Name: async_rithmic
3
+ Version: 1.0.0
4
+ Summary: Python API Integration with Rithmic Protocol Buffer API
5
+ Home-page: https://github.com/rundef/pyrithmic
6
+ Author: Mickael Burguet
7
+ Project-URL: Documentation, https://github.com/rundef/pyrithmic
8
+ Project-URL: Bug Reports, https://github.com/rundef/pyrithmic/issues
9
+ Project-URL: Source Code, https://github.com/rundef/pyrithmic
10
+ Keywords: python rithmic
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Topic :: Software Development :: Build Tools
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3 :: Only
21
+ Classifier: License :: OSI Approved :: MIT License
22
+ Classifier: Operating System :: OS Independent
23
+ Requires-Python: >=3.8
24
+ Description-Content-Type: text/markdown
25
+ Provides-Extra: dev
26
+ Provides-Extra: test
27
+ License-File: LICENSE
28
+
29
+ # Python Rithmic API
30
+
31
+ A robust, async-based Python API designed to interface seamlessly with the Rithmic Protocol Buffer API. This package is built to provide an efficient and reliable connection to Rithmic's trading infrastructure, catering to advanced trading strategies and real-time data handling.
32
+
33
+ This was originally a fork of [pyrithmic](https://github.com/jacksonwoody/pyrithmic), but the code has been completely rewritten.
34
+
35
+ ## Key Enhancements
36
+
37
+ This repo introduces several key improvements and new features over the original repository, ensuring compatibility with modern Python environments and providing additional functionality:
38
+
39
+ - **Python 3.11+ Compatibility**: Refactored code to ensure smooth operation with the latest Python versions.
40
+ - **System Name Validation**: Implements pre-login validation of system names, as recommended by Rithmic support, with enhanced error handling during the login process.
41
+ - **Account Selection**: Allows users to specify which account to use when calling trading functions, rather than being restricted to the primary account.
42
+ - **STOP Orders**: Exposing STOP orders to users
43
+ - **Best Bid Offer (BBO) Streaming**: Integrates real-time Best Bid Offer tick streaming.
44
+ - **Historical Time Bars + Time Bars Streaming**:
45
+
46
+ The most significant upgrade is the transition to an async architecture, providing superior performance and responsiveness when dealing with real-time trading and market data.
47
+
48
+ ## Installation
49
+
50
+ ```
51
+ pip install git+https://github.com/rundef/pyrithmic.git#egg=pyrithmic
52
+ ```
53
+
54
+ ## Market data
55
+
56
+ ### Streaming Live Tick Data
57
+
58
+ Here's an example to get the front month contract for ES and stream market data:
59
+
60
+ ```python
61
+ import asyncio
62
+ from rithmic import RithmicClient, Gateway, DataType, LastTradePresenceBits
63
+
64
+ async def callback(data: dict):
65
+ if data["presence_bits"] & LastTradePresenceBits.LAST_TRADE:
66
+ print("received", data)
67
+
68
+ async def main():
69
+ client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
70
+ await client.connect()
71
+
72
+ # Request front month contract
73
+ symbol, exchange = "ES", "CME"
74
+ security_code = await client.get_front_month_contract(symbol, exchange)
75
+
76
+ # Stream market data
77
+ print(f"Streaming market data for {security_code}")
78
+ data_type = DataType.LAST_TRADE
79
+ client.on_tick += callback
80
+ await client.subscribe_to_market_data(security_code, exchange, data_type)
81
+
82
+ # Wait 10 seconds, unsubscribe and disconnect
83
+ await asyncio.sleep(10)
84
+ await client.unsubscribe_from_market_data(security_code, exchange, data_type)
85
+ await client.disconnect()
86
+
87
+ asyncio.run(main())
88
+ ```
89
+
90
+ ### Streaming Live Time Bars
91
+
92
+ ```python
93
+ import asyncio
94
+ from rithmic import RithmicClient, Gateway, TimeBarType
95
+
96
+ async def callback(data: dict):
97
+ print("received", data)
98
+
99
+ async def main():
100
+ client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
101
+ await client.connect()
102
+
103
+ # Request front month contract
104
+ symbol, exchange = "ES", "CME"
105
+ security_code = await client.get_front_month_contract(symbol, exchange)
106
+
107
+ # Stream market data
108
+ print(f"Streaming market data for {security_code}")
109
+
110
+ client.on_time_bar += callback
111
+ await client.subscribe_to_time_bar_data(security_code, exchange, TimeBarType.SECOND_BAR, 6)
112
+
113
+ # Wait 10 seconds, unsubscribe and disconnect
114
+ await asyncio.sleep(20)
115
+ await client.unsubscribe_from_time_bar_data(security_code, exchange, TimeBarType.SECOND_BAR, 6)
116
+ await client.disconnect()
117
+
118
+ asyncio.run(main())
119
+ ```
120
+
121
+ ## Order API
122
+
123
+ #### Placing a Market Order:
124
+
125
+ As a market order will be filled immediately, this script will submit the order and receive a fill straight away:
126
+
127
+ ```python
128
+ import asyncio
129
+ from datetime import datetime
130
+ from rithmic import RithmicClient, Gateway, OrderType, ExchangeOrderNotificationType, TransactionType
131
+
132
+ async def callback(notification):
133
+ if notification.notify_type == ExchangeOrderNotificationType.FILL:
134
+ print("order filled", notification)
135
+
136
+ async def main():
137
+ client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
138
+ await client.connect()
139
+
140
+ # Request front month contract
141
+ symbol, exchange = "ES", "CME"
142
+ security_code = await client.get_front_month_contract(symbol, exchange)
143
+
144
+ # Submit order
145
+ client.on_exchange_order_notification += callback
146
+
147
+ order_id = '{0}_order'.format(datetime.now().strftime('%Y%m%d_%H%M%S'))
148
+ await client.submit_order(
149
+ order_id,
150
+ security_code,
151
+ exchange,
152
+ qty=1,
153
+ order_type=OrderType.MARKET,
154
+ transaction_type=TransactionType.SELL,
155
+ #account_id="ABCD" # Mandatory if you have multiple accounts
156
+ )
157
+
158
+ await asyncio.sleep(1)
159
+
160
+ await client.disconnect()
161
+
162
+ asyncio.run(main())
163
+ ```
164
+
165
+ #### Placing a Limit Order and cancelling it
166
+
167
+ ```python
168
+ import asyncio
169
+ from datetime import datetime
170
+ from rithmic import RithmicClient, Gateway, OrderType, TransactionType
171
+
172
+ async def exchange_order_notification_callback(notification):
173
+ print("exchange order notification", notification)
174
+
175
+ async def main():
176
+ client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
177
+ await client.connect()
178
+
179
+ # Request front month contract
180
+ symbol, exchange = "ES", "CME"
181
+ security_code = await client.get_front_month_contract(symbol, exchange)
182
+
183
+ # Submit order
184
+ client.on_exchange_order_notification += exchange_order_notification_callback
185
+
186
+ order_id = '{0}_order'.format(datetime.now().strftime('%Y%m%d_%H%M%S'))
187
+ await client.submit_order(
188
+ order_id,
189
+ security_code,
190
+ exchange,
191
+ qty=1,
192
+ order_type=OrderType.LIMIT,
193
+ transaction_type=TransactionType.BUY,
194
+ price=5300.
195
+ )
196
+
197
+ await asyncio.sleep(1)
198
+ await client.cancel_order(order_id)
199
+
200
+ await asyncio.sleep(1)
201
+ await client.disconnect()
202
+
203
+ asyncio.run(main())
204
+ ```
205
+
206
+ ## History Data API
207
+
208
+ ### Fetch Historical Tick Data
209
+
210
+ The following example will fetch historical data, in a streaming fashion:
211
+
212
+ ```python
213
+ import asyncio
214
+ from datetime import datetime
215
+ from rithmic import RithmicClient, Gateway
216
+
217
+ async def main():
218
+ client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
219
+ await client.connect()
220
+
221
+ # Fetch historical tick data
222
+ ticks = await client.get_historical_tick_data(
223
+ "ESZ4",
224
+ "CME",
225
+ datetime(2024, 10, 15, 15, 30),
226
+ datetime(2024, 10, 15, 15, 31),
227
+ )
228
+
229
+ print(f"Received {len(ticks)} ticks")
230
+ print(f"Last tick timestamp: {ticks[-1]['datetime']}")
231
+
232
+ await client.disconnect()
233
+
234
+ asyncio.run(main())
235
+ ```
236
+
237
+ ### Fetch Historical Time Bars
238
+
239
+ ```python
240
+ import asyncio
241
+ from datetime import datetime
242
+ from rithmic import RithmicClient, Gateway, TimeBarType
243
+
244
+ async def main():
245
+ client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
246
+ await client.connect()
247
+
248
+ # Fetch historical time bar data
249
+ bars = await client.get_historical_time_bar(
250
+ "ESZ4",
251
+ "CME",
252
+ datetime(2024, 10, 15, 15, 30),
253
+ datetime(2024, 10, 15, 15, 31),
254
+ TimeBarType.SECOND_BAR,
255
+ 6
256
+ )
257
+
258
+ print(f"Received {len(bars)} bars")
259
+ print(f"Last bar timestamp: {bars[-1]['datetime']}")
260
+
261
+ await client.disconnect()
262
+
263
+ asyncio.run(main())
264
+ ```
265
+
266
+ ## Other methods
267
+
268
+ This code snippet will list your account summary, session orders and positions:
269
+
270
+ ```python
271
+ import asyncio
272
+ from rithmic import RithmicClient, Gateway
273
+
274
+ async def main():
275
+ client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
276
+ await client.connect()
277
+
278
+ account_id = "MY_ACCOUNT"
279
+
280
+ summary = await client.list_account_summary(account_id=account_id)
281
+ print("Account summary:", summary[0])
282
+
283
+ orders = await client.list_orders(account_id=account_id)
284
+ print("Orders:", orders)
285
+
286
+ positions = await client.list_positions(account_id=account_id)
287
+ print("Positions:", positions)
288
+
289
+ await client.disconnect()
290
+
291
+ asyncio.run(main())
292
+ ```
293
+
294
+ ## Testing
295
+
296
+ To execute the tests, use the following command: `make tests`
297
+
298
+ ## Unimplemented
299
+
300
+ The following features are currently not available in this package.
301
+ Contributions are welcome!
302
+ If you're interested in adding any of these features, please feel free to submit a Pull Request.
303
+
304
+ - Search Symbols Endpoint
305
+ - Bracket Orders
306
+ - One-Cancels-Other (OCO) Orders
307
+ - Market depth
308
+ - Tick bar historical & live data (Volume, Range or Tick bars)
@@ -0,0 +1,280 @@
1
+ # Python Rithmic API
2
+
3
+ A robust, async-based Python API designed to interface seamlessly with the Rithmic Protocol Buffer API. This package is built to provide an efficient and reliable connection to Rithmic's trading infrastructure, catering to advanced trading strategies and real-time data handling.
4
+
5
+ This was originally a fork of [pyrithmic](https://github.com/jacksonwoody/pyrithmic), but the code has been completely rewritten.
6
+
7
+ ## Key Enhancements
8
+
9
+ This repo introduces several key improvements and new features over the original repository, ensuring compatibility with modern Python environments and providing additional functionality:
10
+
11
+ - **Python 3.11+ Compatibility**: Refactored code to ensure smooth operation with the latest Python versions.
12
+ - **System Name Validation**: Implements pre-login validation of system names, as recommended by Rithmic support, with enhanced error handling during the login process.
13
+ - **Account Selection**: Allows users to specify which account to use when calling trading functions, rather than being restricted to the primary account.
14
+ - **STOP Orders**: Exposing STOP orders to users
15
+ - **Best Bid Offer (BBO) Streaming**: Integrates real-time Best Bid Offer tick streaming.
16
+ - **Historical Time Bars + Time Bars Streaming**:
17
+
18
+ The most significant upgrade is the transition to an async architecture, providing superior performance and responsiveness when dealing with real-time trading and market data.
19
+
20
+ ## Installation
21
+
22
+ ```
23
+ pip install git+https://github.com/rundef/pyrithmic.git#egg=pyrithmic
24
+ ```
25
+
26
+ ## Market data
27
+
28
+ ### Streaming Live Tick Data
29
+
30
+ Here's an example to get the front month contract for ES and stream market data:
31
+
32
+ ```python
33
+ import asyncio
34
+ from rithmic import RithmicClient, Gateway, DataType, LastTradePresenceBits
35
+
36
+ async def callback(data: dict):
37
+ if data["presence_bits"] & LastTradePresenceBits.LAST_TRADE:
38
+ print("received", data)
39
+
40
+ async def main():
41
+ client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
42
+ await client.connect()
43
+
44
+ # Request front month contract
45
+ symbol, exchange = "ES", "CME"
46
+ security_code = await client.get_front_month_contract(symbol, exchange)
47
+
48
+ # Stream market data
49
+ print(f"Streaming market data for {security_code}")
50
+ data_type = DataType.LAST_TRADE
51
+ client.on_tick += callback
52
+ await client.subscribe_to_market_data(security_code, exchange, data_type)
53
+
54
+ # Wait 10 seconds, unsubscribe and disconnect
55
+ await asyncio.sleep(10)
56
+ await client.unsubscribe_from_market_data(security_code, exchange, data_type)
57
+ await client.disconnect()
58
+
59
+ asyncio.run(main())
60
+ ```
61
+
62
+ ### Streaming Live Time Bars
63
+
64
+ ```python
65
+ import asyncio
66
+ from rithmic import RithmicClient, Gateway, TimeBarType
67
+
68
+ async def callback(data: dict):
69
+ print("received", data)
70
+
71
+ async def main():
72
+ client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
73
+ await client.connect()
74
+
75
+ # Request front month contract
76
+ symbol, exchange = "ES", "CME"
77
+ security_code = await client.get_front_month_contract(symbol, exchange)
78
+
79
+ # Stream market data
80
+ print(f"Streaming market data for {security_code}")
81
+
82
+ client.on_time_bar += callback
83
+ await client.subscribe_to_time_bar_data(security_code, exchange, TimeBarType.SECOND_BAR, 6)
84
+
85
+ # Wait 10 seconds, unsubscribe and disconnect
86
+ await asyncio.sleep(20)
87
+ await client.unsubscribe_from_time_bar_data(security_code, exchange, TimeBarType.SECOND_BAR, 6)
88
+ await client.disconnect()
89
+
90
+ asyncio.run(main())
91
+ ```
92
+
93
+ ## Order API
94
+
95
+ #### Placing a Market Order:
96
+
97
+ As a market order will be filled immediately, this script will submit the order and receive a fill straight away:
98
+
99
+ ```python
100
+ import asyncio
101
+ from datetime import datetime
102
+ from rithmic import RithmicClient, Gateway, OrderType, ExchangeOrderNotificationType, TransactionType
103
+
104
+ async def callback(notification):
105
+ if notification.notify_type == ExchangeOrderNotificationType.FILL:
106
+ print("order filled", notification)
107
+
108
+ async def main():
109
+ client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
110
+ await client.connect()
111
+
112
+ # Request front month contract
113
+ symbol, exchange = "ES", "CME"
114
+ security_code = await client.get_front_month_contract(symbol, exchange)
115
+
116
+ # Submit order
117
+ client.on_exchange_order_notification += callback
118
+
119
+ order_id = '{0}_order'.format(datetime.now().strftime('%Y%m%d_%H%M%S'))
120
+ await client.submit_order(
121
+ order_id,
122
+ security_code,
123
+ exchange,
124
+ qty=1,
125
+ order_type=OrderType.MARKET,
126
+ transaction_type=TransactionType.SELL,
127
+ #account_id="ABCD" # Mandatory if you have multiple accounts
128
+ )
129
+
130
+ await asyncio.sleep(1)
131
+
132
+ await client.disconnect()
133
+
134
+ asyncio.run(main())
135
+ ```
136
+
137
+ #### Placing a Limit Order and cancelling it
138
+
139
+ ```python
140
+ import asyncio
141
+ from datetime import datetime
142
+ from rithmic import RithmicClient, Gateway, OrderType, TransactionType
143
+
144
+ async def exchange_order_notification_callback(notification):
145
+ print("exchange order notification", notification)
146
+
147
+ async def main():
148
+ client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
149
+ await client.connect()
150
+
151
+ # Request front month contract
152
+ symbol, exchange = "ES", "CME"
153
+ security_code = await client.get_front_month_contract(symbol, exchange)
154
+
155
+ # Submit order
156
+ client.on_exchange_order_notification += exchange_order_notification_callback
157
+
158
+ order_id = '{0}_order'.format(datetime.now().strftime('%Y%m%d_%H%M%S'))
159
+ await client.submit_order(
160
+ order_id,
161
+ security_code,
162
+ exchange,
163
+ qty=1,
164
+ order_type=OrderType.LIMIT,
165
+ transaction_type=TransactionType.BUY,
166
+ price=5300.
167
+ )
168
+
169
+ await asyncio.sleep(1)
170
+ await client.cancel_order(order_id)
171
+
172
+ await asyncio.sleep(1)
173
+ await client.disconnect()
174
+
175
+ asyncio.run(main())
176
+ ```
177
+
178
+ ## History Data API
179
+
180
+ ### Fetch Historical Tick Data
181
+
182
+ The following example will fetch historical data, in a streaming fashion:
183
+
184
+ ```python
185
+ import asyncio
186
+ from datetime import datetime
187
+ from rithmic import RithmicClient, Gateway
188
+
189
+ async def main():
190
+ client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
191
+ await client.connect()
192
+
193
+ # Fetch historical tick data
194
+ ticks = await client.get_historical_tick_data(
195
+ "ESZ4",
196
+ "CME",
197
+ datetime(2024, 10, 15, 15, 30),
198
+ datetime(2024, 10, 15, 15, 31),
199
+ )
200
+
201
+ print(f"Received {len(ticks)} ticks")
202
+ print(f"Last tick timestamp: {ticks[-1]['datetime']}")
203
+
204
+ await client.disconnect()
205
+
206
+ asyncio.run(main())
207
+ ```
208
+
209
+ ### Fetch Historical Time Bars
210
+
211
+ ```python
212
+ import asyncio
213
+ from datetime import datetime
214
+ from rithmic import RithmicClient, Gateway, TimeBarType
215
+
216
+ async def main():
217
+ client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
218
+ await client.connect()
219
+
220
+ # Fetch historical time bar data
221
+ bars = await client.get_historical_time_bar(
222
+ "ESZ4",
223
+ "CME",
224
+ datetime(2024, 10, 15, 15, 30),
225
+ datetime(2024, 10, 15, 15, 31),
226
+ TimeBarType.SECOND_BAR,
227
+ 6
228
+ )
229
+
230
+ print(f"Received {len(bars)} bars")
231
+ print(f"Last bar timestamp: {bars[-1]['datetime']}")
232
+
233
+ await client.disconnect()
234
+
235
+ asyncio.run(main())
236
+ ```
237
+
238
+ ## Other methods
239
+
240
+ This code snippet will list your account summary, session orders and positions:
241
+
242
+ ```python
243
+ import asyncio
244
+ from rithmic import RithmicClient, Gateway
245
+
246
+ async def main():
247
+ client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
248
+ await client.connect()
249
+
250
+ account_id = "MY_ACCOUNT"
251
+
252
+ summary = await client.list_account_summary(account_id=account_id)
253
+ print("Account summary:", summary[0])
254
+
255
+ orders = await client.list_orders(account_id=account_id)
256
+ print("Orders:", orders)
257
+
258
+ positions = await client.list_positions(account_id=account_id)
259
+ print("Positions:", positions)
260
+
261
+ await client.disconnect()
262
+
263
+ asyncio.run(main())
264
+ ```
265
+
266
+ ## Testing
267
+
268
+ To execute the tests, use the following command: `make tests`
269
+
270
+ ## Unimplemented
271
+
272
+ The following features are currently not available in this package.
273
+ Contributions are welcome!
274
+ If you're interested in adding any of these features, please feel free to submit a Pull Request.
275
+
276
+ - Search Symbols Endpoint
277
+ - Bracket Orders
278
+ - One-Cancels-Other (OCO) Orders
279
+ - Market depth
280
+ - Tick bar historical & live data (Volume, Range or Tick bars)
@@ -0,0 +1,3 @@
1
+ [build-system]
2
+ requires = ["setuptools>=46.4.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
@@ -0,0 +1,8 @@
1
+ [metadata]
2
+ version = attr: rithmic.__version__
3
+ license_files = LICENSE
4
+
5
+ [egg_info]
6
+ tag_build =
7
+ tag_date = 0
8
+
@@ -0,0 +1,50 @@
1
+ import setuptools
2
+
3
+ with open('README.md', 'r', encoding='utf-8') as fh:
4
+ long_description = fh.read()
5
+
6
+ setuptools.setup(
7
+ name='async_rithmic',
8
+ version='1.0.0',
9
+ author='Mickael Burguet',
10
+ description='Python API Integration with Rithmic Protocol Buffer API',
11
+ keywords='python rithmic',
12
+ long_description=long_description,
13
+ long_description_content_type='text/markdown',
14
+ url='https://github.com/rundef/pyrithmic',
15
+ project_urls={
16
+ 'Documentation': 'https://github.com/rundef/pyrithmic',
17
+ 'Bug Reports': 'https://github.com/rundef/pyrithmic/issues',
18
+ 'Source Code': 'https://github.com/rundef/pyrithmic',
19
+ # 'Funding': '',
20
+ # 'Say Thanks!': '',
21
+ },
22
+ package_dir={'': 'src'},
23
+ packages=setuptools.find_packages(where='src'),
24
+ include_package_data=True,
25
+ classifiers=[
26
+ # see https://pypi.org/classifiers/
27
+ 'Development Status :: 5 - Production/Stable',
28
+
29
+ 'Intended Audience :: Developers',
30
+ 'Topic :: Software Development :: Build Tools',
31
+ 'Programming Language :: Python :: 3',
32
+ 'Programming Language :: Python :: 3.8',
33
+ 'Programming Language :: Python :: 3.9',
34
+ 'Programming Language :: Python :: 3.10',
35
+ 'Programming Language :: Python :: 3.11',
36
+ 'Programming Language :: Python :: 3.12',
37
+ 'Programming Language :: Python :: 3 :: Only',
38
+ 'License :: OSI Approved :: MIT License',
39
+ 'Operating System :: OS Independent',
40
+ ],
41
+ python_requires='>=3.8',
42
+ install_requires=[
43
+ 'websockets>=9.0',
44
+ 'protobuf==4.25.4',
45
+ ],
46
+ extras_require={
47
+ 'dev': ['check-manifest'],
48
+ 'test': ['coverage', 'pytest'],
49
+ },
50
+ )