Python wrapper for a high-performance Rust orderbook CLI
Project description
hft-lob
hft-lob is a Python library that wraps a high-performance Rust binary to read and decode NSE (National Stock Exchange) binary market feed files and reconstruct a Limit Order Book (LOB) for any instrument token. It gives you a clean Python API — no need to understand the binary format, no C extensions, no complex setup.
Features
| # | Feature | Description |
|---|---|---|
| 1 | get_all_messages | Load all LOB messages at once into a Python list |
| 2 | get_next_message | Stream messages one at a time using a cursor |
| 3 | is_end_of_file | Check whether all messages have been read |
Installation
pip install hft-lob
Requirements:
- Linux x86_64
- Python >= 3.7
- No additional dependencies
Quick Start
from hft_lob.cli import Reader
# Step 1: Create a Reader with your file and token
reader = Reader("/path/to/feed.bin", tokens=1333)
# Step 2: Use any of the three features
messages = reader.get_all_messages() # Feature 1
msg = reader.get_next_message() # Feature 2
done = reader.is_end_of_file() # Feature 3
Feature Details
1. get_all_messages
What it does: Runs the Rust binary once, loads every LOB message from the file into memory, and returns them all as a Python list. Best when you want to process the entire dataset at once.
from hft_lob.cli import Reader
reader = Reader("/path/to/feed.bin", tokens=1333)
messages = reader.get_all_messages()
print(f"Total messages: {len(messages)}") # e.g. 493000
print(f"Header: {reader.header}") # column names
print(f"First row: {messages[0]}") # first CSV row
print(f"Last row: {messages[-1]}") # last CSV row
Returns: list[str] — each item is one full CSV row of LOB data
After calling: is_end_of_file() becomes True
2. get_next_message
What it does: Returns one message at a time, advancing an internal cursor on each call. Returns None when there are no more messages. Best when you want to process data row by row or stop early.
from hft_lob.cli import Reader
reader = Reader("/path/to/feed.bin", tokens=1333)
# Get just the first message
msg = reader.get_next_message()
print(msg)
# Or loop through all messages one by one
while True:
msg = reader.get_next_message()
if msg is None:
break
fields = msg.split(",")
print(f"Mid price: {fields[2]}")
Returns: str (one CSV row) on each call, or None when all messages are exhausted
After last message: is_end_of_file() becomes True
3. is_end_of_file
What it does: Tells you whether all messages have been read. Returns True in two cases — after get_all_messages() is called, or after get_next_message() reaches the last message. Returns False if messages are still available.
from hft_lob.cli import Reader
reader = Reader("/path/to/feed.bin", tokens=1333)
print(reader.is_end_of_file()) # False — nothing read yet
msg = reader.get_next_message()
# ... keep reading ...
print(reader.is_end_of_file()) # True — when all messages are done
Returns: bool — True if finished, False if messages remain
How It Works (Architecture)
Your Python Code
|
v
hft_lob.cli.Reader <-- Python class (this library)
|
v
Rust Binary (subprocess) <-- orderbook-linux-x86_64
|
v
NSE Binary Feed File <-- e.g., Feed_CM_StreamID_2_29_12_2025.bin
|
v
CSV Output (parsed LOB) <-- returned back to your Python code
The Rust binary is bundled inside the Python package. When you call Reader(...), Python internally runs the Rust binary as a subprocess, passes your file path and token, captures the CSV output, and hands it back to you as Python strings. You never have to touch the binary directly.
Package Structure
hft-lob/ ← Python package root
│
├── hft_lob/ ← Main Python package (installed into site-packages)
│ ├── __init__.py ← Package initializer (marks this as a Python package)
│ ├── cli.py ← ALL the logic: Reader class + helper functions
│ └── bin/
│ └── orderbook-linux-x86_64 ← Compiled Rust binary (bundled with the package)
│
├── pyproject.toml ← Package metadata: name, version, dependencies, entry points
├── setup.py ← Legacy build config (used by setuptools)
├── README.md ← This file
└── dist/ ← Built packages (generated by `python -m build`)
├── hft_lob-0.1.8.tar.gz ← Source distribution
└── hft_lob-0.1.8-py3-none-any.whl ← Wheel (what pip installs)
| File | Purpose |
|---|---|
hft_lob/__init__.py |
Marks hft_lob as a Python package. Empty by design — import directly from hft_lob.cli |
hft_lob/cli.py |
Contains Reader class, get_lob_for_token() function, and main() CLI entry point |
hft_lob/bin/orderbook-linux-x86_64 |
The Rust binary that does the heavy computation. Bundled so users don't install anything extra |
pyproject.toml |
Tells pip how to install the package, what Python version is needed, and what CLI command to register |
Full API Reference
Reader(file_path, tokens)
| Parameter | Type | Description |
|---|---|---|
file_path |
str |
Path to the NSE binary feed .bin file |
tokens |
int or list[int] |
Instrument token(s) to extract |
What happens internally:
- Validates the Rust binary exists inside the installed package
- Validates your
file_pathexists on disk - For each token, runs the Rust binary as a subprocess
- Captures CSV output, strips the header row (stored in
reader.header) - Stores all data rows in memory — ready to read
Extra attributes:
| Attribute | Description |
|---|---|
reader.header |
CSV column names string e.g. local_ts,exch_ts,mid_price,... |
reader.close() |
No-op, safe to call — no file handle to close |
get_lob_for_token(file_path, token)
Lower-level helper — directly runs the Rust binary and returns raw CSV as a single string (includes header).
from hft_lob.cli import get_lob_for_token
raw = get_lob_for_token("/path/to/feed.bin", 1333)
print(raw)
CSV Output Format
Each message row has 23 comma-separated fields:
local_ts, exch_ts, mid_price,
bid_price_0, bid_qty_0, ask_price_0, ask_qty_0,
bid_price_1, bid_qty_1, ask_price_1, ask_qty_1,
bid_price_2, bid_qty_2, ask_price_2, ask_qty_2,
bid_price_3, bid_qty_3, ask_price_3, ask_qty_3,
bid_price_4, bid_qty_4, ask_price_4, ask_qty_4
| Field | Description |
|---|---|
local_ts |
Local timestamp (nanoseconds) when message was received |
exch_ts |
Exchange timestamp (nanoseconds) from NSE |
mid_price |
(best bid + best ask) / 2 |
bid_price_N |
Bid price at depth level N (0 = best bid) |
bid_qty_N |
Total quantity at bid level N |
ask_price_N |
Ask price at depth level N (0 = best ask) |
ask_qty_N |
Total quantity at ask level N |
More Examples
Parse into a dict
from hft_lob.cli import Reader
reader = Reader("/path/to/feed.bin", tokens=1333)
messages = reader.get_all_messages()
columns = reader.header.split(",")
first = dict(zip(columns, messages[0].split(",")))
print(f"Best bid: {first['bid_price_0']} x {first['bid_qty_0']}")
print(f"Best ask: {first['ask_price_0']} x {first['ask_qty_0']}")
Multiple tokens
reader = Reader("/path/to/feed.bin", tokens=[1333, 2885, 5900])
all_msgs = reader.get_all_messages()
print(f"Combined messages: {len(all_msgs)}")
Load into pandas
import io, pandas as pd
from hft_lob.cli import Reader
reader = Reader("/path/to/feed.bin", tokens=1333)
messages = reader.get_all_messages()
df = pd.read_csv(io.StringIO(reader.header + "\n" + "\n".join(messages)))
print(df[["local_ts", "mid_price", "bid_price_0", "ask_price_0"]].head())
CLI Usage
hft-lob /path/to/feed.bin 1333
Prints raw CSV to stdout.
Platform Support
| Platform | Supported |
|---|---|
| Linux x86_64 | Yes |
| macOS | No |
| Windows | No |
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hft_lob-0.1.9.tar.gz.
File metadata
- Download URL: hft_lob-0.1.9.tar.gz
- Upload date:
- Size: 225.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
046f311b1afcf8434a11824f06c9911301531b56b9b28adab74ece7292f4efd4
|
|
| MD5 |
a8ce7a094a05f745c9d9dd27eab8b4ea
|
|
| BLAKE2b-256 |
e72a7ee2c7a12c1d34b4e80f676f1a8fe114a401d4ed838658dfcf3ef9287bc3
|
File details
Details for the file hft_lob-0.1.9-py3-none-any.whl.
File metadata
- Download URL: hft_lob-0.1.9-py3-none-any.whl
- Upload date:
- Size: 222.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
14acf97ffef6bcc6da9fff5783a3a1947fa720e174b8c0acd4cb8b36190b0da5
|
|
| MD5 |
bf9d7233cb0209ac891524509d54a5f4
|
|
| BLAKE2b-256 |
af05883d74bbf27236b282db2a659a25329bb08f56ff0a46ff1911f5ad973217
|