> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dune.com/llms.txt
> Use this file to discover all available pages before exploring further.

# hyperliquid.perp_trades

> One row per fill leg on Hyperliquid perpetual futures, covering both sides of every match across first-party and HIP-3 builder-deployed markets.

export const PremiumDatasetAccessCard = ({href = "https://dune.com/enterprise#contact-form", note = null}) => <Card title="Gated dataset" icon="lock" href={href}>
    Querying this dataset requires an entitlement on your workspace. See <a href="/data-catalog/overview#access-tiers-public-vs-gated-datasets">access tiers</a>, or contact the Dune team to enable access.
    {note && <><br /><br />{note}</>}
  </Card>;

`hyperliquid.perp_trades` is the fill table for Hyperliquid perpetual futures, venue-wide: first-party markets (`coin` = `BTC`) and HIP-3 builder-deployed markets (`coin` = `xyz:TSLA`) alike. Grain: one row per fill **leg** — both sides of every match — keyed on `(block_date, coin, trader, oid, tid)`, with `tid` shared by the two legs of a match. Spot and HIP-4 outcome markets are out of scope.

<PremiumDatasetAccessCard />

Fills are decoded from the full node fills stream rather than from taker order actions (`fills_raw`), which misses every engine-generated fill — TWAP child slices and liquidation executions — worth 5-30% of volume. History starts 2025-07-27 and runs at roughly 8.75M legs per day across the 417 coins that have traded (as of 2026-08-21).

## Table schema

| Column                   | Type                          | Description                                                                                                                    |
| ------------------------ | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `block_month`            | `DATE`                        | Month of `block_date`, for month-grain grouping. Not the partition key                                                         |
| `block_date`             | `DATE`                        | Partition key, and the only column that prunes                                                                                 |
| `block_time`             | `TIMESTAMP(3) WITH TIME ZONE` | Block time of the fill                                                                                                         |
| `block_number`           | `BIGINT`                      | Block height                                                                                                                   |
| `event_index`            | `INTEGER`                     | Position of the leg within the block; the two legs of a match sit at consecutive indices                                       |
| `perp_dex`               | `VARCHAR`                     | `hyperliquid` for first-party markets, otherwise the builder DEX code (`xyz`, `flx`, `para`, …)                                |
| `coin`                   | `VARCHAR`                     | Venue-native market id: `BTC` (first-party), `xyz:TSLA` (HIP-3). Join key to `perp_market_details`                             |
| `market_symbol`          | `VARCHAR`                     | `coin` with the `dex:` prefix stripped. Not unique across dexes — never join on it                                             |
| `asset_id`               | `BIGINT`                      | Numeric asset id used by the raw Hyperliquid action tables. `NULL` when a market traded before the registry poller recorded it |
| `trader`                 | `VARBINARY`                   | The account on this leg, as raw bytes rather than a hex string                                                                 |
| `is_taker`               | `BOOLEAN`                     | Aggressor flag. Exactly one leg per match has it set                                                                           |
| `side`                   | `VARCHAR`                     | `buy` or `sell` from this leg's perspective                                                                                    |
| `dir`                    | `VARCHAR`                     | Raw Hyperliquid direction string, e.g. `Open Long`, `Close Short` — the position effect, not the order side                    |
| `fill_type`              | `VARCHAR`                     | Normalised leg role: `order`, `twap`, `liquidation`, `adl`, `settlement`, `vault_netting`                                      |
| `start_position`         | `DOUBLE`                      | Signed position size immediately before this fill                                                                              |
| `price`                  | `DOUBLE`                      | Fill price, in the market's quote token (see `fee_token`)                                                                      |
| `size`                   | `DOUBLE`                      | Fill size in base units                                                                                                        |
| `notional_usd`           | `DOUBLE`                      | `price * size`. Sums to \~2x reported volume unless you filter `is_taker`                                                      |
| `closed_pnl_usd`         | `DOUBLE`                      | Realised PnL on this leg; non-zero on closes                                                                                   |
| `fee_usd`                | `DOUBLE`                      | This leg's fee, in `fee_token`. Negative on maker rebates                                                                      |
| `builder_fee_usd`        | `DOUBLE`                      | Front-end / builder-code fee share, populated on \~6% of legs                                                                  |
| `deployer_fee_usd`       | `DOUBLE`                      | HIP-3 deployer fee share                                                                                                       |
| `fee_token`              | `VARCHAR`                     | Quote / collateral token the prices and fees are denominated in. Not always USDC                                               |
| `priority_gas`           | `DOUBLE`                      | HYPE spent in the priority-gas auction. Sparse                                                                                 |
| `tid`                    | `BIGINT`                      | Match id, shared by both legs — the pairing key                                                                                |
| `oid`                    | `BIGINT`                      | Order id, globally unique                                                                                                      |
| `cloid`                  | `VARCHAR`                     | Client order id where the trader set one                                                                                       |
| `builder`                | `VARBINARY`                   | Builder (front-end) address, populated on \~6% of legs                                                                         |
| `twap_id`                | `BIGINT`                      | TWAP order id, set only on the taker leg. Group by it to reconstruct an executed schedule                                      |
| `liquidation_method`     | `VARCHAR`                     | `market` or `backstop`. Set on both legs of the match — use `fill_type` for the role                                           |
| `liquidated_trader`      | `VARBINARY`                   | The account that was liquidated. Also present on both legs                                                                     |
| `liquidation_mark_price` | `DOUBLE`                      | Mark price at liquidation                                                                                                      |
| `_updated_at`            | `TIMESTAMP(3) WITH TIME ZONE` | Build timestamp. Legs are immutable, so in practice when the leg was first written                                             |

<Warning>
  Bound `block_date` on every query. It is the partition key and the only column that prunes: `block_month` is a plain column, so filtering it alone reads every day in the month, and nothing prunes *within* a day — a `coin` filter still scans the full partition. An unbounded scan reads the whole multi-billion-row history.
</Warning>

## Both legs are here, so filter is\_taker for volume

`SUM(notional_usd)` over this table is \~2x exchange-reported volume, because every match contributes a taker leg and a maker leg. Filtering `is_taker` counts each match once. For pre-aggregated volume, use [`perp_market_metrics_hourly`](/data-catalog/curated/perpetuals/hyperliquid/perp-market-metrics-hourly) or [`perp_market_metrics_daily`](/data-catalog/curated/perpetuals/hyperliquid/perp-market-metrics-daily), which are the volume source of truth.

```sql theme={null}
-- Traded volume per market, single-counted
SELECT
  block_date,
  coin,
  SUM(notional_usd) AS volume_usd,
  COUNT(*) AS trades
FROM hyperliquid.perp_trades
WHERE block_date >= current_date - INTERVAL '7' day
  AND block_date < current_date
  AND is_taker
  AND fill_type NOT IN ('settlement', 'vault_netting')
GROUP BY 1, 2
ORDER BY 3 DESC
```

Do **not** filter `is_taker` when the question is per-account: at account grain each leg is one account's own participation, which is also why [`perp_accounts_daily`](/data-catalog/curated/perpetuals/hyperliquid/perp-accounts-daily) aggregates both legs. The same applies to `closed_pnl_usd` — maker-side closes carry realised PnL too, and a taker-only filter drops roughly 40% of it.

## fill\_type

`fill_type` is the leg's role, normalised from `dir`, `liquidation_method`, `is_taker` and `twap_id`.

| Value           | Leg role                                                                                                          |
| --------------- | ----------------------------------------------------------------------------------------------------------------- |
| `order`         | A voluntary order fill, including the resting order hit by an ordinary liquidation                                |
| `twap`          | The leg belongs to a TWAP child slice; always the taker                                                           |
| `liquidation`   | This leg's account was force-closed for undercollateralisation                                                    |
| `adl`           | This leg's account was the profitable side force-closed by auto-deleveraging                                      |
| `settlement`    | Engine force-close of all open positions when a builder DEX delists a market: one price, one timestamp, zero fees |
| `vault_netting` | Vault position netting (`dir = 'Net Child Vaults'`), not a trade at all                                           |

`settlement` and `vault_netting` are administrative and belong in no volume or activity measure. `liquidation` and `adl` are genuine risk transfers at market prices, but they are forced, so include them only when the question covers forced flow.

TWAP legs inflate fill counts far more than volume — one parent order becomes many slices. Count `DISTINCT twap_id` for order-level figures.

## Liquidation columns mark the match, not the role

<Warning>
  `liquidation_method` and `liquidated_trader` are stamped on **both** legs of a liquidation match. Counting rows where `liquidation_method IS NOT NULL` therefore doubles the answer: measured 2026-08-12, 17,044 legs carried a method while only 8,522 accounts were liquidated. Use `fill_type = 'liquidation'` for the forced leg.
</Warning>

The roles depend on the method. On `market` (ordinary) liquidations the liquidated account is the taker and its counterparty is a plain `order` leg. On `backstop` (auto-deleveraging) the roles invert: the bankrupt account is the maker leg with `fill_type = 'liquidation'`, and the profitable account force-closed against it is the taker, with `fill_type = 'adl'`.

## side is the order direction, dir is the position effect

The two legs of a match always carry opposite `side` values. `dir` is not symmetric that way: it describes what the fill did to this leg's own position — `Open Long`, `Close Short`, `Long > Short` — so a `Close Long` fill has `side = 'sell'`. Use `side` for order flow, `dir` or `start_position` for position intent. Perp scope carries exactly 13 `dir` values, verified across full fill history; an unrecognised value lands in `fill_type = 'order'` until the model is taught it.

## Fees

`fee_usd` is negative on maker rebates, so summing it across all legs yields net protocol revenue; add `is_taker` for gross taker fees. `builder_fee_usd` is populated together with `builder` on the \~6% of legs routed through a front-end, and `deployer_fee_usd` only on HIP-3 markets.

All three are denominated in `fee_token`, which is not always USDC — a HIP-3 DEX picks its own quote token, and USDC, USDT0, USDH and USDE all appear across history. They are USD-pegged, which is what keeps the `_usd` column names honest, but a fee on a USDH market is paid in USDH.

## Not in this table

Curated classification — `market_category`, `asset_class`, `asset_type`, `underlying_ticker`, `builder_name` — is deliberately kept off this table so a reclassification does not rewrite billions of rows. Join [`perp_market_details`](/data-catalog/curated/perpetuals/hyperliquid/perp-market-details) on `coin` for it, along with the market-level `max_leverage`, `margin_tiers` and `margin_mode`.

Per-fill leverage and margin mode are absent by design: both are a per-`(user, asset)` account setting rather than a property of a fill, and the venue-wide models do not reconstruct them.
