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
Access to /hypercore (JSON-RPC and WebSocket) and HyperCore gRPC streaming requires a Quicknode Build plan or higher. View pricing to upgrade.
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!