itch5
A fast, zero-copy parser for the Nasdaq TotalView-ITCH 5.0 binary protocol.
ITCH 5.0 is Nasdaq's real-time market data feed. It carries every order book event — adds, cancels, executes, replaces — plus market-wide events, trading halts, and cross-trade notifications, all encoded as compact fixed-length binary messages framed with a 2-byte big-endian length prefix.
Usage
Add the crate to your Cargo.toml:
[]
= "0.1"
Implement [MessageHandler] for the message types you care about, then feed bytes to [Parser]:
use ControlFlow;
use ;
Return ControlFlow::Break(()) from any handler method to stop parsing early.
Core API
Parser
new
Iterates over every framed message in buf, dispatching each one to the corresponding method on handler. The buffer is borrowed for the lifetime of the parser; no heap allocation occurs.
parse_one
parse_one
Parses a single length-prefixed message. Returns (body, remainder) where body starts with the one-byte message-type tag. Useful when you need the raw bytes rather than typed structs — for example, to forward messages to another consumer.
MessageHandler
A visitor trait with one method per message type. Every method has a default no-op implementation, so you only override what you need:
ParseError
Message Types
All 23 ITCH 5.0 message types are covered:
| Tag | Struct | Description |
|---|---|---|
S |
SystemEventMessage |
Market/session lifecycle events |
R |
StockDirectory |
Daily instrument reference data |
H |
StockTradingAction |
Trading halt and resume |
Y |
RegSHORestriction |
Regulation SHO short-sale restriction |
L |
MarketParticipantPosition |
Market maker status and mode |
V |
MWCBDeclineLevelMessage |
Market-wide circuit breaker levels |
W |
MWCBStatusMessage |
Market-wide circuit breaker status |
K |
QuotingPeriodUpdate |
IPO quotation release |
J |
LULDAuctionCollar |
Limit Up/Limit Down auction collar |
h |
OperationalHalt |
Exchange-specific operational halt |
A |
AddOrderNoMPIDAttribution |
New order (anonymous) |
F |
AddOrderWithMPIDAttribution |
New order (attributed) |
E |
OrderExecutedMessage |
Order execution |
C |
OrderExecutedWithPriceMessage |
Order execution at non-display price |
X |
OrderCancelMessage |
Partial order cancellation |
D |
OrderDeleteMessage |
Full order removal |
U |
OrderReplaceMessage |
Cancel-and-replace |
P |
TradeMessage |
Non-displayed trade |
Q |
CrossTradeMessage |
Opening/closing/halt cross execution |
B |
BrokenTradeMessage |
Trade break |
I |
NetOrderImbalanceIndicatorMessage |
Cross imbalance data |
N |
RetailPriceImprovementIndicator |
Retail interest flags |
O |
DirectListingwithCapitalRaisePriceDiscoveryMessage |
Direct listing price discovery |
Price Types
Prices in the ITCH protocol are fixed-point integers. The crate provides two newtype wrappers:
| Type | Bytes | Precision | into_f64() divisor |
|---|---|---|---|
Price4 |
4 | 4 decimal places | 10,000 |
Price8 |
8 | 8 decimal places | 100,000,000 |
let price: Price4 = msg.price;
println!; // e.g. "123.4500"
println!; // raw integer value
Symbol
Symbol is an 8-byte ASCII stock ticker, space-padded on the right per the ITCH specification.
let sym: Symbol = msg.stock;
println!; // e.g. "AAPL " trimmed to "AAPL"
// Parse from a string
let sym: Symbol = "MSFT".parse.unwrap;
// Compact hash/unhash for use as a map key
let key: u64 = sym.hash;
let restored: Symbol = from_hash;
Wire Format
Each ITCH message is framed as:
[2 bytes: big-endian message length][message body]
The message body begins with a single ASCII tag byte that identifies the message type, followed by fixed-width fields in network byte order (big-endian). All message structs are #[repr(C, packed)] and implement zerocopy::FromBytes, so parsing is a bounds-checked pointer cast with no copying.
Examples
Count every trade in an ITCH binary file:
cargo run --example parse_file -- /path/to/feed.itch
The source is in examples/parse_file.rs. It memory-maps the file and counts TradeMessage events.
Benchmarks
ITCH5_BENCH_1M_FILE=/path/to/1M-message.itch cargo bench
The benchmark (in benches/itch_bench.rs) reports throughput in messages/second and bytes/second using Criterion.
License
Unlicense — public domain.