vike

HL Cohorts

Cohort positioning for Hyperliquid perps - the cohort vocabulary, how each cohort is positioned now, and the hourly cohort matrix behind a positioning backtest.

2 tools for the cohort side of Hyperliquid: which cohorts of wallets exist and where each one is positioned right now and hour by hour across all symbols (hl_segments), and one symbol's hourly positioning by cohort over time (hl_cohort_metrics). They are the /v1/hl-cohorts REST routes shaped for an agent: each call reads one view, which is one route, runs the same query function that route runs, and costs what that route costs. hl_segments takes a view; hl_cohort_metrics has one view and no view parameter.

The behaviour every Hyperliquid tool shares (a call checked against its route before any query runs, symbol as the instrument parameter, the new field names only, keyset cursors, and the units table, where bias and pct_wallets_in_profit are both fractions) is stated once, under How these tools behave. The ladders are explained on Cohorts and axes and when a label was computed on Point-in-time vs current labels. For the current positioning of one symbol, hl_market on the Hyperliquid page is the shorter read; hl_cohort_metrics is the one for research.

hl_cohort_metrics

1 credit. The hourly cohort matrix of one symbol: for every hour, how much long and short notional each bucket of one ladder holds. It answers "are whales or smart money long or short BTC", the history of that answer, and is the source for a positioning backtest.

ParameterTypeDefaultNotes
symbolstringrequiredInstrument ticker, e.g. BTC; a HIP-3 market is dex:TICKER. An all-symbol matrix is refused
axisenumsizesize, pnl, pnl_abs, tier or pnl_unrealized; the ladders are described below
startstring—ISO-8601 UTC lower bound
endstring—ISO-8601 UTC upper bound
opened_withinenumall24h, 7d, 30d or all: positions opened in that window before each hour, rolling rather than relative to now. Anything but all is refused where the matrix is a stored aggregate (see below)
hoursinteger168Hourly buckets, newest first, max 8760. Pass 1 to 24 for a current read
cursorstring—nextCursor from the previous page; it pages by whole hours
label_basisenum—current or point_in_time. Use point_in_time for any backtest
gradingenum—realized (the default on pnl), realized-pit or unrealized; only on the pnl and pnl_unrealized axes
includestring—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.

Returns {axis, label_basis, grading, metrics, hours, nextCursor}, plus label_computed on every graded ladder (pnl, pnl_unrealized, pnl_abs) and freshness on a window that reaches the present. Each metrics row is one hour for one cohort: ts, cohort, total_position_value and total_position_value_long in USD, bias, and, except under label_basis=point_in_time, position_count, position_count_long, total_unrealized_pnl, total_position_size and total_position_size_long. The response holds about hours times the number of buckets on the ladder, so ask for hours=1 to 24 for a current read and page older data with cursor; paging is by whole hours, so an hour never arrives with some of its cohorts missing.

Three ladders are per wallet (size, pnl, pnl_abs); tier buckets each position by its own notional; pnl_unrealized ranks wallets by the unrealized PnL of their open positions as a share of account value, from the last snapshot before that hour. pnl_abs is always today's dollar bands, so it is look-ahead and never for a backtest. The hour in progress is never returned, so a series that is differenced or z-scored has no partial bar at its right edge. For the current value use hl_market view symbol_metrics.

opened_within is applied or refused, never dropped. It filters live positions, so it works on size, tier, pnl_abs and on pnl with the default label basis. The stored sources (axis=pnl_unrealized, grading=unrealized or realized-pit, and label_basis=point_in_time) have position age summed away, and the REST route answers the all-ages matrix for any value there, including a value that is not an age. The tool refuses anything but all in those combinations, naming the combination, and refuses a value that is not an age everywhere.

For a backtest, pass label_basis=point_in_time. Without it the pnl ladder is today's grading applied to past hours, which lets a wallet that is "smart" now label a period when it was not. label_computed states which source labelled the window and names the point where the label's resolution changes (daily before 2026-08-06, hourly after), which a turnover count will read as a regime change that is an artefact. grading=realized-pit is a frozen control for a study that crosses it: it stops growing, so a recent window comes back short, and freshness.behind_hours says by how much.

For a live read, check freshness. On a window that reaches the present the envelope carries {newest_ts, behind_hours, settled_lag_ceiling_hours, stale}; stale is the verdict, so a caller does not re-derive the rollup's cadence. A window that ends in the past has no freshness.

Are whales net long or short BTC right now, and how has that moved over the last 24 hours?

Compare smart-money and rekt positioning on ETH over the last month, with the cohort labels as they were at the time.

hl_segments

1 credit. The cohort vocabulary and its positioning at the latest snapshot. Read cohorts or segments first to learn the exact labels, then summary for one cohort, heatmap for the whole board or history for one cohort over time.

ParameterTypeDefaultNotes
viewenumsegmentssegments, cohorts, summary, heatmap or history
cohortstring—One label on axis, e.g. whale or 3x smart, spelled as cohorts lists it. Required by summary and history
axisenumsizesize, pnl or pnl_abs (summary, heatmap); history takes size or pnl only and requires it
opened_withinenumall24h, 7d, 30d or all (summary, heatmap); positions with no known open time are left out of every bounded window
startstring—ISO-8601 UTC lower bound, e.g. 2026-10-01T00:00:00Z. history only; hours before 2026-04-07 are never returned. Used by view: history.
endstring—ISO-8601 UTC upper bound, e.g. 2026-10-02T00:00:00Z. history only: with no start, the window is the hours newest hours at or before it. Used by view: history.
hoursinteger168history only: window length in hours when start is omitted, ending at end or now. Max 8760. Used by view: history.
limitinteger5000history only: max hourly rows, newest first; has_more says older ones exist, page back with end = the oldest ts minus 1 second. Max 5000. Used by view: history.
includestring—history only: comma list, only leverage; default none (nothing extra is read). Adds to every hourly row perp_bias = (long - short) / equity, equity_exposure = (long + short) / equity and equity_covered_share = main-dex notional of the counted wallets / main-dex notional of the whole cohort: unbounded ratios (above 1 = more than 1x of equity), native perp account only (main-dex positions of wallets with a known positive native equity, each wallet once; builder-DEX positions are not included). An hour with no stored row, and any hour before leverage.data_from (2026-08-11), is null on all three (never 0). perp_bias and equity_exposure are also null when no counted wallet has a positive equity; equity_covered_share is null when the cohort holds no main-dex notional and a real 0 when it holds some but no wallet is counted. Hours rebuilt from fills rather than read from snapshots are null. An unknown token is refused. Used by view: history.
  • cohorts returns {size, pnl, tier}, each a list of labels in ladder order (pnl also holds unknown, wallets under 10 closed trades). Every cohort parameter on every tool accepts exactly these strings.
  • segments returns one row per bucket with axis, cohort, slug, rank, basis, applies_to, groupable, the bounds (min_usd, max_usd, percentile_min, percentile_max) and min_closed_trades. It is how a client learns that the pnl ladder is a percentile rank of cumulative realized PnL, not dollars, and that pnl_abs is dollars over the same PnL. groupable is false for trade_size, which buckets a position rather than a wallet.
  • summary returns everything one cohort holds across all symbols: total_long_usd, total_short_usd, total_value, bias, n_positions, n_wallets, n_wallets_in_profit, pct_wallets_in_profit, total_margin_used, total_equity, exposure_ratio (notional over margin used, the cohort's realized leverage), total_unrealized_pnl and a by_side block. total_equity is the cohort's whole-account value, not the part backing the positions counted.
  • heatmap returns {axis, opened_within, snapshot_ts, source, totals, heatmap}: one row per symbol, ordered by total notional, each carrying its totals, bias and a segments list of the cohorts that hold anything in it. Empty cells are omitted rather than sent as zeros. It covers every symbol with open interest, so it is a large response.
  • history returns one cohort hour by hour, summed over all symbols, newest first, from 2026-04-07: {axis, cohort, label_basis, data_from, series, has_more} plus label_computed, and leverage under include=leverage. cohort and axis are both required, and axis is size or pnl only. A series row carries ts, long_usd and short_usd in USD, bias = (long - short) / (long + short), a fraction from -1 to +1 that is null when both are 0, and position_count, the number of open positions, not wallets. Each hour carries the cohort label it had then (label_basis is point_in_time; pnl labels are daily before 2026-08-06, and label_computed says so). hours sizes the window, limit caps the rows and has_more says older rows exist: page back with end set to the oldest ts minus one second. include=leverage adds to every row perp_bias, equity_exposure and equity_covered_share, the three summary ratios of that hour, native perp account only; they are null before 2026-08-11 and for a missing hour. An unknown cohort for the axis is an error.

axis is size, pnl or pnl_abs on summary and heatmap, and size or pnl on history; the per-position tier ladder is refused there and is available on hl_cohort_metrics.

Which Hyperliquid cohorts are the most net short right now?

Show how every cohort on the pnl ladder is positioned in SOL.

On this page