itchfeed 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.
- itchfeed-1.0.0/LICENSE +21 -0
- itchfeed-1.0.0/MANIFEST.in +1 -0
- itchfeed-1.0.0/PKG-INFO +217 -0
- itchfeed-1.0.0/README.md +183 -0
- itchfeed-1.0.0/itch/__init__.py +14 -0
- itchfeed-1.0.0/itch/indicators.py +206 -0
- itchfeed-1.0.0/itch/messages.py +1600 -0
- itchfeed-1.0.0/itch/parser.py +180 -0
- itchfeed-1.0.0/itchfeed.egg-info/PKG-INFO +217 -0
- itchfeed-1.0.0/itchfeed.egg-info/SOURCES.txt +15 -0
- itchfeed-1.0.0/itchfeed.egg-info/dependency_links.txt +1 -0
- itchfeed-1.0.0/itchfeed.egg-info/requires.txt +1 -0
- itchfeed-1.0.0/itchfeed.egg-info/top_level.txt +1 -0
- itchfeed-1.0.0/requirements.txt +1 -0
- itchfeed-1.0.0/setup.cfg +4 -0
- itchfeed-1.0.0/setup.py +66 -0
- itchfeed-1.0.0/tests/test_messages.py +444 -0
itchfeed-1.0.0/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2025 Bertin Balouki SIMYELI
|
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 @@
|
|
1
|
+
include requirements.txt
|
itchfeed-1.0.0/PKG-INFO
ADDED
@@ -0,0 +1,217 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: itchfeed
|
3
|
+
Version: 1.0.0
|
4
|
+
Summary: Simple parser for ITCH messages
|
5
|
+
Home-page: https://github.com/bbalouki/itch
|
6
|
+
Author: Bertin Balouki SIMYELI
|
7
|
+
Author-email: <bertin@bbstrader.com>
|
8
|
+
Maintainer: Bertin Balouki SIMYELI
|
9
|
+
License: The MIT License (MIT)
|
10
|
+
Project-URL: Source Code, https://github.com/bbalouki/itch
|
11
|
+
Keywords: Finance,Financial,Quantitative,Equities,Data,Feed,ETFs,Funds,Trading,Investing,Portfolio,Optimization,Performance
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
13
|
+
Classifier: Intended Audience :: Developers
|
14
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
15
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
17
|
+
Classifier: Operating System :: OS Independent
|
18
|
+
Description-Content-Type: text/markdown
|
19
|
+
License-File: LICENSE
|
20
|
+
Requires-Dist: pytest
|
21
|
+
Dynamic: author
|
22
|
+
Dynamic: author-email
|
23
|
+
Dynamic: classifier
|
24
|
+
Dynamic: description
|
25
|
+
Dynamic: description-content-type
|
26
|
+
Dynamic: home-page
|
27
|
+
Dynamic: keywords
|
28
|
+
Dynamic: license
|
29
|
+
Dynamic: license-file
|
30
|
+
Dynamic: maintainer
|
31
|
+
Dynamic: project-url
|
32
|
+
Dynamic: requires-dist
|
33
|
+
Dynamic: summary
|
34
|
+
|
35
|
+
# Nasdaq TotalView-ITCH 5.0 Parser
|
36
|
+
|
37
|
+
[](https://opensource.org/licenses/MIT) <!-- Choose your license -->
|
38
|
+
|
39
|
+
A Python library for parsing binary data conforming to the Nasdaq TotalView-ITCH 5.0 protocol specification. This parser converts the raw byte stream into structured Python objects, making it easier to work with Nasdaq market data.
|
40
|
+
|
41
|
+
## Overview
|
42
|
+
|
43
|
+
The Nasdaq TotalView-ITCH 5.0 protocol is a binary protocol used by Nasdaq to disseminate full order book depth, trade information, and system events for equities traded on its execution system. This parser handles the low-level details of reading the binary format, unpacking fields according to the specification, and presenting the data as intuitive Python objects.
|
44
|
+
|
45
|
+
## Features
|
46
|
+
|
47
|
+
* **Parses ITCH 5.0 Binary Data:** Accurately interprets the binary message structures defined in the official specification.
|
48
|
+
* **Supports All Standard Message Types:** Implements classes for all messages defined in the ITCH 5.0 specification (System Event, Stock Directory, Add Order, Trade, etc.).
|
49
|
+
* **Object-Oriented Representation:** Each ITCH message type is represented by a dedicated Python class (`SystemEventMessage`, `AddOrderMessage`, etc.), inheriting from a common `MarketMessage` base class.
|
50
|
+
* **Flexible Input:** Reads and parses messages from:
|
51
|
+
* Binary files (`.gz` or similar).
|
52
|
+
* Raw byte streams (e.g., from network sockets).
|
53
|
+
* **Data Decoding:** Provides a `.decode()` method on each message object to convert it into a human-readable `dataclass` representation, handling:
|
54
|
+
* Byte-to-string conversion (ASCII).
|
55
|
+
* Stripping padding spaces.
|
56
|
+
* Price decoding based on defined precision.
|
57
|
+
* **Timestamp Handling:** Correctly reconstructs the 6-byte (48-bit) nanosecond timestamps.
|
58
|
+
* **Price Handling:** Decodes fixed-point price fields into floating-point numbers based on the standard 4 or 8 decimal place precision.
|
59
|
+
* **Pure Python:** Relies only on the Python standard library . No external dependencies required.
|
60
|
+
|
61
|
+
## Installation
|
62
|
+
|
63
|
+
You can install this project using ``pip``
|
64
|
+
|
65
|
+
1. **Clone the repository (or download the source code):**
|
66
|
+
```bash
|
67
|
+
pip install itch
|
68
|
+
```
|
69
|
+
2. **Import the necessary modules** directly into your Python project:
|
70
|
+
```python
|
71
|
+
from itch.parser import MessageParser
|
72
|
+
from itch.messages import ModifyOrderMessage
|
73
|
+
```
|
74
|
+
|
75
|
+
## Usage
|
76
|
+
|
77
|
+
### Parsing from a Binary File
|
78
|
+
|
79
|
+
This is useful for processing historical ITCH data stored in files. The `MessageParser` handles buffering efficiently.
|
80
|
+
|
81
|
+
```python
|
82
|
+
from itch import MessageParser
|
83
|
+
from itch.messages import AddOrderMessage, TradeMessage
|
84
|
+
|
85
|
+
# Initialize the parser. Optionally filter messages by type.
|
86
|
+
# parser = MessageParser(message_type=b"AP") # Only parse AddOrder and NonCrossTrade messages
|
87
|
+
parser = MessageParser()
|
88
|
+
|
89
|
+
# Path to your ITCH 5.0 data file
|
90
|
+
itch_file_path = 'path/to/your/data'
|
91
|
+
# you can find sample data [here](https://emi.nasdaq.com/ITCH/Nasdaq%20ITCH/)
|
92
|
+
|
93
|
+
try:
|
94
|
+
with open(itch_file_path, 'rb') as itch_file:
|
95
|
+
# read_message_from_file returns a list of parsed message objects
|
96
|
+
parsed_messages = parser.read_message_from_file(itch_file)
|
97
|
+
|
98
|
+
print(f"Parsed {len(parsed_messages)} messages.")
|
99
|
+
|
100
|
+
# Process the messages
|
101
|
+
for message in parsed_messages:
|
102
|
+
# Access attributes directly
|
103
|
+
print(f"Type: {message.message_type.decode()}, Timestamp: {message.timestamp}")
|
104
|
+
|
105
|
+
if isinstance(message, AddOrderMessage):
|
106
|
+
print(f" Add Order: Ref={message.order_reference_number}, "
|
107
|
+
f"Side={message.buy_sell_indicator.decode()}, "
|
108
|
+
f"Shares={message.shares}, Stock={message.stock.decode().strip()}, "
|
109
|
+
f"Price={message.decode_price('price')}")
|
110
|
+
|
111
|
+
elif isinstance(message, TradeMessage):
|
112
|
+
print(f" Trade: Match={message.match_number}")
|
113
|
+
# Access specific trade type attributes...
|
114
|
+
|
115
|
+
# Get a human-readable dataclass representation
|
116
|
+
decoded_msg = message.decode()
|
117
|
+
print(f" Decoded: {decoded_msg}")
|
118
|
+
|
119
|
+
except FileNotFoundError:
|
120
|
+
print(f"Error: File not found at {itch_file_path}")
|
121
|
+
except Exception as e:
|
122
|
+
print(f"An error occurred: {e}")
|
123
|
+
|
124
|
+
```
|
125
|
+
|
126
|
+
### Parsing from Raw Bytes
|
127
|
+
|
128
|
+
This is suitable for real-time processing, such as reading from a network stream.
|
129
|
+
|
130
|
+
```python
|
131
|
+
from itch import MessageParser
|
132
|
+
from itch.messages import AddOrderMessage
|
133
|
+
from queue import Queue
|
134
|
+
|
135
|
+
# Initialize the parser
|
136
|
+
parser = MessageParser()
|
137
|
+
|
138
|
+
# Simulate receiving a chunk of binary data (e.g., from a network socket)
|
139
|
+
# This chunk contains multiple ITCH messages, each prefixed with 0x00 and length byte
|
140
|
+
# Example: \x00\x0bS...\x00\x25R...\x00\x27F...
|
141
|
+
raw_binary_data: bytes = b"..." # Your raw ITCH 5.0 data chunk
|
142
|
+
|
143
|
+
# read_message_from_bytes returns a queue of parsed message objects
|
144
|
+
message_queue: Queue = parser.read_message_from_bytes(raw_binary_data)
|
145
|
+
|
146
|
+
print(f"Parsed {message_queue.qsize()} messages from the byte chunk.")
|
147
|
+
|
148
|
+
# Process messages from the queue
|
149
|
+
while not message_queue.empty():
|
150
|
+
message = message_queue.get()
|
151
|
+
|
152
|
+
print(f"Type: {message.message_type.decode()}, Timestamp: {message.timestamp}")
|
153
|
+
|
154
|
+
if isinstance(message, AddOrderMessage):
|
155
|
+
print(f" Add Order: Ref={message.order_reference_number}, "
|
156
|
+
f"Stock={message.stock.decode().strip()}, Price={message.decode_price('price')}")
|
157
|
+
|
158
|
+
# Use the decoded representation
|
159
|
+
decoded_msg = message.decode(prefix="Decoded")
|
160
|
+
print(f" Decoded: {decoded_msg}")
|
161
|
+
|
162
|
+
```
|
163
|
+
|
164
|
+
## Supported Message Types
|
165
|
+
|
166
|
+
The parser supports the following ITCH 5.0 message types. Each message object has attributes corresponding to the fields defined in the specification. Refer to the class docstrings in `itch.messages` for detailed attribute descriptions.
|
167
|
+
|
168
|
+
| Type (Byte) | Class Name | Description |
|
169
|
+
| :---------- | :-------------------------------- | :----------------------------------------------- |
|
170
|
+
| `S` | `SystemEventMessage` | System Event Message |
|
171
|
+
| `R` | `StockDirectoryMessage` | Stock Directory Message |
|
172
|
+
| `H` | `StockTradingActionMessage` | Stock Trading Action Message |
|
173
|
+
| `Y` | `RegSHOMessage` | Reg SHO Short Sale Price Test Restricted Indicator |
|
174
|
+
| `L` | `MarketParticipantPositionMessage`| Market Participant Position message |
|
175
|
+
| `V` | `MWCBDeclineLeveMessage` | Market-Wide Circuit Breaker (MWCB) Decline Level |
|
176
|
+
| `W` | `MWCBStatusMessage` | Market-Wide Circuit Breaker (MWCB) Status |
|
177
|
+
| `K` | `IPOQuotingPeriodUpdateMessage` | IPO Quoting Period Update Message |
|
178
|
+
| `J` | `LULDAuctionCollarMessage` | LULD Auction Collar Message |
|
179
|
+
| `h` | `OperationalHaltMessage` | Operational Halt Message |
|
180
|
+
| `A` | `AddOrderNoMPIAttributionMessage` | Add Order (No MPID Attribution) |
|
181
|
+
| `F` | `AddOrderMPIDAttribution` | Add Order (MPID Attribution) |
|
182
|
+
| `E` | `OrderExecutedMessage` | Order Executed Message |
|
183
|
+
| `C` | `OrderExecutedWithPriceMessage` | Order Executed With Price Message |
|
184
|
+
| `X` | `OrderCancelMessage` | Order Cancel Message |
|
185
|
+
| `D` | `OrderDeleteMessage` | Order Delete Message |
|
186
|
+
| `U` | `OrderReplaceMessage` | Order Replace Message |
|
187
|
+
| `P` | `NonCrossTradeMessage` | Trade Message (Non-Cross) |
|
188
|
+
| `Q` | `CrossTradeMessage` | Cross Trade Message |
|
189
|
+
| `B` | `BrokenTradeMessage` | Broken Trade / Order Execution Message |
|
190
|
+
| `I` | `NOIIMessage` | Net Order Imbalance Indicator (NOII) Message |
|
191
|
+
| `N` | `RetailPriceImprovementIndicator` | Retail Price Improvement Indicator (RPII) |
|
192
|
+
| `O` | `DLCRMessage` | Direct Listing with Capital Raise Message |
|
193
|
+
|
194
|
+
## Data Representation
|
195
|
+
|
196
|
+
* **Base Class:** All message classes inherit from `itch.messages.MarketMessage`. This base class provides common attributes like `message_type`, `description`, `stock_locate`, `tracking_number`, and `timestamp`.
|
197
|
+
* **Timestamp:** Timestamps are stored as 64-bit integers representing nanoseconds since midnight. The `set_timestamp` and `split_timestamp` methods handle the conversion from/to the 6-byte representation used in the raw messages.
|
198
|
+
* **Prices:** Price fields (e.g., `price`, `execution_price`, `level1_price`) are stored as integers in the raw message objects. Use the `message.decode_price('attribute_name')` method to get the correctly scaled floating-point value (usually 4 or 8 decimal places, defined by `message.price_precision`).
|
199
|
+
* **Strings:** Alpha fields are stored as `bytes`. The `.decode()` method converts these to ASCII strings and removes right-padding spaces.
|
200
|
+
* **Decoded Objects:** The `message.decode()` method returns a standard Python `dataclass` instance. This provides a clean, immutable, and easily inspectable representation of the message content with correct data types (float for prices, string for text).
|
201
|
+
|
202
|
+
## Contributing
|
203
|
+
|
204
|
+
Contributions are welcome! If you find a bug, have a suggestion, or want to add a feature:
|
205
|
+
|
206
|
+
1. **Check Issues:** See if an issue for your topic already exists.
|
207
|
+
2. **Open an Issue:** If not, open a new issue describing the bug or feature request.
|
208
|
+
3. **Fork and Branch:** Fork the repository and create a new branch for your changes.
|
209
|
+
4. **Implement Changes:** Make your code changes, ensuring adherence to the ITCH 5.0 specification. Add tests if applicable.
|
210
|
+
5. **Submit Pull Request:** Open a pull request from your branch to the main repository, referencing the relevant issue.
|
211
|
+
|
212
|
+
## License
|
213
|
+
|
214
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
215
|
+
|
216
|
+
## References
|
217
|
+
* **Nasdaq TotalView-ITCH 5.0 Specification:** The official [documentation](https://www.nasdaqtrader.com/content/technicalsupport/specifications/dataproducts/NQTVITCHspecification.pdf) is the definitive source for protocol details.
|
itchfeed-1.0.0/README.md
ADDED
@@ -0,0 +1,183 @@
|
|
1
|
+
# Nasdaq TotalView-ITCH 5.0 Parser
|
2
|
+
|
3
|
+
[](https://opensource.org/licenses/MIT) <!-- Choose your license -->
|
4
|
+
|
5
|
+
A Python library for parsing binary data conforming to the Nasdaq TotalView-ITCH 5.0 protocol specification. This parser converts the raw byte stream into structured Python objects, making it easier to work with Nasdaq market data.
|
6
|
+
|
7
|
+
## Overview
|
8
|
+
|
9
|
+
The Nasdaq TotalView-ITCH 5.0 protocol is a binary protocol used by Nasdaq to disseminate full order book depth, trade information, and system events for equities traded on its execution system. This parser handles the low-level details of reading the binary format, unpacking fields according to the specification, and presenting the data as intuitive Python objects.
|
10
|
+
|
11
|
+
## Features
|
12
|
+
|
13
|
+
* **Parses ITCH 5.0 Binary Data:** Accurately interprets the binary message structures defined in the official specification.
|
14
|
+
* **Supports All Standard Message Types:** Implements classes for all messages defined in the ITCH 5.0 specification (System Event, Stock Directory, Add Order, Trade, etc.).
|
15
|
+
* **Object-Oriented Representation:** Each ITCH message type is represented by a dedicated Python class (`SystemEventMessage`, `AddOrderMessage`, etc.), inheriting from a common `MarketMessage` base class.
|
16
|
+
* **Flexible Input:** Reads and parses messages from:
|
17
|
+
* Binary files (`.gz` or similar).
|
18
|
+
* Raw byte streams (e.g., from network sockets).
|
19
|
+
* **Data Decoding:** Provides a `.decode()` method on each message object to convert it into a human-readable `dataclass` representation, handling:
|
20
|
+
* Byte-to-string conversion (ASCII).
|
21
|
+
* Stripping padding spaces.
|
22
|
+
* Price decoding based on defined precision.
|
23
|
+
* **Timestamp Handling:** Correctly reconstructs the 6-byte (48-bit) nanosecond timestamps.
|
24
|
+
* **Price Handling:** Decodes fixed-point price fields into floating-point numbers based on the standard 4 or 8 decimal place precision.
|
25
|
+
* **Pure Python:** Relies only on the Python standard library . No external dependencies required.
|
26
|
+
|
27
|
+
## Installation
|
28
|
+
|
29
|
+
You can install this project using ``pip``
|
30
|
+
|
31
|
+
1. **Clone the repository (or download the source code):**
|
32
|
+
```bash
|
33
|
+
pip install itch
|
34
|
+
```
|
35
|
+
2. **Import the necessary modules** directly into your Python project:
|
36
|
+
```python
|
37
|
+
from itch.parser import MessageParser
|
38
|
+
from itch.messages import ModifyOrderMessage
|
39
|
+
```
|
40
|
+
|
41
|
+
## Usage
|
42
|
+
|
43
|
+
### Parsing from a Binary File
|
44
|
+
|
45
|
+
This is useful for processing historical ITCH data stored in files. The `MessageParser` handles buffering efficiently.
|
46
|
+
|
47
|
+
```python
|
48
|
+
from itch import MessageParser
|
49
|
+
from itch.messages import AddOrderMessage, TradeMessage
|
50
|
+
|
51
|
+
# Initialize the parser. Optionally filter messages by type.
|
52
|
+
# parser = MessageParser(message_type=b"AP") # Only parse AddOrder and NonCrossTrade messages
|
53
|
+
parser = MessageParser()
|
54
|
+
|
55
|
+
# Path to your ITCH 5.0 data file
|
56
|
+
itch_file_path = 'path/to/your/data'
|
57
|
+
# you can find sample data [here](https://emi.nasdaq.com/ITCH/Nasdaq%20ITCH/)
|
58
|
+
|
59
|
+
try:
|
60
|
+
with open(itch_file_path, 'rb') as itch_file:
|
61
|
+
# read_message_from_file returns a list of parsed message objects
|
62
|
+
parsed_messages = parser.read_message_from_file(itch_file)
|
63
|
+
|
64
|
+
print(f"Parsed {len(parsed_messages)} messages.")
|
65
|
+
|
66
|
+
# Process the messages
|
67
|
+
for message in parsed_messages:
|
68
|
+
# Access attributes directly
|
69
|
+
print(f"Type: {message.message_type.decode()}, Timestamp: {message.timestamp}")
|
70
|
+
|
71
|
+
if isinstance(message, AddOrderMessage):
|
72
|
+
print(f" Add Order: Ref={message.order_reference_number}, "
|
73
|
+
f"Side={message.buy_sell_indicator.decode()}, "
|
74
|
+
f"Shares={message.shares}, Stock={message.stock.decode().strip()}, "
|
75
|
+
f"Price={message.decode_price('price')}")
|
76
|
+
|
77
|
+
elif isinstance(message, TradeMessage):
|
78
|
+
print(f" Trade: Match={message.match_number}")
|
79
|
+
# Access specific trade type attributes...
|
80
|
+
|
81
|
+
# Get a human-readable dataclass representation
|
82
|
+
decoded_msg = message.decode()
|
83
|
+
print(f" Decoded: {decoded_msg}")
|
84
|
+
|
85
|
+
except FileNotFoundError:
|
86
|
+
print(f"Error: File not found at {itch_file_path}")
|
87
|
+
except Exception as e:
|
88
|
+
print(f"An error occurred: {e}")
|
89
|
+
|
90
|
+
```
|
91
|
+
|
92
|
+
### Parsing from Raw Bytes
|
93
|
+
|
94
|
+
This is suitable for real-time processing, such as reading from a network stream.
|
95
|
+
|
96
|
+
```python
|
97
|
+
from itch import MessageParser
|
98
|
+
from itch.messages import AddOrderMessage
|
99
|
+
from queue import Queue
|
100
|
+
|
101
|
+
# Initialize the parser
|
102
|
+
parser = MessageParser()
|
103
|
+
|
104
|
+
# Simulate receiving a chunk of binary data (e.g., from a network socket)
|
105
|
+
# This chunk contains multiple ITCH messages, each prefixed with 0x00 and length byte
|
106
|
+
# Example: \x00\x0bS...\x00\x25R...\x00\x27F...
|
107
|
+
raw_binary_data: bytes = b"..." # Your raw ITCH 5.0 data chunk
|
108
|
+
|
109
|
+
# read_message_from_bytes returns a queue of parsed message objects
|
110
|
+
message_queue: Queue = parser.read_message_from_bytes(raw_binary_data)
|
111
|
+
|
112
|
+
print(f"Parsed {message_queue.qsize()} messages from the byte chunk.")
|
113
|
+
|
114
|
+
# Process messages from the queue
|
115
|
+
while not message_queue.empty():
|
116
|
+
message = message_queue.get()
|
117
|
+
|
118
|
+
print(f"Type: {message.message_type.decode()}, Timestamp: {message.timestamp}")
|
119
|
+
|
120
|
+
if isinstance(message, AddOrderMessage):
|
121
|
+
print(f" Add Order: Ref={message.order_reference_number}, "
|
122
|
+
f"Stock={message.stock.decode().strip()}, Price={message.decode_price('price')}")
|
123
|
+
|
124
|
+
# Use the decoded representation
|
125
|
+
decoded_msg = message.decode(prefix="Decoded")
|
126
|
+
print(f" Decoded: {decoded_msg}")
|
127
|
+
|
128
|
+
```
|
129
|
+
|
130
|
+
## Supported Message Types
|
131
|
+
|
132
|
+
The parser supports the following ITCH 5.0 message types. Each message object has attributes corresponding to the fields defined in the specification. Refer to the class docstrings in `itch.messages` for detailed attribute descriptions.
|
133
|
+
|
134
|
+
| Type (Byte) | Class Name | Description |
|
135
|
+
| :---------- | :-------------------------------- | :----------------------------------------------- |
|
136
|
+
| `S` | `SystemEventMessage` | System Event Message |
|
137
|
+
| `R` | `StockDirectoryMessage` | Stock Directory Message |
|
138
|
+
| `H` | `StockTradingActionMessage` | Stock Trading Action Message |
|
139
|
+
| `Y` | `RegSHOMessage` | Reg SHO Short Sale Price Test Restricted Indicator |
|
140
|
+
| `L` | `MarketParticipantPositionMessage`| Market Participant Position message |
|
141
|
+
| `V` | `MWCBDeclineLeveMessage` | Market-Wide Circuit Breaker (MWCB) Decline Level |
|
142
|
+
| `W` | `MWCBStatusMessage` | Market-Wide Circuit Breaker (MWCB) Status |
|
143
|
+
| `K` | `IPOQuotingPeriodUpdateMessage` | IPO Quoting Period Update Message |
|
144
|
+
| `J` | `LULDAuctionCollarMessage` | LULD Auction Collar Message |
|
145
|
+
| `h` | `OperationalHaltMessage` | Operational Halt Message |
|
146
|
+
| `A` | `AddOrderNoMPIAttributionMessage` | Add Order (No MPID Attribution) |
|
147
|
+
| `F` | `AddOrderMPIDAttribution` | Add Order (MPID Attribution) |
|
148
|
+
| `E` | `OrderExecutedMessage` | Order Executed Message |
|
149
|
+
| `C` | `OrderExecutedWithPriceMessage` | Order Executed With Price Message |
|
150
|
+
| `X` | `OrderCancelMessage` | Order Cancel Message |
|
151
|
+
| `D` | `OrderDeleteMessage` | Order Delete Message |
|
152
|
+
| `U` | `OrderReplaceMessage` | Order Replace Message |
|
153
|
+
| `P` | `NonCrossTradeMessage` | Trade Message (Non-Cross) |
|
154
|
+
| `Q` | `CrossTradeMessage` | Cross Trade Message |
|
155
|
+
| `B` | `BrokenTradeMessage` | Broken Trade / Order Execution Message |
|
156
|
+
| `I` | `NOIIMessage` | Net Order Imbalance Indicator (NOII) Message |
|
157
|
+
| `N` | `RetailPriceImprovementIndicator` | Retail Price Improvement Indicator (RPII) |
|
158
|
+
| `O` | `DLCRMessage` | Direct Listing with Capital Raise Message |
|
159
|
+
|
160
|
+
## Data Representation
|
161
|
+
|
162
|
+
* **Base Class:** All message classes inherit from `itch.messages.MarketMessage`. This base class provides common attributes like `message_type`, `description`, `stock_locate`, `tracking_number`, and `timestamp`.
|
163
|
+
* **Timestamp:** Timestamps are stored as 64-bit integers representing nanoseconds since midnight. The `set_timestamp` and `split_timestamp` methods handle the conversion from/to the 6-byte representation used in the raw messages.
|
164
|
+
* **Prices:** Price fields (e.g., `price`, `execution_price`, `level1_price`) are stored as integers in the raw message objects. Use the `message.decode_price('attribute_name')` method to get the correctly scaled floating-point value (usually 4 or 8 decimal places, defined by `message.price_precision`).
|
165
|
+
* **Strings:** Alpha fields are stored as `bytes`. The `.decode()` method converts these to ASCII strings and removes right-padding spaces.
|
166
|
+
* **Decoded Objects:** The `message.decode()` method returns a standard Python `dataclass` instance. This provides a clean, immutable, and easily inspectable representation of the message content with correct data types (float for prices, string for text).
|
167
|
+
|
168
|
+
## Contributing
|
169
|
+
|
170
|
+
Contributions are welcome! If you find a bug, have a suggestion, or want to add a feature:
|
171
|
+
|
172
|
+
1. **Check Issues:** See if an issue for your topic already exists.
|
173
|
+
2. **Open an Issue:** If not, open a new issue describing the bug or feature request.
|
174
|
+
3. **Fork and Branch:** Fork the repository and create a new branch for your changes.
|
175
|
+
4. **Implement Changes:** Make your code changes, ensuring adherence to the ITCH 5.0 specification. Add tests if applicable.
|
176
|
+
5. **Submit Pull Request:** Open a pull request from your branch to the main repository, referencing the relevant issue.
|
177
|
+
|
178
|
+
## License
|
179
|
+
|
180
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
181
|
+
|
182
|
+
## References
|
183
|
+
* **Nasdaq TotalView-ITCH 5.0 Specification:** The official [documentation](https://www.nasdaqtrader.com/content/technicalsupport/specifications/dataproducts/NQTVITCHspecification.pdf) is the definitive source for protocol details.
|
@@ -0,0 +1,14 @@
|
|
1
|
+
"""
|
2
|
+
Nasdaq TotalView-ITCH 5.0 Parser
|
3
|
+
================================
|
4
|
+
"""
|
5
|
+
|
6
|
+
__author__ = "Bertin Balouki SIMYELI"
|
7
|
+
__copyright__ = "2025 Bertin Balouki SIMYELI"
|
8
|
+
__email__ = "bertin@bbstrader.com"
|
9
|
+
__license__ = "MIT"
|
10
|
+
__version__ = "1.0.0"
|
11
|
+
|
12
|
+
|
13
|
+
from itch.messages import * # noqa: F403
|
14
|
+
from itch.parser import MessageParser # noqa: F401
|
@@ -0,0 +1,206 @@
|
|
1
|
+
SYSTEM_EVENT_CODES = {
|
2
|
+
b"O": "Start of Messages",
|
3
|
+
b"S": "Start of System hours",
|
4
|
+
b"Q": "Start of Market hours",
|
5
|
+
b"M": "End of Market hours",
|
6
|
+
b"E": "End of System hours",
|
7
|
+
b"C": "End of Messages",
|
8
|
+
}
|
9
|
+
|
10
|
+
|
11
|
+
MARKET_CATEGORY = {
|
12
|
+
b"N": "NYSE",
|
13
|
+
b"A": "AMEX",
|
14
|
+
b"P": "Arca",
|
15
|
+
b"Q": "NASDAQ Global Select",
|
16
|
+
b"G": "NASDAQ Global Market",
|
17
|
+
b"S": "NASDAQ Capital Market",
|
18
|
+
b"Z": "BATS",
|
19
|
+
b"V": "Investors Exchange",
|
20
|
+
b" ": "Not available",
|
21
|
+
}
|
22
|
+
|
23
|
+
|
24
|
+
FINANCIAL_STATUS_INDICATOR = {
|
25
|
+
b"D": "Deficient",
|
26
|
+
b"E": "Delinquent",
|
27
|
+
b"Q": "Bankrupt",
|
28
|
+
b"S": "Suspended",
|
29
|
+
b"G": "Deficient and Bankrupt",
|
30
|
+
b"H": "Deficient and Delinquent",
|
31
|
+
b"J": "Delinquent and Bankrupt",
|
32
|
+
b"K": "Deficient, Delinquent and Bankrupt",
|
33
|
+
b"C": "Creations and/or Redemptions Suspended for Exchange Traded Product",
|
34
|
+
b"N": "Normal (Default): Issuer is NOT Deficient, Delinquent, or Bankrupt",
|
35
|
+
b" ": "Not available. Firms should refer to SIAC feeds for code if needed",
|
36
|
+
}
|
37
|
+
|
38
|
+
|
39
|
+
ISSUE_CLASSIFICATION_VALUES = {
|
40
|
+
b"A": "American Depositary Share",
|
41
|
+
b"B": "Bond",
|
42
|
+
b"C": "Common Stock",
|
43
|
+
b"F": "Depository Receipt",
|
44
|
+
b"I": "144A",
|
45
|
+
b"L": "Limited Partnership",
|
46
|
+
b"N": "Notes",
|
47
|
+
b"O": "Ordinary Share",
|
48
|
+
b"P": "Preferred Stock",
|
49
|
+
b"Q": "Other Securities",
|
50
|
+
b"R": "Right",
|
51
|
+
b"S": "Shares of Beneficial Interest",
|
52
|
+
b"T": "Convertible Debenture",
|
53
|
+
b"U": "Unit",
|
54
|
+
b"V": "Units/Beneficial Interest",
|
55
|
+
b"W": "Warrant",
|
56
|
+
}
|
57
|
+
|
58
|
+
|
59
|
+
ISSUE_SUB_TYPE_VALUES = {
|
60
|
+
b"A": "Preferred Trust Securities",
|
61
|
+
b"AI": "Alpha Index ETNs",
|
62
|
+
b"B": "Index Based Derivative",
|
63
|
+
b"C": "Common Shares",
|
64
|
+
b"CB": "Commodity Based Trust Shares",
|
65
|
+
b"CF": "Commodity Futures Trust Shares",
|
66
|
+
b"CL": "Commodity-Linked Securities",
|
67
|
+
b"CM": "Commodity Index Trust Shares",
|
68
|
+
b"CO": "Collateralized Mortgage Obligation",
|
69
|
+
b"CT": "Currency Trust Shares",
|
70
|
+
b"CU": "Commodity-Currency-Linked Securities",
|
71
|
+
b"CW": "Currency Warrants",
|
72
|
+
b"D": "Global Depositary Shares",
|
73
|
+
b"E": "ETF-Portfolio Depositary Receipt",
|
74
|
+
b"EG": "Equity Gold Shares",
|
75
|
+
b"EI": "ETN-Equity Index-Linked Securities",
|
76
|
+
b"EM": "NextShares Exchange Traded Managed Fund*",
|
77
|
+
b"EN": "Exchange Traded Notes",
|
78
|
+
b"EU": "Equity Units",
|
79
|
+
b"F": "HOLDRS",
|
80
|
+
b"FI": "ETN-Fixed Income-Linked Securities",
|
81
|
+
b"FL": "ETN-Futures-Linked Securities",
|
82
|
+
b"G": "Global Shares",
|
83
|
+
b"I": "ETF-Index Fund Shares",
|
84
|
+
b"IR": "Interest Rate",
|
85
|
+
b"IW": "Index Warrant",
|
86
|
+
b"IX": "Index-Linked Exchangeable Notes",
|
87
|
+
b"J": "Corporate Backed Trust Security",
|
88
|
+
b"L": "Contingent Litigation Right",
|
89
|
+
b"LL": "Limited Liability Company (LLC)",
|
90
|
+
b"M": "Equity-Based Derivative",
|
91
|
+
b"MF": "Managed Fund Shares",
|
92
|
+
b"ML": "ETN-Multi-Factor Index-Linked Securities",
|
93
|
+
b"MT": "Managed Trust Securities",
|
94
|
+
b"N": "NY Registry Shares",
|
95
|
+
b"O": "Open Ended Mutual Fund",
|
96
|
+
b"P": "Privately Held Security",
|
97
|
+
b"PP": "Poison Pill",
|
98
|
+
b"PU": "Partnership Units",
|
99
|
+
b"Q": "Closed-End Funds",
|
100
|
+
b"R": "Reg-S",
|
101
|
+
b"RC": "Commodity-Redeemable Commodity-Linked Securities",
|
102
|
+
b"RF": "ETN-Redeemable Futures-Linked Securities",
|
103
|
+
b"RT": "REIT",
|
104
|
+
b"RU": "Commodity-Redeemable Currency-Linked Securities",
|
105
|
+
b"S": "SEED",
|
106
|
+
b"SC": "Spot Rate Closing",
|
107
|
+
b"SI": "Spot Rate Intraday",
|
108
|
+
b"T": "Tracking Stock",
|
109
|
+
b"TC": "Trust Certificates",
|
110
|
+
b"TU": "Trust Units",
|
111
|
+
b"U": "Portal",
|
112
|
+
b"V": "Contingent Value Right",
|
113
|
+
b"W": "Trust Issued Receipts",
|
114
|
+
b"WC": "World Currency Option",
|
115
|
+
b"X": "Trust",
|
116
|
+
b"Y": "Other",
|
117
|
+
b"Z": "Not Applicable",
|
118
|
+
}
|
119
|
+
|
120
|
+
|
121
|
+
TRADING_STATES = {
|
122
|
+
b"H": "Halted across all U.S. equity markets / SROs",
|
123
|
+
b"P": "Paused across all U.S. equity markets / SROs",
|
124
|
+
b"Q": "Quotation only period for cross-SRO halt or pause",
|
125
|
+
b"T": "Trading on NASDAQ",
|
126
|
+
}
|
127
|
+
|
128
|
+
|
129
|
+
TRADING_ACTION_REASON_CODES = {
|
130
|
+
b"T1": "Halt News Pending",
|
131
|
+
b"T2": "Halt News Disseminated",
|
132
|
+
b"T3": "News and Resumption Times",
|
133
|
+
b"T5": "Single Security Trading Pause In Effect",
|
134
|
+
b"T6": "Regulatory Halt - Extraordinary Market Activity",
|
135
|
+
b"T7": "Single Security Trading Pause / Quotation Only Period",
|
136
|
+
b"T8": "Halt ETF",
|
137
|
+
b"T12": "Trading Halted; For Information Requested by Listing Market",
|
138
|
+
b"H4": "Halt Non-Compliance",
|
139
|
+
b"H9": "Halt Filings Not Current",
|
140
|
+
b"H10": "Halt SEC Trading Suspension",
|
141
|
+
b"H11": "Halt Regulatory Concern",
|
142
|
+
b"O1": "Operations Halt; Contact Market Operations",
|
143
|
+
b"LUDP": "Volatility Trading Pause",
|
144
|
+
b"LUDS": "Volatility Trading Pause - Straddle Condition",
|
145
|
+
b"MWC0": "Market Wide Circuit Breaker Halt - Carry over from previous day",
|
146
|
+
b"MWC1": "Market Wide Circuit Breaker Halt - Level 1",
|
147
|
+
b"MWC2": "Market Wide Circuit Breaker Halt - Level 2",
|
148
|
+
b"MWC3": "Market Wide Circuit Breaker Halt - Level 3",
|
149
|
+
b"MWCQ": "Market Wide Circuit Breaker Resumption",
|
150
|
+
b"IPO1": "IPO Issue Not Yet Trading",
|
151
|
+
b"IPOQ": "IPO Security Released for Quotation (Nasdaq Securities Only)",
|
152
|
+
b"IPOE": "IPO Security — Positioning Window Extension (Nasdaq Securities Only)",
|
153
|
+
b"M1": "Corporate Action",
|
154
|
+
b"M2": "Quotation Not Available",
|
155
|
+
b"R1": "New Issue Available",
|
156
|
+
b"R2": "Issue Available",
|
157
|
+
b"R4": "Qualifications Issues Reviewed/Resolved; Quotations/Trading to Resume",
|
158
|
+
b"R9": "Filing Requirements Satisfied/Resolved; Quotations/Trading To Resume",
|
159
|
+
b"C3": "Issuer News Not Forthcoming; Quotations/Trading To Resume",
|
160
|
+
b"C4": "Qualifications Halt Ended; Maintenance Requirements Met; Resume",
|
161
|
+
b"C9": "Qualifications Halt Concluded; Filings Met; Quotes/Trades To Resume",
|
162
|
+
b"C11": "Trade Halt Concluded By Other Regulatory Authority; Quotes/Trades Resume",
|
163
|
+
b" ": "Reason Not Available",
|
164
|
+
}
|
165
|
+
|
166
|
+
|
167
|
+
PRIMARY_MARKET_MAKER = {
|
168
|
+
b"Y": "Primary market maker",
|
169
|
+
b"N": "Non-primary market maker",
|
170
|
+
}
|
171
|
+
|
172
|
+
|
173
|
+
MARKET_MAKER_MODE = {
|
174
|
+
b"N": "Normal",
|
175
|
+
b"P": "Passive",
|
176
|
+
b"S": "Syndicate",
|
177
|
+
b"R": "Pre-syndicate",
|
178
|
+
b"L": "Penalty",
|
179
|
+
}
|
180
|
+
|
181
|
+
|
182
|
+
MARKET_PARTICIPANT_STATE = {
|
183
|
+
b"A": "Active",
|
184
|
+
b"E": "Excused",
|
185
|
+
b"W": "Withdrawn",
|
186
|
+
b"S": "Suspended",
|
187
|
+
b"D": "Deleted",
|
188
|
+
}
|
189
|
+
|
190
|
+
|
191
|
+
PRICE_VARIATION_INDICATOR = {
|
192
|
+
b"L": "Less than 1%",
|
193
|
+
b"1": "1 to 1.99%",
|
194
|
+
b"2": "2 to 2.99%",
|
195
|
+
b"3": "3 to 3.99%",
|
196
|
+
b"4": "4 to 4.99%",
|
197
|
+
b"5": "5 to 5.99%",
|
198
|
+
b"6": "6 to 6.99%",
|
199
|
+
b"7": "7 to 7.99%",
|
200
|
+
b"8": "8 to 8.99%",
|
201
|
+
b"9": "9 to 9.99%",
|
202
|
+
b"A": "10 to 19.99%",
|
203
|
+
b"B": "20 to 29.99%",
|
204
|
+
b"C": "30% or greater",
|
205
|
+
b" ": "Cannot be calculated",
|
206
|
+
}
|