Skip to main content

PoolPrice fields

What it is​

Trading.Pairs carries two prices for each liquidity pool:

  • Price is the traded price: OHLC built from the swaps in the interval.
  • PoolPrice is the pool's own price: what the pool's curve quotes at its current liquidity, after the last swap the pool reported.

PoolPrice is a marginal price, not an executed one. On a thin liquidity pool it sits beyond the traded close by that swap's price impact, so it legitimately differs from Price.Ohlc.Close on the same row. On deep liquidity pools the two agree within a percent.

PoolPrice is on Pairs only. Tokens and Currencies have no pool price: a token's price is a blend of its pools, and the token row's LeadingPool names the pool whose price counts most.

How to get it​

Select PoolPrice { … } on Trading.Pairs next to Price, in queries and subscriptions. Filter on PoolPrice.Source to keep only rows that have a pool price.

The same values are on the trading.prices Kafka topic as PairUpdate.PoolPriceUpdate (see Kafka).

How it is derived​

The price is read from the pool's state after each pool event. PoolPrice.Source says where:

SourceRead fromWhere
tableThe spot of the pool's slippage tableEVM
eventThe post-swap state the venue's swap event reportsSolana
reservesQuote reserve divided by base reserve of a constant-product poolSolana constant-product venues, such as pump AMM
"" (empty)No pool pricePools that report no price state

Unit. PoolPrice follows the row's unit exactly like Price: USD on rows where Price.IsQuotedInUsd is true (the default), quote tokens per base token when you filter Price: {IsQuotedInUsd: false}.

OHLC. Open is the close of the previous interval. High and Low are the extremes the curve quoted after a swap inside the interval, so on a thin pool they sit beyond the traded High and Low by each swap's own impact.

Not blended. The pool price belongs to one pool. The token's blended price stays the index; see the Price Index Algorithm.

Fields​

FieldTypeMeaning
PoolPrice.PriceFloatThe pool's price at the end of the row's interval. Equals PoolPrice.Ohlc.Close.
PoolPrice.Ohlc { Open High Low Close }FloatThe pool price over the row's interval.
PoolPrice.Average { Mean SimpleMoving WeightedSimpleMoving ExponentialMoving }FloatAverages over the last five intervals of this length.
PoolPrice.SourceStringtable, event or reserves, above. Empty when the pool has no price.
PoolPrice.UpdatedAtDateTimeTime of the pool event the price came from. On EVM it can trail the row's block by a few seconds. On Solana it equals the block time.

When PoolPrice is empty​

Not every pool reports a price. When it does not, PoolPrice.Price, Ohlc, Average and UpdatedAt are null and Source is "". Filter on PoolPrice.Source to keep only priced rows, as the examples below do.

Examples​

Pool price candles next to traded candles​

The WETH/USDC Uniswap v3 liquidity pool on Ethereum, 1-minute bars for the last 30 minutes. PoolPrice.Ohlc and Price.Ohlc come back on the same row.

Run query ➤

query PoolPriceVsTradeCandles {
Trading {
Pairs(
limit: {count: 30}
orderBy: {descending: Interval_Time_Start}
where: {
Pool: {Address: {is: "0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640"}}
Interval: {Time: {Duration: {eq: 60}}}
Block: {Time: {since_relative: {minutes_ago: 30}}}
}
) {
Interval { Time { Start Duration } }
Token { Symbol }
QuoteToken { Symbol }
PoolPrice {
Source
UpdatedAt
Ohlc { Open High Low Close }
}
Price {
Ohlc { Open High Low Close }
}
}
}
}

Does a liquidity pool have a pool price?​

Returns the latest hour with a pool price. An empty list means the pool has none. Do not add a time bound here: the pool address alone is the fast path.

Run query ➤

query HasPoolPrice {
Trading {
Pairs(
limit: {count: 1}
orderBy: {descending: Interval_Time_Start}
where: {
Pool: {Address: {is: "0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640"}}
Interval: {Time: {Duration: {eq: 3600}}}
PoolPrice: {Source: {not: ""}}
}
) {
Interval { Time { Start } }
PoolPrice { Price Source UpdatedAt }
}
}
}

Pool price in quote tokens​

SOL's liquidity pools on Solana, priced in quote tokens per SOL instead of USD. Source: {is: "event"} keeps pools whose price comes from the venue's swap event.

Run query ➤

query PoolPriceInQuoteTokens {
Trading {
Pairs(
limit: {count: 10}
orderBy: {descending: Interval_Time_Start}
where: {
Token: {Id: {is: "bid:solana:So11111111111111111111111111111111111111112"}}
Price: {IsQuotedInUsd: false}
Interval: {Time: {Duration: {eq: 60}}}
Block: {Time: {since_relative: {minutes_ago: 5}}}
PoolPrice: {Source: {is: "event"}}
}
) {
Market { Protocol }
Pool { Address }
QuoteToken { Symbol }
PoolPrice { Price Source UpdatedAt }
Price { Ohlc { Close } }
}
}
}

Stream the pool price live​

The same where works on a subscription. A pair whose pool never prices sends nothing when filtered on Source.

Run query ➤

subscription PoolPriceLive {
Trading {
Pairs(
where: {
Pool: {Address: {is: "0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640"}}
Interval: {Time: {Duration: {eq: 60}}}
PoolPrice: {Source: {not: ""}}
}
) {
Interval { Time { Start } }
PoolPrice { Price Source UpdatedAt }
Price { Ohlc { Close } }
}
}
}

Pool price of one Uniswap v4 liquidity pool​

Uniswap v4 and other singleton designs share one manager address across many pools. Add Pool: {Id: {is: …}} to select one pool. This is LSK/ETH on Ethereum, with the pool price's moving averages.

Run query ➤

query PoolPriceUniswapV4Pool {
Trading {
Pairs(
limit: {count: 10}
orderBy: {descending: Interval_Time_Start}
where: {
Pool: {
Address: {is: "0x000000000004444c5dc75cb358380d2e3de08a90"}
Id: {is: "0x6af632b8235f1a9d95a816f7a4090736346b763a8ab4e8327017aaae72d0d1d2"}
}
Interval: {Time: {Duration: {eq: 60}}}
Block: {Time: {since_relative: {minutes_ago: 30}}}
}
) {
Interval { Time { Start } }
Market { Protocol Id }
Token { Symbol }
QuoteToken { Symbol }
PoolPrice {
Price
Source
UpdatedAt
Average { Mean SimpleMoving WeightedSimpleMoving ExponentialMoving }
}
Price { Ohlc { Close } }
}
}
}

Kafka: trading.prices​

The pool price is on the trading.prices topic from protobuf v2.6.8, defined in market/price_index.proto. It is on PairUpdate only, not on token, currency or trade messages.

MessageFieldNumberUnit
PairUpdatePoolPriceUpdate PoolPriceUpdate13USD
PairUpdatePoolPriceUpdate PoolPriceUpdateInQuoteTokens14Quote tokens per base token

PoolPriceUpdate:

FieldTypeNumberMeaning
Pricefloat1The latest pool price, the close of the shortest interval.
Sourcestring2table, event or reserves, as in GraphQL.
UpdatedAtuint323Unix second of the pool event the price was read from.
PriceByTimeIntervalsrepeated PriceByTimeInterval4The pool price over each interval, one entry per interval of PriceUpdate.PriceByTimeIntervals on the same PairUpdate, matched by TimeInterval. Ohlc and the moving averages are set; Amounts, MeanPrice and Ohlc.Volume are not, because a pool price has no volume.

Differences from GraphQL:

  • PoolPriceUpdate is absent when the pool has no priced state. The USD one is also absent when the quote currency has no USD rate. Check HasField before reading.
  • UpdatedAt is a unix second, not a DateTime.

Archive columns​

Rows of the Trading.Pairs cube in the parquet archive (pairs_by_token_id, pairs_by_currency_id, pairs_by_token_address, pairs_by_pool_address, pairs_by_interval_start) carry the same values as twelve columns:

ColumnTypeMeaning
PoolPrice_PriceFloat32The pool's price at the end of the row's interval, in the row's unit. Equals PoolPrice_Ohlc_Close.
PoolPrice_Ohlc_Open / _High / _Low / _CloseFloat32The pool price over the row's interval.
PoolPrice_Average_Mean / _SimpleMoving / _WeightedSimpleMoving / _ExponentialMovingFloat32Moving averages over the pool price of the last five intervals of this length. PoolPrice_Average_Estimate is always 0.
PoolPrice_SourceLowCardinality(String)table, event or reserves. Empty when there is no pool price.
PoolPrice_UpdatedAtUInt32Unix second of the pool event the price was read from.

The unit follows the row, like the Price_* columns: USD when Price_IsQuotedInUsd = 1, quote tokens per base token otherwise. A row with no pool price has PoolPrice_Price = 0 and an empty PoolPrice_Source, not NULL.

Build with Bitquery

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.