Hyperliquid Cohort Metrics
hl_cohort_metricsHourly long/short positioning of ONE Hyperliquid perp split by cohort: every bucket of one ladder, every hour, in one call (the matrix behind 'are whales / smart money long or short BTC'). axis picks the ladder: size (account value), pnl (percentile of cumulative realized PnL), pnl_abs (realized PnL in dollar bands), pnl_unrealized (currently onside), tier (each position's own notional). Data from 2026-04-07 (the first hour cohort labels are correct); an older start is served from there and the envelope says data_from. Rows are hour x cohort: n_wallets (wallets in the cohort holding the symbol), notional in USD (total_position_value, total_position_value_long) and bias = (long - short) / (long + short), a fraction from -1 (all short) to +1 (all long), not a percent. BACKTESTS: by default the pnl cohort is TODAY's grading applied to past hours (look-ahead); pass label_basis=point_in_time for each hour's label as it was, and read label_computed and freshness in the envelope. The hour in progress is never included. The response holds about hours x 12-13 rows: pass a small hours (1-24) for a current read and page older data with cursor. With include (volume, median_pnl; size or pnl axis) the newest hour's rows also carry each cohort's 24-hour fill volume and the median realized PnL of its wallets, in USD, computed at request time. Same data as GET /v1/hl-cohorts/symbols/{symbol}/cohort-metrics.
Tool call template
Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.
{
"id": 1,
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"arguments": {
"symbol": "<symbol>"
},
"name": "hl_cohort_metrics"
}
}Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | ISO-8601 UTC upper bound, e.g. 2026-10-02T00:00:00Z. | |
| axis | No | Ladder to split by: `size` (account value), `pnl` (percentile of cumulative realized PnL), `pnl_abs` (realized PnL in dollar bands), `tier` (each position's own notional bucket; `trade_size` is an alias of it), `pnl_unrealized` (currently onside). | size |
| hours | No | Number of hourly buckets, newest first; the response holds about this many x 12-13 cohort rows. Pass 1-24 for a current read. Max 8760. | |
| start | No | ISO-8601 UTC lower bound, e.g. 2026-10-01T00:00:00Z. The hour in progress is never returned. | |
| cursor | No | Cursor over HOURS: `nextCursor` from the previous page, verbatim. | |
| symbol | Yes | Hyperliquid instrument ticker, e.g. BTC, ETH, HYPE; a HIP-3 market is `dex:TICKER`, e.g. xyz:TSLA. Required: an all-symbol matrix is refused. | |
| grading | No | Which PnL grading labels each wallet (axis `pnl` or `pnl_unrealized` only): `realized` (default on `pnl`), `realized-pit` (a control rebuilt once a day through 23:00 of the last complete UTC day, so a recent window comes back 1 to 25 hours short; read `freshness.behind_hours`) or `unrealized`. For live trading use `realized` with label_basis=point_in_time. | |
| include | No | Comma list of `volume`, `median_pnl`; default none. Adds to the NEWEST hour's rows `volume_24h_usd` (USD the cohort's wallets filled in this symbol in the last 24 hours; on `size` only wallets holding it now count; null if they filled nothing or the cohort is empty) and `median_realized_pnl_usd` (USD, median cumulative realized PnL over the DISTINCT wallets holding the symbol now; null if none does). The median is a sampled quantile: exact up to 8,192 wallets in a cohort, an estimate above it; the asset page's pnl-axis "Med Lifetime" counts positions rather than wallets, so it can differ slightly. Both are current figures, not that hour's, and null on `unknown`. Only `axis=size` or `axis=pnl` with the default grading; refused with opened_within, cursor or a past `end`. | |
| label_basis | No | `point_in_time` returns each hour's cohort label AS IT WAS: use it for every backtest (axis=pnl). Every field is served while each hour of the page carries that label on its rows: every hour from 2026-08-06 09:00 UTC and most earlier ones. A page reaching an hour without it (all of April 2026, about 365 hours from May to 2026-08-06 08:00) comes from the hourly aggregate, where position_count*, total_unrealized_pnl and total_position_size* are null, named in `unavailable_fields`. Without it a `pnl` cohort is TODAY's grading applied to past hours (look-ahead). `size`, `tier` and `pnl_unrealized` are always point-in-time; `pnl_abs` is always today's bands (look-ahead, never for a backtest); a conflicting value is refused. | |
| opened_within | No | Only positions opened within this window BEFORE EACH HOUR (rolling per bucket, not relative to now): `24h`, `7d`, `30d` or `all`. Applied on `size`, `tier`, `pnl_abs` and `pnl` with the default label basis; REFUSED (anything but `all`) with `axis=pnl_unrealized`, `grading=unrealized` or `realized-pit`, and `label_basis=point_in_time`, whose stored sources sum position age away. | all |