Hyperliquid Tick Size and Lot Size: Round Prices and Sizes
Hyperliquid tick size and lot size rules: 5 significant figures, szDecimals, the $10 perp minimum, and a Python function that rounds orders correctly.

"Order has invalid price." If your bot gets this back from Hyperliquid, or "Price must be divisible by tick size", nothing is wrong with your strategy.
The price or size just wasn't rounded the way Hyperliquid expects, and the fix is a few lines of code.
Hyperliquid tick size: rules, not a fixed tick
On most centralized exchanges (CEXs), each market has a fixed tick size you look up once. Hyperliquid uses rules instead:
| Tick size on Hyperliquid | Tick size on a typical CEX | |
|---|---|---|
| Price step | Set by a rule: at most 5 significant figures, plus a decimals cap | A fixed step per market |
| When it changes | Automatically, as the price moves | When the exchange updates the market |
| Whole-number prices | Always valid | Depends on the market |
| Minimum order | $10 on perps, 10 of the quote token on spot | Varies by market |
So you can't store one tick per market. You store the rule and apply it to every order.
The fix takes three steps:
- Read
szDecimals, the number that sets each market's limits. - Round prices and sizes before you send them.
- Read the errors the exchange returns when an order breaks a rule.
Market values are a snapshot from when we tested.
The rules
| Perps | Spot | |
|---|---|---|
| Significant figures in a price | At most 5 | At most 5 |
| Decimal places in a price | At most 6 − szDecimals | At most 8 − szDecimals |
| Whole-number prices | Always valid | Always valid |
| Decimal places in a size | At most szDecimals | At most the base token'sszDecimals |
| Minimum order value | $10 | 10 of the quote token |
The rules come from Hyperliquid's tick and lot size docs. Their own examples:
1234.5is valid;1234.56isn't (six significant figures).0.001234is valid on a perp;0.0012345isn't (seven decimals, more than 6 − 0).123456is valid even though12345.6isn't, because whole numbers skip the significant-figure limit.
So what is the tick size?
Because of the 5-significant-figure rule, the price step depends on the price. Before the decimals cap, it's:
| Price | Step from 5 significant figures |
|---|---|
| 10,000 and above | 1 |
| 1,000 up to 10,000 | 0.1 |
| 100 up to 1,000 | 0.01 |
| 10 up to 100 | 0.001 |
| Below 10 | Smaller, until the decimals cap stops it |
The decimals cap can make the step coarser. BTC, with szDecimals 5, can never go finer than 0.1. At low prices, the cap usually wins. kPEPE, at about $0.0044 with szDecimals 0, can only use 6 decimals, so its step is 0.000001. Don't store one tick per market; store the rule.
Lot size is the size step: 1 ÷ 10^szDecimals. BTC has szDecimals 5, so sizes move in steps of 0.00001 BTC. The $10 minimum usually binds first.
About the snippets: like our docs, they're excerpts. They assume Python with requests installed and imported, with the SDK's exchange client for the order example.
Step 1: Read szDecimals for each market
Every rule above depends on one number per market: szDecimals, the number of decimal places a size may have. It also sets the price decimals cap. Perps keep it in meta. Spot keeps it per token in spotMeta, and the one that counts is the base token's:
meta = requests.post(INFO, json={"type": "meta"}).json()
mids = requests.post(INFO, json={"type": "allMids"}).json()
for a in meta["universe"]:
n = a["name"]
if n in ("BTC", "ETH", "HYPE", "kPEPE"):
print(f"{n:6} szDecimals={a['szDecimals']} mid={mids[n]}")BTC szDecimals=5 mid=80606.5
ETH szDecimals=4 mid=2340.45
kPEPE szDecimals=0 mid=0.004392
HYPE szDecimals=2 mid=77.1165INFO is Hyperliquid's info endpoint, https://api.hyperliquid.xyz/info. For HIP-3 markets, add the DEX name: {"type": "meta", "dex": "xyz"}. Load this at startup, and refresh it as new markets list.
Step 2: Round prices and sizes before you send
With szDecimals in hand, round every price and size right before the order goes out. This function applies both price rules, keeping whichever allows fewer decimals (never fewer than zero, so whole numbers always pass), and rounds sizes down. It uses Decimal so floating-point errors can't add stray digits:
from decimal import Decimal, ROUND_HALF_UP, ROUND_DOWN
def round_price(px, sz_decimals, max_decimals=6): # 6 perps, 8 spot
px = Decimal(str(px))
decimals = max(min(max_decimals - sz_decimals, 4 - px.adjusted()), 0)
return px.quantize(Decimal(1).scaleb(-decimals), rounding=ROUND_HALF_UP)
def round_size(sz, sz_decimals):
step = Decimal(1).scaleb(-sz_decimals)
return Decimal(str(sz)).quantize(step, rounding=ROUND_DOWN)Here's what it does to a limit buy 1% below the mid, worth $25, on real markets:
| Market | szDecimals |
Price you computed | Price to send | Size you computed | Size to send |
|---|---|---|---|---|---|
| BTC | 5 | 79800.435 | 79800 | 0.000313281… | 0.00031 |
| ETH | 4 | 2317.1445 | 2317.1 | 0.010789141… | 0.0107 |
| HYPE | 2 | 76.352265 | 76.352 | 0.327429710… | 0.32 |
| kPEPE | 0 | 0.0043461 | 0.004346 | 5752.28… | 5752 |
| HMSTR | 0 | 0.00014058 | 0.000141 | 177834.68… | 177834 |
The function doesn't check the $10 minimum, so check price × size after rounding.
Step 3: Read what the exchange says
To see the difference rounding makes, here's the same BTC order sent twice with the Python SDK: first as computed, then rounded. We sent it on testnet, so no real money was at risk:
sz = float(round_size(0.000301234, 5)) # BTC, about $12
for px in (40867.53, round_price(40867.53, 5)): # as computed, then rounded
r = exchange.order("BTC", True, sz, float(px), {"limit": {"tif": "Gtc"}})
print(px, r["response"]["data"]["statuses"][0])40867.53 {'error': 'Order has invalid price.'}
40868 {'resting': {'oid': 63656385802}}exchange is the SDK's Exchange client, set up on testnet as in our testnet guide. The resting order was cancelled straight after.
Errors you may see, and their usual cause:
| Error | Usual cause | Fix |
|---|---|---|
Price must be divisible by tick size. | More than 5 significant figures | round_price |
Order has invalid price. | Too many decimal places | round_price |
Order has invalid size. | More decimals thanszDecimals | round_size |
Order must have minimum value of $10. | Order worth under $10 | Raise the size |
Most order errors come back inside each order's status, even when the top level says "ok". Some are rejected for the whole request, so check both levels. The full list is in Hyperliquid's error docs.
How Hydromancer's API comes in
Rounding is a Hyperliquid rule, so the rounding itself doesn't change with Hydromancer. What changes is where your bot reads market data from:
| What you need | Without Hydromancer (Hyperliquid's API only) | With Hydromancer's API |
|---|---|---|
meta, spotMeta and allPerpMetas | From Hyperliquid, sharing 1,200 weight a minute per IP with every other read | The same requests, with a separate per-key budget: 5,000, 20,000 or 50,000 weight a minute by plan, per our rate limits docs |
| Placing the rounded order | Hyperliquid's exchange API | The same: orders always go to Hyperliquid |
If your bot already reads its data from Hydromancer, load szDecimals from there too, and keep your Hyperliquid budget for order-related reads.
What to know
- Round mids before using them as prices. A mid can fall between two ticks.
- Round sizes yourself. Don't rely on the exchange to round a size with too many decimals.
- **
szDecimalscan differ between testnet and mainnet** for the same coin, so read it from the network you trade on. - HIP-3 markets follow the perp rules. Their
szDecimalscomes frommetawith the DEX name.
FAQ
What is the tick size on Hyperliquid?
There's no fixed tick per market. Prices can have at most 5 significant figures, so the step depends on the price: $1 above $10,000, $0.1 from $1,000 up to $10,000, and so on. The decimals cap of 6 − szDecimals on perps can make it coarser.
What is szDecimals?
The number of decimal places a size may have on that market. It also sets the price decimals cap. Find it in meta for perps and spotMeta for spot.
Why do I get "Order has invalid price" with only 5 significant figures?
Because the decimals cap applies too. On a perp with szDecimals 0, 0.0022335 has 5 significant figures but 7 decimals. Round it to 0.002234.
How do I calculate the price step on Hyperliquid?
Work out the step allowed by 5 significant figures, and the step forced by the decimals cap of 6 − szDecimals places on perps (8 − szDecimals on spot). Use the larger of the two steps; whole-number prices are always allowed. For BTC at $80,000 that gives a $1 step. The round_price function above does it for any market.
Are the tick size rules the same on testnet and mainnet?
The rules are the same, but szDecimals can differ between the two networks for the same coin. Read it from the network you trade on.
What is the minimum order size on Hyperliquid?
$10 on perps, or 10 of the quote token on spot. Sizes move in steps of 1 ÷ 10^szDecimals.
Read next

How to Build a Hyperliquid Copy Trading Bot
Build a copy trading bot on Hyperliquid: follow a trader's fills live, size each copy, re-check positions for missed trades, and know its limits.

Hyperliquid Leaderboard: How to Track Top Addresses' PnL
See Hyperliquid's top 10 traders by PnL over the last 365 days, then build your own leaderboard from public data and avoid its common traps.

How to Build a Hyperliquid Trading Bot
Learn how to build a Hyperliquid trading bot: a signal from market data, signed orders through Hyperliquid's API, risk limits and a kill switch, with examples.