Method · measured 24 Oct 2026
How we measure what Hyperliquid's API returns
Everything here uses Hyperliquid's public, read-only info endpoint and public wallet addresses. No keys, no private data. Each step is described so the numbers can be checked.
1. The coverage check
Funding is only paid on an open position, and a position is only opened by a fill. So if a wallet paid funding before the oldest fill the API still returns, fills from that earlier period exist but are no longer returned.
- Read every fill the API returns with
userFillsByTime, paging forward from time 0, 2,000 per page. Each next page starts at the last fill's timestamp; overlap is removed by trade id, coin and time. - Read the earliest funding rows with
userFundingfrom time 0 and ignore rows with a zero position size, which prove nothing. - Read the earliest ledger event (deposits, transfers) with
userNonFundingLedgerUpdates. - Truncated: the oldest returned fill is more than 2 hours after the first funding on a non-zero position. The 2-hour slack covers funding that lands in the same hour as the opening fill. If funding exists and no fill is returned at all, the wallet is also truncated.
- Possibly truncated: no funding to prove it, but the first page of fills is full and trading starts more than 7 days after the first ledger event. We report this separately and never count it as proof.
- Otherwise: no gap found. That is not a promise the history is complete, only that this check found nothing.
2. The 40-wallet sample
We took active wallets from Hyperliquid's public leaderboard and picked 10 per lifetime-volume band, 40 in total, then ran the coverage check on each on 24 October 2026.
| Lifetime volume | Wallets with older fills not returned | Fills still returned | Period not returned |
|---|---|---|---|
| $1M – $10M | 1 of 10 | 135 days | 205 days |
| $10M – $100M | 2 of 10 | 227 days | 42 days |
| $100M – $1B | 3 of 10 | 78 days | 567 days |
| $1B and above | 10 of 10 | 36 days | 378 days |
Days are medians among the affected wallets in each band. Small sample: 10 wallets per band is enough to show the pattern, not to estimate exact rates. We do not publish the wallet list or rank wallets.
3. Unexplained position changes
Every fill reports the position size before it (startPosition). For each coin we put the returned fills in time order and check that each one starts where the previous one ended.
One order often fills against several makers in the same millisecond, and the trade ids within that millisecond do not follow the position. So within each timestamp we first order the fills into a continuous chain (start size to end size), if one exists. Only after that do we count a break: a fill whose start does not match where the previous fill for that coin left the position. We call that an unexplained position change: something moved the position, and the API does not return a fill for it.
We do not know the cause of each change, so we do not call them lost trades. To corroborate them we use funding: if a funding row between the two fills shows a position size different from where the previous fill left it, the position really did change in between.
| Example wallet | Fills returned | Unexplained position changes | Corroborated by funding |
|---|---|---|---|
| A vault wallet | 29,112 | 401 | 139 |
| An active trading wallet | 11,205 | 0 | 0 |
Measured 24 Oct 2026. Wallets are not identified. "No fee" and "no realized PnL" mean the field is empty in the export, not zero. The second wallet still has older fills not returned (coverage check above), but the fills that are returned form a continuous chain.
4. Reconciliation against Hyperliquid's own PnL
Hyperliquid's portfolio endpoint returns its own all-time PnL series for a wallet. We compare it with the result computed from returned fills and funding (price PnL, minus fees, plus or minus funding) over the same period.
This is a cross-check, not proof. Hyperliquid's series includes unrealized PnL on open positions, and its all-time view can include activity outside perp fills. A difference between the two is a reason to look closer, never by itself proof that records are absent.
5. Known limits
- We only see what the public API returns at the time we ask. Results can change as Hyperliquid changes retention.
- The coverage check needs funding history. A wallet that never held a position across a funding hour cannot be proven truncated; at most it is flagged as possibly truncated.
- The continuity check finds breaks between returned fills. It cannot see a gap before the oldest returned fill, which is what the coverage check is for.
- Funding corroboration only works where a funding payment fell between the two fills. An uncorroborated change is not evidence against it.
- Floating-point sizes are compared with a tolerance of 0.000001.
- The sample is small and drawn from the leaderboard, so it leans towards very active wallets.
6. Other sources of full history
Hyperliquid's documentation lists other ways to get historical data: a third-party full trade-history export tool, and a requester-pays S3 archive of node fills (with funding and transfers in a separate event archive). See Historical data in the Hyperliquid docs.
We compared two wallets against a full-history export from a third-party tool listed in Hyperliquid's docs: the vault wallet above and one active trading wallet that uses TWAP orders. In both exports many times are cut to the second (all rows of one, 1.8M of 3.0M of the other), so we use a rule that works at that precision:
- A break is two consecutive perp fills of one coin from the fills API, each alone in its millisecond, where the second does not start where the first left the position.
- A break is testable when the two fills fall in different seconds and the export holds no extra rows in those two seconds beyond the ones the API returned.
- A testable break is closed when the export's rows strictly between the two seconds, plus the API fills after the first fill in its second and before the second fill in its second, of the same coin change the signed position by exactly the size of the break (within 0.0001 of the break's size, or 0.0001 for breaks under one unit).
| Wallet | Export rows | TWAP slice rows | Breaks | Testable | Closed by the export (% of testable) |
|---|---|---|---|---|---|
| A vault wallet | 2,957,086 | 2,928,633 | 2,076 | 1,396 | 1,358 (97.3%) |
| An active TWAP-using wallet | 610,419 | 418,490 | 1,865 | 1,174 | 1,174 (100%) |
Measured 24–25 Oct 2026. TWAP slice rows are rows with a zero transaction hash. Wallets are not identified. "No fee" and "no realized PnL" mean the field is empty in the export, not zero. The vault wallet's 401 changes in section 3 use the older millisecond chain rule on API fills only, so the two counts are not comparable.
What this shows, for these two wallets: the standard fills API leaves out TWAP slice fills (the separate TWAP endpoint keeps only the latest 2,000, and none of those appeared in the fills API), and under this rule the export's rows account for 97% and 100% of testable breaks. That fits TWAP slices being left out, but does not prove it is the cause of each break. About a third of breaks (680 and 691) cannot be tested at second precision and stay open questions; of all breaks, 65% and 63% are closed. It also shows that neither source is complete on its own: on the vault wallet, at least 1,385 fills the API returned have no row with the same coin, side, price and size anywhere in the export (1,904 when the time must also match to the second), and many export rows have no fee (1,783,371 and 72,132) or no realized PnL (2,388,294 and 342,382). Two wallets are a small sample, not a rate for all wallets.
7. Rerun it
Our study script (not published yet) reads a list of public addresses and writes a CSV and a short summary: fills returned, earliest fill, earliest funding on a non-zero position, earliest ledger event, verdict, unexplained position changes and how many are corroborated. It makes about one call per second.
The same continuity check runs in the free Hyperliquid to Koinly converter, in your browser.