itchfeed 1.0.3__tar.gz → 1.0.4__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.
- {itchfeed-1.0.3/itchfeed.egg-info → itchfeed-1.0.4}/PKG-INFO +75 -1
- {itchfeed-1.0.3 → itchfeed-1.0.4}/README.md +74 -0
- {itchfeed-1.0.3 → itchfeed-1.0.4}/itch/__init__.py +2 -1
- {itchfeed-1.0.3 → itchfeed-1.0.4}/itch/messages.py +55 -0
- {itchfeed-1.0.3 → itchfeed-1.0.4/itchfeed.egg-info}/PKG-INFO +75 -1
- {itchfeed-1.0.3 → itchfeed-1.0.4}/itchfeed.egg-info/SOURCES.txt +1 -0
- {itchfeed-1.0.3 → itchfeed-1.0.4}/setup.py +1 -1
- itchfeed-1.0.4/tests/test_create_message.py +28 -0
- {itchfeed-1.0.3 → itchfeed-1.0.4}/LICENSE +0 -0
- {itchfeed-1.0.3 → itchfeed-1.0.4}/MANIFEST.in +0 -0
- {itchfeed-1.0.3 → itchfeed-1.0.4}/itch/indicators.py +0 -0
- {itchfeed-1.0.3 → itchfeed-1.0.4}/itch/parser.py +0 -0
- {itchfeed-1.0.3 → itchfeed-1.0.4}/itchfeed.egg-info/dependency_links.txt +0 -0
- {itchfeed-1.0.3 → itchfeed-1.0.4}/itchfeed.egg-info/requires.txt +0 -0
- {itchfeed-1.0.3 → itchfeed-1.0.4}/itchfeed.egg-info/top_level.txt +0 -0
- {itchfeed-1.0.3 → itchfeed-1.0.4}/requirements.txt +0 -0
- {itchfeed-1.0.3 → itchfeed-1.0.4}/setup.cfg +0 -0
- {itchfeed-1.0.3 → itchfeed-1.0.4}/tests/test_messages.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: itchfeed
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.4
|
4
4
|
Summary: Simple parser for ITCH messages
|
5
5
|
Home-page: https://github.com/bbalouki/itch
|
6
6
|
Download-URL: https://pypi.org/project/itchfeed/
|
@@ -52,6 +52,8 @@ Dynamic: summary
|
|
52
52
|
* [Usage](#usage)
|
53
53
|
* [Parsing from a Binary File](#parsing-from-a-binary-file)
|
54
54
|
* [Parsing from Raw Bytes](#parsing-from-raw-bytes)
|
55
|
+
* [Creating Messages Programmatically](#creating-messages-programmatically)
|
56
|
+
* [Example with Real-World Sample Data](#example-with-real-world-sample-data)
|
55
57
|
* [Interpreting Market Data (Conceptual Overview)](#interpreting-market-data-conceptual-overview)
|
56
58
|
* [Supported Message Types](#supported-message-types)
|
57
59
|
* [Data Representation](#data-representation)
|
@@ -211,6 +213,78 @@ while not message_queue.empty():
|
|
211
213
|
|
212
214
|
```
|
213
215
|
|
216
|
+
### Creating Messages Programmatically
|
217
|
+
|
218
|
+
In addition to parsing, `itch` provides a simple way to create ITCH message objects from scratch. This is particularly useful for:
|
219
|
+
- **Testing:** Generating specific message sequences to test your own downstream applications.
|
220
|
+
- **Simulation:** Building custom market simulators that produce ITCH-compliant data streams.
|
221
|
+
- **Data Generation:** Creating custom datasets for analysis or backtesting.
|
222
|
+
|
223
|
+
The `create_message` function is the primary tool for this purpose. It takes a `message_type` and keyword arguments corresponding to the desired message attributes.
|
224
|
+
|
225
|
+
Here's a basic example of how to create a `SystemEventMessage` to signal the "Start of Messages":
|
226
|
+
|
227
|
+
```python
|
228
|
+
from itch.messages import create_message, SystemEventMessage
|
229
|
+
|
230
|
+
# Define the attributes for the message
|
231
|
+
event_attributes = {
|
232
|
+
"stock_locate": 1,
|
233
|
+
"tracking_number": 2,
|
234
|
+
"timestamp": 1651500000 * 1_000_000_000,
|
235
|
+
"event_code": b"O"
|
236
|
+
}
|
237
|
+
|
238
|
+
# Create the message object
|
239
|
+
system_event_message = create_message(b"S", **event_attributes)
|
240
|
+
|
241
|
+
# You can now work with this object just like one from the parser
|
242
|
+
print(isinstance(system_event_message, SystemEventMessage))
|
243
|
+
# Expected output: True
|
244
|
+
|
245
|
+
print(system_event_message)
|
246
|
+
# Expected output: SystemEventMessage(description='System Event Message', event_code='O', message_format='!HHHIc', message_pack_format='!cHHHIc', message_size=12, message_type='S', price_precision=4, stock_locate=1, timestamp=86311638581248, tracking_number=2)
|
247
|
+
```
|
248
|
+
|
249
|
+
### Example with Real-World Sample Data
|
250
|
+
|
251
|
+
You can also use the sample data provided in `tests/data.py` to create messages, simulating a more realistic scenario.
|
252
|
+
|
253
|
+
```python
|
254
|
+
from itch.messages import create_message, AddOrderNoMPIAttributionMessage
|
255
|
+
from tests.data import TEST_DATA
|
256
|
+
|
257
|
+
# Get the sample data for an "Add Order" message (type 'A')
|
258
|
+
add_order_data = TEST_DATA[b"A"]
|
259
|
+
|
260
|
+
# Create the message
|
261
|
+
add_order_message = create_message(b"A", **add_order_data)
|
262
|
+
|
263
|
+
# Verify the type
|
264
|
+
print(isinstance(add_order_message, AddOrderNoMPIAttributionMessage))
|
265
|
+
# Expected output: True
|
266
|
+
|
267
|
+
# Access its attributes
|
268
|
+
print(f"Stock: {add_order_message.stock.decode().strip()}")
|
269
|
+
# Expected output: Stock: AAPL
|
270
|
+
|
271
|
+
print(f"Price: {add_order_message.decode_price('price')}")
|
272
|
+
# Expected output: Price: 150.1234
|
273
|
+
|
274
|
+
# Test all message types in the sample data
|
275
|
+
for message_type, sample_data in TEST_DATA.items():
|
276
|
+
print(f"Creating message of type {message_type}")
|
277
|
+
message = create_message(message_type, **sample_data)
|
278
|
+
print(f"Created message: {message}")
|
279
|
+
print(f"Packed message: {message.pack()}")
|
280
|
+
print(f"Message size: {message.message_size}")
|
281
|
+
print(f"Message Attributes: {message.get_attributes()}")
|
282
|
+
assert len(message.pack()) == message.message_size
|
283
|
+
print()
|
284
|
+
```
|
285
|
+
|
286
|
+
By leveraging `create_message`, you can build robust test suites for your trading algorithms, compliance checks, or data analysis pipelines without needing a live data feed.
|
287
|
+
|
214
288
|
## Interpreting Market Data (Conceptual Overview)
|
215
289
|
|
216
290
|
Parsing individual ITCH messages is the first step; understanding market dynamics often requires processing and correlating a sequence of these messages. This library provides the tools to decode messages, but interpreting their collective meaning requires building further logic.
|
@@ -16,6 +16,8 @@
|
|
16
16
|
* [Usage](#usage)
|
17
17
|
* [Parsing from a Binary File](#parsing-from-a-binary-file)
|
18
18
|
* [Parsing from Raw Bytes](#parsing-from-raw-bytes)
|
19
|
+
* [Creating Messages Programmatically](#creating-messages-programmatically)
|
20
|
+
* [Example with Real-World Sample Data](#example-with-real-world-sample-data)
|
19
21
|
* [Interpreting Market Data (Conceptual Overview)](#interpreting-market-data-conceptual-overview)
|
20
22
|
* [Supported Message Types](#supported-message-types)
|
21
23
|
* [Data Representation](#data-representation)
|
@@ -175,6 +177,78 @@ while not message_queue.empty():
|
|
175
177
|
|
176
178
|
```
|
177
179
|
|
180
|
+
### Creating Messages Programmatically
|
181
|
+
|
182
|
+
In addition to parsing, `itch` provides a simple way to create ITCH message objects from scratch. This is particularly useful for:
|
183
|
+
- **Testing:** Generating specific message sequences to test your own downstream applications.
|
184
|
+
- **Simulation:** Building custom market simulators that produce ITCH-compliant data streams.
|
185
|
+
- **Data Generation:** Creating custom datasets for analysis or backtesting.
|
186
|
+
|
187
|
+
The `create_message` function is the primary tool for this purpose. It takes a `message_type` and keyword arguments corresponding to the desired message attributes.
|
188
|
+
|
189
|
+
Here's a basic example of how to create a `SystemEventMessage` to signal the "Start of Messages":
|
190
|
+
|
191
|
+
```python
|
192
|
+
from itch.messages import create_message, SystemEventMessage
|
193
|
+
|
194
|
+
# Define the attributes for the message
|
195
|
+
event_attributes = {
|
196
|
+
"stock_locate": 1,
|
197
|
+
"tracking_number": 2,
|
198
|
+
"timestamp": 1651500000 * 1_000_000_000,
|
199
|
+
"event_code": b"O"
|
200
|
+
}
|
201
|
+
|
202
|
+
# Create the message object
|
203
|
+
system_event_message = create_message(b"S", **event_attributes)
|
204
|
+
|
205
|
+
# You can now work with this object just like one from the parser
|
206
|
+
print(isinstance(system_event_message, SystemEventMessage))
|
207
|
+
# Expected output: True
|
208
|
+
|
209
|
+
print(system_event_message)
|
210
|
+
# Expected output: SystemEventMessage(description='System Event Message', event_code='O', message_format='!HHHIc', message_pack_format='!cHHHIc', message_size=12, message_type='S', price_precision=4, stock_locate=1, timestamp=86311638581248, tracking_number=2)
|
211
|
+
```
|
212
|
+
|
213
|
+
### Example with Real-World Sample Data
|
214
|
+
|
215
|
+
You can also use the sample data provided in `tests/data.py` to create messages, simulating a more realistic scenario.
|
216
|
+
|
217
|
+
```python
|
218
|
+
from itch.messages import create_message, AddOrderNoMPIAttributionMessage
|
219
|
+
from tests.data import TEST_DATA
|
220
|
+
|
221
|
+
# Get the sample data for an "Add Order" message (type 'A')
|
222
|
+
add_order_data = TEST_DATA[b"A"]
|
223
|
+
|
224
|
+
# Create the message
|
225
|
+
add_order_message = create_message(b"A", **add_order_data)
|
226
|
+
|
227
|
+
# Verify the type
|
228
|
+
print(isinstance(add_order_message, AddOrderNoMPIAttributionMessage))
|
229
|
+
# Expected output: True
|
230
|
+
|
231
|
+
# Access its attributes
|
232
|
+
print(f"Stock: {add_order_message.stock.decode().strip()}")
|
233
|
+
# Expected output: Stock: AAPL
|
234
|
+
|
235
|
+
print(f"Price: {add_order_message.decode_price('price')}")
|
236
|
+
# Expected output: Price: 150.1234
|
237
|
+
|
238
|
+
# Test all message types in the sample data
|
239
|
+
for message_type, sample_data in TEST_DATA.items():
|
240
|
+
print(f"Creating message of type {message_type}")
|
241
|
+
message = create_message(message_type, **sample_data)
|
242
|
+
print(f"Created message: {message}")
|
243
|
+
print(f"Packed message: {message.pack()}")
|
244
|
+
print(f"Message size: {message.message_size}")
|
245
|
+
print(f"Message Attributes: {message.get_attributes()}")
|
246
|
+
assert len(message.pack()) == message.message_size
|
247
|
+
print()
|
248
|
+
```
|
249
|
+
|
250
|
+
By leveraging `create_message`, you can build robust test suites for your trading algorithms, compliance checks, or data analysis pipelines without needing a live data feed.
|
251
|
+
|
178
252
|
## Interpreting Market Data (Conceptual Overview)
|
179
253
|
|
180
254
|
Parsing individual ITCH messages is the first step; understanding market dynamics often requires processing and correlating a sequence of these messages. This library provides the tools to decode messages, but interpreting their collective meaning requires building further logic.
|
@@ -35,6 +35,13 @@ class MarketMessage(object):
|
|
35
35
|
def __repr__(self):
|
36
36
|
return repr(self.decode())
|
37
37
|
|
38
|
+
def pack(self) -> bytes:
|
39
|
+
"""
|
40
|
+
Packs the message into bytes using the defined message_pack_format.
|
41
|
+
This method should be overridden by subclasses to include specific fields.
|
42
|
+
"""
|
43
|
+
pass
|
44
|
+
|
38
45
|
def set_timestamp(self, ts1: int, ts2: int):
|
39
46
|
"""
|
40
47
|
Reconstructs a 6-byte timestamp (48 bits) from two 32-bit unsigned integers.
|
@@ -1598,3 +1605,51 @@ messages: Dict[bytes, Type[MarketMessage]] = {
|
|
1598
1605
|
b"N": RetailPriceImprovementIndicator,
|
1599
1606
|
b"O": DLCRMessage,
|
1600
1607
|
}
|
1608
|
+
|
1609
|
+
|
1610
|
+
def create_message(message_type: bytes, **kwargs) -> Type[MarketMessage]:
|
1611
|
+
"""
|
1612
|
+
Creates a new message of a given type with specified attributes.
|
1613
|
+
|
1614
|
+
This function simplifies the process of message creation by handling
|
1615
|
+
the instantiation and attribute setting for any valid message type.
|
1616
|
+
It's particularly useful for simulating trading environments or
|
1617
|
+
generating test data without manually packing and unpacking bytes.
|
1618
|
+
|
1619
|
+
Args:
|
1620
|
+
message_type (bytes):
|
1621
|
+
A single-byte identifier for the message type (e.g., b'A'
|
1622
|
+
for AddOrderNoMPIAttributionMessage).
|
1623
|
+
**kwargs:
|
1624
|
+
Keyword arguments representing the attributes of the message.
|
1625
|
+
These must match the attributes expected by the message class
|
1626
|
+
(e.g., `stock_locate`, `timestamp`, `price`).
|
1627
|
+
|
1628
|
+
Returns:
|
1629
|
+
MarketMessage:
|
1630
|
+
An instance of the corresponding message class, populated with
|
1631
|
+
the provided attributes.
|
1632
|
+
|
1633
|
+
Raises:
|
1634
|
+
ValueError:
|
1635
|
+
If the `message_type` is not found in the registered messages.
|
1636
|
+
"""
|
1637
|
+
message_class = messages.get(message_type)
|
1638
|
+
if not message_class:
|
1639
|
+
raise ValueError(f"Unknown message type: {message_type.decode()}")
|
1640
|
+
|
1641
|
+
# Create a new instance without calling __init__
|
1642
|
+
# __init__ is for unpacking, not creating
|
1643
|
+
instance = message_class.__new__(message_class)
|
1644
|
+
|
1645
|
+
# Set attributes from kwargs
|
1646
|
+
for key, value in kwargs.items():
|
1647
|
+
if key == 'timestamp':
|
1648
|
+
# Timestamps are 48-bit, so we need to mask the original value
|
1649
|
+
value &= ((1 << 48) - 1)
|
1650
|
+
setattr(instance, key, value)
|
1651
|
+
|
1652
|
+
# Set the message_type attribute on the instance, as it's used by pack()
|
1653
|
+
instance.message_type = message_type
|
1654
|
+
|
1655
|
+
return instance
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: itchfeed
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.4
|
4
4
|
Summary: Simple parser for ITCH messages
|
5
5
|
Home-page: https://github.com/bbalouki/itch
|
6
6
|
Download-URL: https://pypi.org/project/itchfeed/
|
@@ -52,6 +52,8 @@ Dynamic: summary
|
|
52
52
|
* [Usage](#usage)
|
53
53
|
* [Parsing from a Binary File](#parsing-from-a-binary-file)
|
54
54
|
* [Parsing from Raw Bytes](#parsing-from-raw-bytes)
|
55
|
+
* [Creating Messages Programmatically](#creating-messages-programmatically)
|
56
|
+
* [Example with Real-World Sample Data](#example-with-real-world-sample-data)
|
55
57
|
* [Interpreting Market Data (Conceptual Overview)](#interpreting-market-data-conceptual-overview)
|
56
58
|
* [Supported Message Types](#supported-message-types)
|
57
59
|
* [Data Representation](#data-representation)
|
@@ -211,6 +213,78 @@ while not message_queue.empty():
|
|
211
213
|
|
212
214
|
```
|
213
215
|
|
216
|
+
### Creating Messages Programmatically
|
217
|
+
|
218
|
+
In addition to parsing, `itch` provides a simple way to create ITCH message objects from scratch. This is particularly useful for:
|
219
|
+
- **Testing:** Generating specific message sequences to test your own downstream applications.
|
220
|
+
- **Simulation:** Building custom market simulators that produce ITCH-compliant data streams.
|
221
|
+
- **Data Generation:** Creating custom datasets for analysis or backtesting.
|
222
|
+
|
223
|
+
The `create_message` function is the primary tool for this purpose. It takes a `message_type` and keyword arguments corresponding to the desired message attributes.
|
224
|
+
|
225
|
+
Here's a basic example of how to create a `SystemEventMessage` to signal the "Start of Messages":
|
226
|
+
|
227
|
+
```python
|
228
|
+
from itch.messages import create_message, SystemEventMessage
|
229
|
+
|
230
|
+
# Define the attributes for the message
|
231
|
+
event_attributes = {
|
232
|
+
"stock_locate": 1,
|
233
|
+
"tracking_number": 2,
|
234
|
+
"timestamp": 1651500000 * 1_000_000_000,
|
235
|
+
"event_code": b"O"
|
236
|
+
}
|
237
|
+
|
238
|
+
# Create the message object
|
239
|
+
system_event_message = create_message(b"S", **event_attributes)
|
240
|
+
|
241
|
+
# You can now work with this object just like one from the parser
|
242
|
+
print(isinstance(system_event_message, SystemEventMessage))
|
243
|
+
# Expected output: True
|
244
|
+
|
245
|
+
print(system_event_message)
|
246
|
+
# Expected output: SystemEventMessage(description='System Event Message', event_code='O', message_format='!HHHIc', message_pack_format='!cHHHIc', message_size=12, message_type='S', price_precision=4, stock_locate=1, timestamp=86311638581248, tracking_number=2)
|
247
|
+
```
|
248
|
+
|
249
|
+
### Example with Real-World Sample Data
|
250
|
+
|
251
|
+
You can also use the sample data provided in `tests/data.py` to create messages, simulating a more realistic scenario.
|
252
|
+
|
253
|
+
```python
|
254
|
+
from itch.messages import create_message, AddOrderNoMPIAttributionMessage
|
255
|
+
from tests.data import TEST_DATA
|
256
|
+
|
257
|
+
# Get the sample data for an "Add Order" message (type 'A')
|
258
|
+
add_order_data = TEST_DATA[b"A"]
|
259
|
+
|
260
|
+
# Create the message
|
261
|
+
add_order_message = create_message(b"A", **add_order_data)
|
262
|
+
|
263
|
+
# Verify the type
|
264
|
+
print(isinstance(add_order_message, AddOrderNoMPIAttributionMessage))
|
265
|
+
# Expected output: True
|
266
|
+
|
267
|
+
# Access its attributes
|
268
|
+
print(f"Stock: {add_order_message.stock.decode().strip()}")
|
269
|
+
# Expected output: Stock: AAPL
|
270
|
+
|
271
|
+
print(f"Price: {add_order_message.decode_price('price')}")
|
272
|
+
# Expected output: Price: 150.1234
|
273
|
+
|
274
|
+
# Test all message types in the sample data
|
275
|
+
for message_type, sample_data in TEST_DATA.items():
|
276
|
+
print(f"Creating message of type {message_type}")
|
277
|
+
message = create_message(message_type, **sample_data)
|
278
|
+
print(f"Created message: {message}")
|
279
|
+
print(f"Packed message: {message.pack()}")
|
280
|
+
print(f"Message size: {message.message_size}")
|
281
|
+
print(f"Message Attributes: {message.get_attributes()}")
|
282
|
+
assert len(message.pack()) == message.message_size
|
283
|
+
print()
|
284
|
+
```
|
285
|
+
|
286
|
+
By leveraging `create_message`, you can build robust test suites for your trading algorithms, compliance checks, or data analysis pipelines without needing a live data feed.
|
287
|
+
|
214
288
|
## Interpreting Market Data (Conceptual Overview)
|
215
289
|
|
216
290
|
Parsing individual ITCH messages is the first step; understanding market dynamics often requires processing and correlating a sequence of these messages. This library provides the tools to decode messages, but interpreting their collective meaning requires building further logic.
|
@@ -12,7 +12,7 @@ with io.open(path.join(here, "README.md"), encoding="utf-8") as f:
|
|
12
12
|
with io.open(path.join(here, "requirements.txt"), encoding="utf-8") as f:
|
13
13
|
REQUIREMENTS = [line.rstrip() for line in f]
|
14
14
|
|
15
|
-
VERSION = "1.0.
|
15
|
+
VERSION = "1.0.4"
|
16
16
|
DESCRIPTION = "Simple parser for ITCH messages"
|
17
17
|
|
18
18
|
KEYWORDS = [
|
@@ -0,0 +1,28 @@
|
|
1
|
+
import pytest
|
2
|
+
from itch.messages import create_message, messages
|
3
|
+
from .data import TEST_DATA
|
4
|
+
|
5
|
+
@pytest.mark.parametrize("message_type, sample_data", TEST_DATA.items())
|
6
|
+
def test_create_message_and_pack(message_type, sample_data):
|
7
|
+
"""
|
8
|
+
Tests that create_message correctly creates a message that can be packed,
|
9
|
+
and that the packed message can be unpacked to match the original data.
|
10
|
+
"""
|
11
|
+
# Create a message using the new function
|
12
|
+
created_message = create_message(message_type, **sample_data)
|
13
|
+
|
14
|
+
# Pack the created message
|
15
|
+
packed_message = created_message.pack()
|
16
|
+
|
17
|
+
# Unpack the message using the original class constructor
|
18
|
+
message_class = messages[message_type]
|
19
|
+
unpacked_message = message_class(packed_message)
|
20
|
+
|
21
|
+
# Verify that the attributes of the unpacked message match the original data
|
22
|
+
for key, expected_value in sample_data.items():
|
23
|
+
if key == 'timestamp':
|
24
|
+
# Timestamps are 48-bit, so we need to mask the original value
|
25
|
+
expected_value &= ((1 << 48) - 1)
|
26
|
+
assert getattr(unpacked_message, key) == expected_value, (
|
27
|
+
f"Attribute '{key}' mismatch for message type {message_type.decode()}"
|
28
|
+
)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|