DEV Community

Joshua Yap for Hydromancer

Posted on

How deep is the Hyperliquid order book? Measure it in Python

A mid price tells you where a market is. It doesn't tell you what a $1M order would cost. For that you need the order book itself, and you need to read it by size rather than by price level.

This walkthrough measures depth on Hyperliquid in three short scripts: how far a given order would reach, who is sitting at the top of the book, and how to get an alert when liquidity thins out.

The data comes from the Python SDK of Hydromancer, a Hyperliquid data provider. It keeps a local copy of the full order book for the coins you subscribe to, individual orders included, and updates it block by block.

Setup

You need Python 3.11 or newer and a Hydromancer API key. Keys come with a paid plan and are issued through onboarding.

pip install git+https://github.com/hydromancerxyz/hydromancer-sdk.git
export HYDROMANCER_API_KEY="your-api-key"
Enter fullscreen mode Exit fullscreen mode

How far does an order reach?

get_notional_depth gives the USD resting within a distance of mid, in basis points. get_depth gives the distance of the last order you would need to fill a USD amount. Both take a side: "A" for asks, which a buy consumes, and "B" for bids, which a sell consumes.

from hydromancer_sdk import OrderbookStream

COINS = ["BTC", "ETH", "HYPE"]
SIZES = [10_000, 100_000, 1_000_000]

with OrderbookStream(coins=COINS) as stream:
    for coin in COINS:
        print(f"\n{coin}: bid {stream.best_bid(coin)}, ask {stream.best_ask(coin)}")
        for side, name in (("A", "buy"), ("B", "sell")):
            within_1pct = stream.get_notional_depth(coin, 100, side)
            print(f"  {name}: ${within_1pct:,} within 1% of mid")
            for size in SIZES:
                if size > within_1pct:
                    print(f"    ${size:,}: goes past 1%")
                    continue
                print(f"    ${size:,}: last fill {stream.get_depth(coin, size, side):.2f} bps from mid")
Enter fullscreen mode Exit fullscreen mode

Here is part of one run:

BTC: bid 77710, ask 77711
  buy: $121,046,238 within 1% of mid
    $10,000: last fill 0.06 bps from mid
    $100,000: last fill 0.06 bps from mid
    $1,000,000: last fill 0.58 bps from mid

HYPE: bid 87.859, ask 87.86
  buy: $17,374,400 within 1% of mid
    $10,000: last fill 1.54 bps from mid
    $100,000: last fill 3.47 bps from mid
    $1,000,000: last fill 12.01 bps from mid
Enter fullscreen mode Exit fullscreen mode

In this snapshot, a $1M buy reached 0.58 bps from mid on BTC and 12.01 bps on HYPE. These numbers move constantly, so treat them as an example of the method.

Two things to watch:

  • get_depth is the worst price, not the average. It reports how far the last order sits from mid. Your average fill will be at that distance or closer to mid.
  • Check size first. If a side holds less than the amount you ask for, get_depth returns the distance to its deepest order instead of failing. That is why the script compares the size with get_notional_depth before calling it.

Who is at the top of the book?

Level-based feeds tell you the total size at a price. An L4 book keeps each order, so you can see how concentrated a level is.

from hydromancer_sdk import OrderbookStream, SCALE

with OrderbookStream(coins=["ETH"]) as stream:
    best = round(float(stream.best_bid("ETH")) * SCALE)
    sizes = []
    for user in stream.best_bid_users("ETH"):
        orders = stream.orders_by_user("ETH", user)
        sizes.append(sum(o.sz for o in orders if o.side == "B" and o.px == best))
    total = sum(sizes)
    print(f"{len(sizes)} addresses at the best bid, {total / SCALE:.4f} ETH in total")
    print(f"largest holds {max(sizes) / total:.0%} of the level")
Enter fullscreen mode Exit fullscreen mode
27 addresses at the best bid, 146.1634 ETH in total
largest holds 18% of the level
Enter fullscreen mode Exit fullscreen mode

The total alone hides that split: if the largest address pulls its orders, this level loses 18% of its size at once. The stream keeps updating while this runs, so treat the result as a snapshot.

Get an alert when the book thins out

on_update runs after each block. This script prints only when liquidity crosses a floor, so it stays quiet the rest of the time.

import time
from hydromancer_sdk import OrderbookStream

FLOOR = 1_000_000
thin = False

def on_update(stream, height):
    global thin
    liquidity = stream.get_notional_depth("ETH", 5, "B")
    now_thin = liquidity < FLOOR
    if now_thin != thin:
        thin = now_thin
        state = "thin" if thin else "recovered"
        print(f"block {height}: ETH bids within 5 bps {state} at ${liquidity:,}")

with OrderbookStream(coins=["ETH"], on_update=on_update) as stream:
    while True:
        time.sleep(10)
Enter fullscreen mode Exit fullscreen mode

The callback runs on every block, so keep it light. Hand anything slow, such as a webhook call, to a queue or another thread. The SDK also swallows exceptions raised in the callback, so a bug there fails silently.

In one run it fired once and recovered eight blocks later:

block 1204235330: ETH bids within 5 bps thin at $247,471
block 1204235338: ETH bids within 5 bps recovered at $1,023,761
Enter fullscreen mode Exit fullscreen mode

At the roughly 14 blocks per second I measured, that dip lasted under a second. It may not fire on every run. To skip dips this short, require at least ten thin blocks in a row before alerting.

Where to go next

This article was created with the help of AI.

Top comments (0)