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