Hyperliquid HIP-3 Stocks API
HIP-3 lets anyone deploy a perpetual market on Hyperliquid. In practice that has produced a full off-chain asset complex trading on-chain: S&P 500, Nasdaq-100, individual US equities, country ETFs, gold, oil, natural gas and FX — all as perps settled in USDC on HyperCore.
Bitquery indexes every HIP-3 market alongside the native perps, in the same Hyperliquid
cube. This page covers how to address those markets, and the queries that matter for
pricing, market making and basis trading against the underlying.
The video ranks the HIP-3 stock, index and commodity perps by volume and by number of traders over one week.
To query or stream data outside the Bitquery IDE, you need an API access token.
Follow the steps here: How to generate Bitquery API token ➤
How HIP-3 markets are addressed
Every market carries a Market object. Three fields identify a HIP-3 market:
| Field | Native perp | HIP-3 market |
|---|---|---|
Kind | perp | hip3 |
Protocol | hypercore | the deployer, e.g. xyz, io, para, mkts, hyna |
CoinRaw | BTC | xyz:SP500 — deployer:symbol |
Symbol | BTC | SP500 — the bare symbol |
Two consequences worth knowing before you write a filter:
Symbolis not unique across deployers.SNDKtrades under bothxyz:andio:,AVGOunder bothxyz:andpara:,UNITREEunderxyz:andpara:. Filter onCoinRawwhen you mean one specific market, and onSymbolonly when you deliberately want every deployer's version of the same underlying.- Filter the whole asset class with
Kind, not with aProtocolallowlist. New deployers appear without notice;Kind: {is: "hip3"}keeps working.
List every HIP-3 market
Ranks all HIP-3 markets by USD volume over the last 24 hours, with trade and distinct trader counts. Every match has a maker row and a taker row, so volume and trades count the taker side only. This is the discovery query — run it first to see what exists right now.
Run it in the IDE: Hyperliquid HIP-3 Markets ➤
query {
Hyperliquid {
Trades(
limit: {count: 300}
orderBy: {descendingByField: "volumeUsd"}
where: {
Trade: {Market: {Kind: {is: "hip3"}}}
Block: {Time: {since_relative: {hours_ago: 24}}}
}
) {
Trade {
Market { Symbol CoinRaw Protocol }
}
volumeUsd: sum(of: Trade_Execution_NotionalUSD, if: {Trade: {Execution: {IsAggressor: true}}})
trades: count(if: {Trade: {Execution: {IsAggressor: true}}})
traders: count(distinct: Trade_Trader_Address)
}
}
}
Swap Kind for Protocol: {is: "xyz"} to scope to a single deployer.
Trades on a stock market
Every fill on xyz:SP500, both sides of each match. IsAggressor marks the taker, and a
negative Fee is a maker rebate. Execution.Index is the fill's place in its block (all
fills of a block share Block.Time), and Position.Size the account's position after the fill.
Run it in the IDE: Hyperliquid SP500 Perp Trades ➤
query {
Hyperliquid {
Trades(
limit: {count: 50}
orderBy: {descending: [Block_Time, Trade_Execution_Index]}
where: {Trade: {Market: {CoinRaw: {is: "xyz:SP500"}}}}
) {
Block { Time }
Trade {
Market { Symbol CoinRaw Kind Protocol }
Execution { Price Size Side Direction IsAggressor Index Oid Tid }
Fees { Fee FeeToken BuilderFee }
Position { Leverage IsCross SizeBefore Size RealizedPnl }
Trader { Address }
}
}
}
}
Change CoinRaw to any market from the discovery query — xyz:NVDA, xyz:TSLA,
xyz:GOLD, mkts:USTECH, io:GPRO.
Mark prices across all HIP-3 markets
MarkPrices is a latest-state cube: one row per market holding its current mark, not a
time series. Use it for a pricing snapshot; use Candles or Trades for history.
Run it in the IDE: Hyperliquid HIP-3 Mark Prices ➤
query {
Hyperliquid {
MarkPrices(
limit: {count: 200}
orderBy: {descending: LastTime}
where: {Market: {Kind: {is: "hip3"}}}
) {
LastTime
LastBlock
Mark
Market { Symbol CoinRaw Protocol }
}
}
}
Note the field names differ from the other cubes: LastTime / LastBlock rather than
Block { Time }, and the price is Mark.
Basis: on-chain mark vs off-chain reference
This is the query behind the HIP-3 arbitrage trade. PriceUpdates carries the oracle feed
the market is priced against, and Kind separates the components:
Kind | Meaning |
|---|---|
spotInput | the off-chain reference price for the underlying |
markInput | the input to the on-chain mark |
mark | the published mark price |
oracle | the published oracle price |
extPerpInput | external perp reference, where used |
extPerp | the published external perp price |
Because spotInput is indexed alongside the mark, the basis is computable from Bitquery
alone — you do not need to bring your own equities feed just to measure the spread.
Run it in the IDE: Hyperliquid HIP-3 Basis Spread ➤
query {
Hyperliquid {
PriceUpdates(
limit: {count: 100}
orderBy: {descending: Block_Time}
where: {PriceUpdate: {Market: {CoinRaw: {is: "xyz:NVDA"}}}}
) {
Block { Time }
PriceUpdate {
Market { Symbol CoinRaw }
Kind
Price
DailyPx
UpdateClass
UpdateTime
}
}
}
}
Pair the spotInput series with Trades on the same market to see where fills landed
relative to the reference, which is what decides whether a basis trade was actually
capturable rather than just visible.
OHLCV candles for a stock perp
Candles are pre-aggregated. Interval.Time.Duration is in seconds — 60 for 1m,
300 for 5m, 900 for 15m, 3600 for 1h.
Run it in the IDE: Hyperliquid Stock Perp Candles ➤
query {
Hyperliquid {
Candles(
limit: {count: 60}
orderBy: {descending: Interval_Time_Start}
where: {
Market: {CoinRaw: {is: "xyz:NVDA"}}
Interval: {Time: {Duration: {eq: 60}}}
}
) {
Interval { Time { Start Duration } }
Market { Symbol CoinRaw }
Ohlc { Open High Low Close Volume }
}
}
}
If you need an interval the Candles cube does not carry, aggregate Trades directly. Keep
the taker side only, as Candles does, or every match counts twice in volume. open and
close come from the first and last block of the interval; the fills of one block share
Block_Time, so they can differ from the Candles values, which order fills by Execution.Index.
Run it in the IDE: Hyperliquid HIP-3 OHLC From Trades ➤
query {
Hyperliquid {
Trades(
limit: {count: 100}
orderBy: {descendingByField: "interval_Time"}
where: {
Trade: {Market: {CoinRaw: {is: "xyz:SP500"}}, Execution: {IsAggressor: true}}
Block: {Time: {since_relative: {hours_ago: 24}}}
}
) {
interval: Block { Time(interval: {in: minutes, count: 30}) }
open: Trade { Execution { Price(minimum: Block_Time) } }
high: Trade { Execution { Price(maximum: Trade_Execution_Price) } }
low: Trade { Execution { Price(minimum: Trade_Execution_Price) } }
close: Trade { Execution { Price(maximum: Block_Time) } }
volume: sum(of: Trade_Execution_Size)
trades: count
}
}
}
L4 order book for a stock perp
BookUpdates are per-order deltas, not aggregated price levels. Each row names the
order id and the wallet behind it, so you can reconstruct the book at any instant and
measure queue position, order lifetime and maker behaviour.
Run it in the IDE: Hyperliquid Stock Book Updates ➤
subscription {
Hyperliquid {
BookUpdates(
where: {BookUpdate: {Market: {CoinRaw: {is: "xyz:NVDA"}}}}
) {
Block { Time }
BookUpdate {
Market { Symbol CoinRaw }
Kind
Side
Px
Size
SizeBefore
Oid
Trader { Address }
}
}
}
}
Kind is new, update or remove. Size is empty on a remove — the order is
gone, so there is no resting size to report; use Px, Side and Oid to find the level
it left. Change subscription to query and add limit / orderBy for history: without a
Block: {Time: ...} filter the query covers the last 30 minutes, and about 7 days are kept.
Funding on HIP-3 markets
Funding is per trader, per market, and settles hourly. Rate is the funding rate applied
and Amount the USDC paid or received.
Run it in the IDE: Hyperliquid HIP-3 Funding ➤
query {
Hyperliquid {
PerpFundings(
limit: {count: 50}
orderBy: {descending: Block_Time}
where: {Funding: {Market: {Kind: {is: "hip3"}}}, Block: {Time: {since_relative: {hours_ago: 2}}}}
) {
Block { Time }
Funding {
Market { Symbol CoinRaw Protocol }
Trader { Address }
Rate
Amount
Size
}
}
}
}
Equity perps have no natural funding anchor overnight or at weekends, when the underlying market is closed. Funding is where that dislocation shows up, so this series is worth watching if you carry HIP-3 positions across a session boundary.
Liquidations on HIP-3 markets
Run it in the IDE: Hyperliquid HIP-3 Liquidations ➤
query {
Hyperliquid {
PerpLiquidations(
limit: {count: 50}
orderBy: {descending: [Block_Time, Liquidation_Execution_Index]}
where: {Liquidation: {Market: {Kind: {is: "hip3"}}}}
) {
Block { Time }
Liquidation {
Market { Symbol CoinRaw Protocol }
LiquidatedUser
Liquidator
MarkPx
Method
Trader { Address }
Execution { Price Size Side Index }
Position { Leverage SizeBefore Size RealizedPnl }
}
}
}
}
Method distinguishes a market liquidation from a backstop one. Both sides of a forced fill
are listed with the same LiquidatedUser: the row whose Trader.Address equals it is the
liquidated account's own fill, the others are the accounts that took the other side. Sign a fill
by Execution.Side (Buy adds, Sell subtracts).
Top traders on a stock market
Ranks wallets by traded size on one market, with realized PnL. Useful for copy-trading, market-maker identification and flow analysis.
Run it in the IDE: Hyperliquid HIP-3 Top Traders ➤
query {
Hyperliquid {
Trades(
limit: {count: 50}
orderBy: {descendingByField: "volume"}
where: {
Trade: {Market: {CoinRaw: {is: "xyz:SP500"}}}
Block: {Time: {since_relative: {hours_ago: 24}}}
}
) {
Trade { Trader { Address } }
volume: sum(of: Trade_Execution_Size)
trades: count
pnl: sum(of: Trade_Position_RealizedPnl)
}
}
}
Field notes
- Prices and sizes are decimal strings, not floats, in every cube except
Candles(whoseOhlcfields are floats). Parse withDecimalwhere precision matters. - A match produces two
Tradesrows, one per counterparty. Key a trade on(Block.Number, Market.CoinRaw, Execution.Tid)— not onHash, which spans many matches and is all zeroes on both sides of a TWAP fill.Tidis a hash, not a sequence: to order the fills of a block, useExecution.Index(orderBy: {descending: [Block_Time, Trade_Execution_Index]}). Position.SizeBeforeandPosition.Sizeare signed position sizes before and after the fill, negative for short. They are not money; realized PnL isPosition.RealizedPnl.Directiontakes values likeOpen Long,Close ShortandShort > Long— a flip through flat is one fill, not two.- Retention. These cubes are served from realtime with roughly a 30-day window (about
7 days for
Orders,BookUpdatesandSignedActions). For longer ranges, see Data Coverage & Retention. For older data, ask about a Data Store export.
Related
Ready to run this in production?
Get an API key and run these queries in minutes, or talk to us about plans and enterprise delivery.