Measuring Hyperliquid: volume, open interest, users
Public Hyperliquid figures disagree mostly because each counts the same fills differently; a number means something only with its rows and units.
Two dashboards can report one market’s volume over the same days, differ by tens of per cent, and both be right. They add up different rows. Before you quote a figure, know which rows it counts.
One trade writes two rows
Section titled “One trade writes two rows”Every match writes two fills of equal notional sharing one tid: the taker’s (crossed: true) and the resting maker’s.
Say one trade of 1,000 USDC matches. Sum both rows → 2,000. Halve the sum → 1,000. Count each tid once → 1,000. Now say your archive kept only the taker row: halving gives 500, while counting each tid once, from whichever row exists, still gives 1,000.
Where most trades kept only one row, halving undercounts them by half. Check how many trades in your window have both rows.
Some fills are not trades
Section titled “Some fills are not trades”On outcome books only Buy and Sell fills are matches. The rest cross no book:
- Settlement fills: one per holder at settlement, paid from the collateral pot. The losing side’s has notional 0 and none carries a builder code; report them apart from trading.
- Conversion fills: split, merge, negate and merge question, priced at 1/n. One dataset counts them as trading volume, another excludes them.
Six lenses on the same fills
Section titled “Six lenses on the same fills”A lens is a rule for which fill rows to add:
| Lens | What it adds up | What it answers |
|---|---|---|
| matched | One notional per tid, attributed through the taker’s builder code |
How much money changed hands |
| routed | Both rows of every trade whose taker used a builder code | How much two-sided flow an app’s takers started |
| tagged | Every row carrying builder code X, taker or maker | How much flow carried an app’s code |
| buy_side | Rows where the fill side is B |
Volume by the buyer’s record only |
| hm_headline | All trading fill rows, divided by 2 | The halving convention several public trackers use; network level only |
| hl_official | Rows that paid a fee, plus winning-side settlement | Hyperliquid’s own rule for outcome volume |
At network level, tagged is effectively the raw sum of non-settlement fills. Officially, per the fee docs, outcome trades pay only when closing or settling and only fee-paying volume counts: minting and a match between two opening orders count nothing, however large, though row-counting lenses include them.
Open interest
Section titled “Open interest”openInterest in asset contexts is in base units (coins or contracts), not dollars: multiply by markPx. An outcome’s open interest is each side’s circulatingSupply, and the sides need not match, so name the side or give both.
Addresses are not people
Section titled “Addresses are not people”One person can run a master account, sub-accounts and vaults (each its own clearinghouse account) and API wallets (which only sign; querying one returns an empty result), and a HyperEVM contract can hold a HyperCore account. Address counts overstate people; signer counts count keys.
The numbers
Section titled “The numbers”| Measurement | Value |
|---|---|
| Halved fill sum vs one count per trade, same outcome archive | about $29.27M vs about $46M |
| Archived trades with only one of their two rows | about 67% |
| Trades with both rows in one node-fill archive, 2 to 15 May | 33.3% of 874k |
| Conversion fills (split, merge, negate) among outcome fills | about 1 in 5 |
| Inflation from mixing trading and settlement volume | about $20M |
| Network tagged plus settlement vs the official statistics page | within about 4% |
| Outcome pairs whose Yes and No supply differed | 89 of 192 |
Fills per userFillsByTime response |
at most 2,000; only the 10,000 most recent are available |
Computing each lens from fills
Section titled “Computing each lens from fills”Every fill carries what a lens needs: tid, crossed (true for the taker), side (B buy, A sell), fee, the optional builderFee, and dir, which names conversions (Split Outcome, Merge Outcome, Negate Outcome, Merge Question) and Settlement.
matched = sum of notional, one row per distinct tidtagged(X) = sum of notional over rows where builder = Xhm_headline = (sum of notional over all Buy and Sell rows) / 2hl_official = sum of notional over rows with fee > 0 + sum of notional over Settlement rows with notional > 0- Deduplicate on
tid, never onhash: an order’s partial fills share ahash. - No public stream carries all fills. Per-user history comes from
userFillsanduserFillsByTime; the publictradesWebSocket channel names both counterparties as[buyer, seller]. - Network-wide history is node fill data,
node_fills_by_block, published by a non-validating node with the requester paying for transfer.
Checklist for stating a number
Section titled “Checklist for stating a number”- Lens: rows, trades, halved rows or fee-paying rows.
- Exclusions: settlement; split, merge and negate conversions.
- Scope: validator-operated perps, HIP-3 perp dexes, spot, outcome markets, or all.
- Window: exact start and end, not “recently”.
- Open interest units: base units or dollars at mark; for an outcome, which side.
- Users: addresses that traded, held funds or signed.
- Source and gaps: API caps, archive completeness.
- Never compare numbers built with different lenses.
For where fills and archives come from, see Data: historical, node and explorer. For other claims to check before print, see Common misconceptions.