Skip to main content

Setting Up Python for OrderBook (L2/L4)

Updated on
Feb 24, 2026

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.

Related Guides

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 library
  • grpcio-tools - Protocol buffer compiler (includes protoc)
  • 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 definitions
  • proto/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)
StreamL4Book Example

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!

Share this doc