Prerequisites
- Python 3.8 or higher
hyperliquid-python-sdkinstalled (pip install hyperliquid-python-sdk)- Reliable Hyperliquid RPC endpoint (sign up for free)
The precision problem
This order gets rejected:"Tick size violation" or "Invalid order size"
This works:
0.00100 breaks when you switch to another asset. You need dynamic precision.
Tick size vs lot size
Hyperliquid enforces precision on both price and quantity: Tick size — price precision:- Prices limited to 5 significant figures
- Max decimal places:
MAX_DECIMALS - szDecimals, whereMAX_DECIMALSis 6 for perps and 8 for spot - Integer prices are always valid regardless of significant figures (for example,
123456is valid for BTC) - Examples for BTC perp (
szDecimals= 5, so max 1 decimal place):97000.5✓,97000.55✗
- Determined by
szDecimalsin asset metadata, fixed per asset at deployment - Ranges from 0 (whole integers only, for example, PURR) to 5 (for example, BTC)
- Must query from API—cannot hardcode
Querying asset metadata
Understanding Hyperliquid asset formats
Hyperliquid uses multiple formats to identify assets: Spot assets:@{index}— direct index reference (for example,@0= BTC/USDC){TOKEN}/USDC— pair name (for example,PURR/USDC)
{SYMBOL}— direct symbol (for example,BTC,ETH,SOL)
Getting spot asset metadata
QueryspotMetaAndAssetCtxs for comprehensive spot data including precision requirements:
Getting perpetual asset metadata
Perps use a simpler structure viametaAndAssetCtxs:
Working with order precision
Calculating valid order sizes (lot size)
Order sizes must be rounded to theszDecimals specified in asset metadata. This is also known as the lot size—the minimum increment for order quantities.
- Target value: $15 USDC
- BTC spot price: $65,000
- Size decimals (
szDecimals): 5 - Raw size: 15 / 65000 = 0.000230769…
- Valid size:
floor(0.000230769 * 100000) / 100000=0.00023(5 decimals)
szDecimals field in metadata determines lot size precision. Query this value from spot_meta_and_asset_ctxs() for spot or meta_and_asset_ctxs() for perps.
Minimum notional value
Hyperliquid enforces minimum order values of $10 (or 10 USDC for spot). The only exception is exactly closing a position with a reduce-only order. Check before placing:Price precision (tick size)
Price precision on Hyperliquid follows specific rules: Significant figures rule — prices can have up to 5 significant figures Integer exception — integer prices are always valid regardless of significant figures (for example,123456 is valid for BTC even though it has 6 significant figures)
Maximum decimal places — determined by the formula MAX_DECIMALS - szDecimals:
- Perpetuals —
MAX_DECIMALS= 6 - Spot —
MAX_DECIMALS= 8
Examples of valid and invalid perpetual prices (BTC,
szDecimals = 5):
97000.5✓ (5 sig figs, 1 decimal)97000.55✗ (exceeds6 - 5 = 1max decimal places)123456✓ (integer exception—always valid)
1234.5✓ (5 significant figures)1234.56✗ (6 significant figures—too many)0.001234✓ (4 significant figures, 6 decimals)
Implementation examples
Complete order placement flow
Putting it together for dynamic multi-asset trading:Handling unknown assets
When trading new or obscure assets:szDecimals default is safer because it produces a more precisely truncated (smaller) size via math.floor.
Caching metadata
Query metadata once, reuse for multiple orders:Troubleshooting
Common rejection reasons
“Order has invalid size” (lot size violation) — size is not a multiple of10^(-szDecimals). Query szDecimals from metadata and floor-truncate order size accordingly.
“Price must be divisible by tick size” (price precision) — price has too many significant figures (>5) or exceeds MAX_DECIMALS - szDecimals decimal places. Use the format_price function above.
“Order must have minimum value of 10 USDC” — below minimum notional value. Increase order size. Exception: exactly closing a position with reduce-only bypasses this minimum.
“User or API Wallet 0x1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0b does not exist” — often caused by trailing zeros in price or size strings during signing. For example, "0.2300" fails where "0.23" succeeds. If you build order wire messages manually, use Decimal.normalize() to strip trailing zeros before signing. The SDK’s float_to_wire() handles this automatically.
“Asset not found” — wrong coin field format (@index for spot, SYMBOL for perps) or delisted asset.
“Insufficient balance” — not a precision issue, but verify wallet has enough collateral before placing orders.
Summary
QueryszDecimals from asset metadata to calculate valid order sizes dynamically—never hardcode precision. Floor-truncate sizes to szDecimals decimal places. Prices must have ≤5 significant figures with max MAX_DECIMALS - szDecimals decimal places (where MAX_DECIMALS is 6 for perps, 8 for spot); integer prices are always valid. Support all asset formats (@index, PAIR/USDC, SYMBOL), validate minimum notional ($10 USDC), and cache metadata to reduce API calls.
The complete implementation is available in the Chainstack Hyperliquid trading bot repository.
Related resources
- Copy trading with spot orders — Build a copy trading bot that mirrors spot trades
- TWAP order execution — Place and monitor TWAP orders on Hyperliquid
- Authentication guide — Authenticate with Hyperliquid exchange API
- API reference — Explore the complete Hyperliquid API reference