> ## 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.

# rwa_hyperliquid.perp_trades

> Taker-leg fills on RWA perpetual markets, covering Hyperliquid HIP-3 builder-deployed perps, with per-fill trader leverage and margin mode.

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>;

`rwa_hyperliquid.perp_trades` is the fill table for RWA perpetual futures — synthetic exposure to a real-world asset with no tokenized share involved. Grain: one taker-leg fill per row, keyed on `(block_month, block_date, unique_key)`. It covers Hyperliquid HIP-3 builder-deployed markets.

<PremiumDatasetAccessCard />

## Taker leg only

Each row represents the taker leg of a fill. As a result, `SUM(notional_usd)` matches the volume Hyperliquid reports for the market without double-counting both sides.

## Leverage and margin, per fill

Three columns carry the trader's risk posture at fill time, and nothing else in the RWA catalog has them — not even the pre-aggregated metrics tables:

| Column | What it tells you |
| - | - |
| `leverage` | The trader's leverage on the position at the moment of the fill |
| `margin_mode` | Whether the trader held the position `cross` or `isolated` |
| `leverage_setting` | Whether that leverage was chosen by the trader or inherited from the market default |

## Table schema

| Column | Type | Description |
| - | - | - |
| `block_month` | `DATE` | Partition column |
| `block_date` | `DATE` | Fill date |
| `block_time` | `TIMESTAMP(3) WITH TIME ZONE` | Fill timestamp |
| `block_number` | `BIGINT` | Block height |
| `perp_dex` | `VARCHAR` | Builder DEX short code |
| `coin` | `VARCHAR` | Full market id in `dex:SYMBOL` form, e.g. `xyz:TSLA` |
| `market_symbol` | `VARCHAR` | Market ticker within the builder DEX |
| `asset_id` | `INTEGER` | HIP-3 asset id. **Join key to `rwa_hyperliquid.markets.asset_id`** |
| `side` | `VARCHAR` | `buy` or `sell`, from the taker's perspective |
| `price` | `DOUBLE` | Fill price |
| `size` | `DOUBLE` | Fill size in contract units |
| `notional_usd` | `DOUBLE` | USD notional of the fill |
| `fill_type` | `VARCHAR` | `order`, `twap`, `liquidation`, `adl` (auto-deleveraging), or `settlement` |
| `builder_name` | `VARCHAR` | Builder DEX full name |
| `trader` | `VARCHAR` | Taker address |
| `leverage` | `INTEGER` | Trader's leverage on the position at fill time. Always populated |
| `margin_mode` | `VARCHAR` | `cross` or `isolated` — what the trader actually used for this position |
| `leverage_setting` | `VARCHAR` | `explicit` when the trader set leverage themselves, `market_default` when they never did |
| `dir` | `VARCHAR` | Hyperliquid direction string, e.g. Open Long, Close Short |
| `fee` | `DOUBLE` | Protocol fee paid |
| `builder_fee` | `DOUBLE` | Fee routed to the builder |
| `deployer_fee` | `DOUBLE` | Fee routed to the market deployer |
| `twap_id` | `BIGINT` | TWAP order identifier, for `fill_type = 'twap'` |
| `liquidation_method` | `VARCHAR` | Liquidation mechanism, for `fill_type = 'liquidation'` |
| `liquidation_liquidated_user` | `VARCHAR` | Account that was liquidated |
| `liquidation_mark_px` | `DOUBLE` | Mark price at liquidation |
| `oid` | `BIGINT` | Order identifier |
| `tid` | `BIGINT` | Trade identifier |
| `unique_key` | `VARCHAR` | Row identifier |
| `_updated_at` | `TIMESTAMP(3) WITH TIME ZONE` | When this row was last refreshed |

<Warning>
  `asset_id` is `INTEGER` here, so it joins to `rwa_hyperliquid.markets.asset_id` with no cast. Do **not** join it to `markets.token_address`, which is the same value typed as `VARCHAR`.

  A perp has no `token_id` and never joins to `rwa_multichain.tokens` — there is no token behind it.
</Warning>

## fill\_type matters for volume

Liquidations, auto-deleveraging (`adl`), and market-delisting `settlement` fills are not discretionary trading. `order` fills dominate, followed by `twap`, with forced closes a small tail. Keep only user-initiated fills when measuring genuine trading demand:

```sql theme={null}
WHERE fill_type IN ('order', 'twap')
```

TWAP fills are one order sliced into many small fills, so they inflate trade counts far more than volume — the fill count runs orders of magnitude above the number of distinct orders behind it. Count distinct `twap_id` rather than rows if you want order-level counts.

## Getting asset class

This table has no `asset_class`. Join [`rwa_hyperliquid.markets`](/data-catalog/curated/rwa/registry/hyperliquid-markets) for classification, issuer, and leverage caps:

```sql theme={null}
SELECT
  m.asset_class,
  m.underlying_ticker,
  p.builder_name,
  COUNT(*) AS fills,
  SUM(p.notional_usd) AS volume_usd
FROM rwa_hyperliquid.perp_trades p
JOIN rwa_hyperliquid.markets m
  ON m.asset_id = p.asset_id
WHERE p.block_date >= current_date - INTERVAL '7' day
  AND p.fill_type IN ('order', 'twap')
GROUP BY 1, 2, 3
ORDER BY 5 DESC
LIMIT 25
```

## leverage\_setting decides whether leverage is a choice

`market_default` fills use Hyperliquid's default of `min(20, max_leverage)` rather than trader-selected leverage.

Filter to `explicit` whenever you are measuring trader risk appetite — mixing the two makes the default look like a popular choice:

```sql theme={null}
WHERE leverage_setting = 'explicit'
```

## margin\_mode here is the trader's choice, not the market's rule

Two different columns share this name, and they mean different things:

* `rwa_hyperliquid.markets.margin_mode` is the regime the **deployer** set for the market: `cross`, `noCross`, or `strictIsolated`.
* `perp_trades.margin_mode` is what the **trader** actually used on that position: `cross` or `isolated`.

A market with `margin_mode = 'cross'` permits both, and in practice sees both — traders on cross-enabled markets still pick isolated a meaningful share of the time. A `noCross` or `strictIsolated` market only ever produces `isolated` fills. So the market-level column tells you what was allowed and the trade-level column tells you what was chosen; they are not interchangeable.

## Example query

```sql theme={null}
-- Leverage distribution by asset class, trader-chosen leverage only
SELECT
  m.asset_class,
  t.margin_mode,
  COUNT(*) AS fills,
  APPROX_PERCENTILE(t.leverage, 0.5) AS median_leverage,
  APPROX_PERCENTILE(t.leverage, 0.95) AS p95_leverage,
  SUM(t.notional_usd) AS volume_usd
FROM rwa_hyperliquid.perp_trades t
JOIN rwa_hyperliquid.markets m
  ON m.asset_id = t.asset_id
WHERE t.block_date >= current_date - INTERVAL '7' day
  AND t.block_date < current_date
  AND t.leverage_setting = 'explicit'
  AND t.fill_type IN ('order', 'twap')
GROUP BY 1, 2
ORDER BY 6 DESC
```

**Was leverage elevated going into a liquidation cluster?**

```sql theme={null}
SELECT
  block_date,
  market_symbol,
  COUNT(*) FILTER (WHERE fill_type = 'liquidation') AS liquidations,
  APPROX_PERCENTILE(leverage, 0.5) AS median_leverage_all_fills,
  SUM(notional_usd) FILTER (WHERE fill_type = 'liquidation') AS liquidated_notional_usd
FROM rwa_hyperliquid.perp_trades
WHERE block_date >= current_date - INTERVAL '30' day
  AND block_date < current_date
GROUP BY 1, 2
HAVING COUNT(*) FILTER (WHERE fill_type = 'liquidation') > 0
ORDER BY 5 DESC
LIMIT 50
```

<Note>
  For pre-aggregated volume, open interest, and funding rather than raw fills, use [`perp_metrics_hourly`](/data-catalog/curated/rwa/activity/perp-metrics-hourly) or [`perp_metrics_daily`](/data-catalog/curated/rwa/activity/perp-metrics-daily). Neither carries leverage — this table is the only source for it.
</Note>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.