Overview
This guide demonstrates how to stream real-time orderbook data from Hyperliquid using gRPC in Python. You'll learn to:
- Stream L2 orderbook (aggregated price levels with depths)
- Stream L4 orderbook (individual orders with full details)
- Generate Python code from Protocol Buffer definitions
- Handle reconnections and errors gracefully
The orderbook streaming API uses a separate proto file (orderbook.proto) from the core streaming API, providing specialized methods optimized for market data.
For core streaming API (StreamData, StreamBlocks, Ping), see Python Setup Guide
Prerequisites
1. Install Python
Python 3.8 or later is required. Verify your installation:
python3 --version
pip3 --version
2. Install Required Packages
Install gRPC and Protocol Buffers tools:
pip3 install grpcio grpcio-tools protobuf
These packages provide:
grpcio- gRPC runtime librarygrpcio-tools- Protocol buffer compiler (includesprotoc)protobuf- Protocol buffer message types
Project Setup
Step 1: Create Project Directory
mkdir hyperliquid-orderbook-python
cd hyperliquid-orderbook-python
mkdir proto examples
Your directory structure:
hyperliquid-orderbook-python/
├── proto/ # Protocol buffer definitions
└── examples/ # Example scripts
Step 2: Download Proto File
Download the orderbook protocol definition:
curl -o proto/orderbook.proto \
https://raw.githubusercontent.com/quiknode-labs/hypercore-grpc-examples/main/proto/orderbook.proto
Step 3: Generate Python Code
Generate Python code from the proto file:
python3 -m grpc_tools.protoc \
-I./proto \
--python_out=./proto \
--grpc_python_out=./proto \
proto/orderbook.proto
This generates:
proto/orderbook_pb2.py- Message definitionsproto/orderbook_pb2_grpc.py- gRPC service client
Step 4: Create Package Init File
Make the proto directory a Python package:
touch proto/__init__.py
Verify the files were generated:
ls -la proto/
# Should show: orderbook.proto, orderbook_pb2.py, orderbook_pb2_grpc.py, __init__.py
Implementation
StreamL2Book Example
Create examples/stream_l2.py:
#!/usr/bin/env python3
"""
StreamL2Book Example - Stream aggregated orderbook data
"""
import grpc
import sys
import time
import argparse
# Add proto directory to path
sys.path.insert(0, '../proto')
try:
import orderbook_pb2 as pb
import orderbook_pb2_grpc as pb_grpc
except ImportError:
print("Error: Proto files not found")
sys.exit(1)
def stream_l2_orderbook(endpoint: str, token: str, coin: str, n_levels: int = 20):
"""Stream L2 orderbook updates for a coin."""
print(f"\n{'='*60}")
print(f"Streaming L2 Orderbook for {coin}")
print(f"Levels: {n_levels}")
print(f"{'='*60}\n")
retry_count = 0
max_retries = 10
base_delay = 2
while retry_count < max_retries:
channel = grpc.secure_channel(
endpoint,
grpc.ssl_channel_credentials(),
options=[
('grpc.max_receive_message_length', 100 * 1024 * 1024),
('grpc.keepalive_time_ms', 30000),
]
)
stub = pb_grpc.OrderBookStreamingStub(channel)
request = pb.L2BookRequest(coin=coin, n_levels=n_levels)
msg_count = 0
try:
if retry_count > 0:
print(f"\n🔄 Reconnecting (attempt {retry_count + 1}/{max_retries})...")
else:
print(f"Connecting to {endpoint}...")
for update in stub.StreamL2Book(request, metadata=[('x-token', token)]):
msg_count += 1
if msg_count == 1:
print(f"✓ First L2 update received!\n")
retry_count = 0
# Display orderbook
print(f"\n{'-'*60}")
print(f"Block: {update.block_number} | Time: {update.time} | Coin: {update.coin}")
print(f"{'-'*60}")
# Display asks (reversed for proper display)
if update.asks:
print("\n ASKS:")
for level in reversed(update.asks[:10]):
print(f" {level.px:>12} | {level.sz:>12} | ({level.n} orders)")
# Display spread
if update.bids and update.asks:
bid_price = float(update.bids[0].px)
ask_price = float(update.asks[0].px)
spread = ask_price - bid_price
spread_bps = (spread / bid_price) * 10000
print(f"\n {'-'*44}")
print(f" SPREAD: {spread:.2f} ({spread_bps:.2f} bps)")
print(f" {'-'*44}")
# Display bids
if update.bids:
print("\n BIDS:")
for level in update.bids[:10]:
print(f" {level.px:>12} | {level.sz:>12} | ({level.n} orders)")
print(f"\n Messages received: {msg_count}")
except grpc.RpcError as e:
if e.code() == grpc.StatusCode.DATA_LOSS:
print(f"\n⚠️ Server reinitialized: {e.details()}")
retry_count += 1
if retry_count < max_retries:
delay = base_delay * (2 ** (retry_count - 1))
print(f"⏳ Waiting {delay}s before reconnecting...")
time.sleep(delay)
continue
print(f"Error: {e.code()} - {e.details()}")
break
except KeyboardInterrupt:
print("\n\nStopped by user")
break
finally:
channel.close()
break
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Stream L2 orderbook data")
parser.add_argument("--endpoint", default="your-endpoint.hype-mainnet.quiknode.pro:10000", help="gRPC endpoint")
parser.add_argument("--token", default="your-auth-token", help="Authentication token")
parser.add_argument("--coin", default="BTC", help="Coin symbol")
parser.add_argument("--levels", type=int, default=20, help="Number of price levels")
args = parser.parse_args()
stream_l2_orderbook(args.endpoint, args.token, args.coin, args.levels)
For individual order streaming with full details, see the StreamL4Book method documentation which includes complete code examples.
Run the Example
Make the script executable and run it:
cd examples
chmod +x stream_l2.py
python3 stream_l2.py \
--endpoint="your-endpoint.hype-mainnet.quiknode.pro:10000" \
--token="your-auth-token" \
--coin="BTC" \
--levels=20
Options:
--endpoint- gRPC endpoint with port 10000--token- Authentication token from Quicknode--coin- Trading pair (BTC, ETH, SOL, etc.)--levels- Number of price levels (default: 20, max: 100)
Output:
============================================================
Streaming L2 Orderbook for BTC
Levels: 20
============================================================
Connecting to your-endpoint.hype-mainnet.quiknode.pro:10000...
✓ First L2 update received!
------------------------------------------------------------
Block: 904331105 | Time: 1771916479849 | Coin: BTC
------------------------------------------------------------
ASKS:
63088 | 3.67635 | (10 orders)
63087 | 3.46847 | (7 orders)
63086 | 0.27414 | (5 orders)
...
--------------------------------------------
SPREAD: 1.00 (0.16 bps)
--------------------------------------------
BIDS:
63078 | 3.57636 | (7 orders)
63077 | 0.04397 | (4 orders)
63076 | 0.00034 | (2 orders)
...
Messages received: 1
Understanding the Output:
- Block/Time - Blockchain block number and timestamp
- Asks - Sell orders (displayed high to low)
- Spread - Difference between best bid and ask in basis points
- Bids - Buy orders (displayed high to low)
- Order Count - Number of individual orders at each price level
We ❤️ Feedback!
If you have any feedback or questions about this documentation, let us know. We'd love to hear from you!