Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/blockchain/BSC/binance-memerush-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -953,7 +953,7 @@ subscription {
Quote
Usd
}
marketcap: calculate(expression: "Price_Average_Mean * 1000000000")
marketcap: calculate(expression: "$Price_Average_Mean * 1000000000")
Price {
Average {
Mean
Expand Down Expand Up @@ -1123,7 +1123,7 @@ subscription {
Quote
Usd
}
marketcap: calculate(expression: "Price_Average_Mean * 1000000000")
marketcap: calculate(expression: "$Price_Average_Mean * 1000000000")
Price {
Average {
Mean
Expand Down
4 changes: 2 additions & 2 deletions docs/blockchain/BSC/four-meme-api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1175,7 +1175,7 @@ subscription {
Quote
Usd
}
marketcap: calculate(expression: "Price_Average_Mean * 1000000000")
marketcap: calculate(expression: "$Price_Average_Mean * 1000000000")
Price {
Average {
Mean
Expand Down Expand Up @@ -1402,7 +1402,7 @@ subscription {
Quote
Usd
}
marketcap: calculate(expression: "Price_Average_Mean * 1000000000")
marketcap: calculate(expression: "$Price_Average_Mean * 1000000000")
Price {
Average {
Mean
Expand Down
2 changes: 1 addition & 1 deletion docs/blockchain/Ethereum/nft/nft-transfer-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ This query fetches the most frequently transferred NFTs on the Ethereum Blockcha
EVM(dataset: combined network: eth){
Transfers(
orderBy: {descendingByField: "count"}
limit: {offset: 10 count: 0}
limit: {offset: 10 count: 100}
where: {
Block: {Date: {since: "2023-05-02" till: "2023-05-09" }}
Transfer: {Currency: {Fungible: false}}}
Expand Down
19 changes: 18 additions & 1 deletion docs/graphql/calculations.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,21 @@ description: "GraphQL Calculations and Expressions in Bitquery GraphQL with clea
Attributes ```maximum``` ```minimum``` ```where``` can be appended to an element in query.
They convert the value to the metric, calculated by the following rules:

* if ```maximum``` or ```minimum``` is added, then the value of the element corresponds to max / min of the provided argument
* if ```maximum``` or ```minimum``` is added, the element returns **its own value on the row where the provided argument is maximal / minimal**. This is an *argmax*, not the maximum of the argument itself: `Number(maximum: Block_GasUsed)` returns the block **number** of the highest-gas block, not the gas figure.
* if ```where``` attribute is defined, then the value of element is taken with the provided condition
* if ```where``` attribute is used with any of ```maximum``` or ```minimum```, then max / min taken conditionally

:::caution On Trading cubes the argument is `if`, not `where`
Field-level `where:` is **rejected** on the `Trading` cubes with
`Unknown argument "where"`. Use `if:` instead, which takes the same filter shape:

```
Price { Ohlc { Close(maximum: Block_Time if: {Trade: {Side: {is: "Buy"}}}) } }
```

The always-true-`where` tip below therefore does not apply to Trading cubes.
:::

## Examples

Maximum block number:
Expand All @@ -37,6 +48,12 @@ Number of the block with the maximum gas used in specific date:
```
Number(maximum: Block_GasUsed where: {Block: {Date:{is: "2022-01-01"}}})
```

:::note Selectors sharing one key resolve to the same row
Several selectors keyed on the **same** argument all read from that one row, so they are mutually
consistent. Mixing keys is what breaks coherence: `Open(minimum: Block_Time)` and
`High(maximum: Price_Ohlc_High)` come from two different rows by design.
:::
:::tip
Use ```where``` with some always-true condition (say, ChainId equal 1) to get **any** value of element
:::
Expand Down
13 changes: 12 additions & 1 deletion docs/graphql/capabilities/array-intersect.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,18 @@ where
Constraints:

- Applicable only to fields with a string data type.
- The function can retrieve only addresses when returning the response; other response fields are not supported in the output.
- Any string-typed field works, not only addresses — DEX market names and protocol families
intersect just as well, and `intersectWith` likewise accepts non-address strings.
- Other response fields **are** supported in the output. Metrics (`count`, `uniq`, `sum`,
`median`) and dimensions (for example `Pair { Market { Name } }` or `Block { Date }`) can be
selected alongside the intersection and come back populated — which is what makes per-group
intersections useful.

:::caution `where` must admit every member of `intersectWith`
The intersection is computed over rows the `where` clause already admits. If the filter excludes
any member of `intersectWith`, that member contributes nothing and the result silently shrinks
rather than erroring. Make sure the `where` clause spans every element you are intersecting on.
:::

### Example

Expand Down
13 changes: 13 additions & 0 deletions docs/graphql/capabilities/expression.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,16 @@ subscription {
}
}
```

:::caution In subscriptions every field reference needs a `$` prefix
Inside a **subscription**, each field reference in an expression must carry the `$` sigil.
A single unsigiled token makes the whole expression return `null` — silently, with no error —
so a mixed expression such as `"$Price_Ohlc_Close - Price_Ohlc_Open"` fails just as completely
as a fully bare one.

Subscriptions also support **arithmetic operators only**. Function calls — `round()`, `floor()`,
`abs()`, `plus()`, `greatest()` — evaluate to `null` in a stream while working normally in a
query. Aliased results can still be referenced and chained (`$diff`).

Queries are unaffected: bare field names and function calls both work there.
:::
8 changes: 4 additions & 4 deletions docs/graphql/data-coverage-retention.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,14 @@ Windows are expressed as rolling ranges, not fixed dates, so they stay correct o
| `Transfers` | ✅ **~12 hours** | via S3 | ✅ | Deep history via S3 export. |
| `Instructions` | ✅ **~12 hours** | — | ✅ | Deep historical instruction lookup by signature is not available via API. |
| `InstructionBalanceUpdates` | ✅ **~12 hours** | — | ✅ | |
| `BalanceUpdates` | ✅ **~7 days** | — | ✅ | Solana has no `Balances` cube; balance changes are queried here. |
| `DEXPools` | ✅ **~7 days** | — | ✅ | Pool events are realtime; not in archive. |
| `BalanceUpdates` | ✅ **~12 hours** | — | ✅ | Solana has no `Balances` cube; balance changes are queried here. |
| `DEXPools` | ✅ **~12 hours** | — | ✅ | Realtime only. The `archive` / `combined` datasets do not exist for this cube — a query against them errors with `no API tables for cube DEXPool`. For historical pool state use a [cloud export](/docs/cloud/). |
| `Transactions` / `Blocks` / `Rewards` / `DEXOrders` / `TokenSupplyUpdates` | ✅ **~12 hours** | — | ✅ | |

:::warning Two Solana cubes carry the same trades with very different depth
`DEXTrades` retains roughly **12 hours**; `DEXTradeByTokens` retains roughly **7 days** — about 15× longer, from the same underlying trades. The same split applies to `InstructionBalanceUpdates` (~12 h) versus `BalanceUpdates` (~7 days).
`DEXTrades` retains roughly **12 hours**; `DEXTradeByTokens` retains roughly **7 days** — about 15× longer, from the same underlying trades.

The pattern is that aggregate-shaped cubes retain much longer than raw per-event cubes. If a Solana query "loses" older data, check whether an aggregate cube covers the same question before assuming the history is gone.
That pair is the exception, not a general rule: **every other Solana realtime cube measured here holds roughly 12 hours**, including `BalanceUpdates`, `DEXPools`, `Transfers`, `Instructions` and `TokenSupplyUpdates`. If a Solana query "loses" older data, check whether `DEXTradeByTokens` or an archive dataset covers the same question before assuming the history is gone.
:::

### Tron & Bitcoin
Expand Down
45 changes: 43 additions & 2 deletions docs/graphql/metrics/if.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,51 @@ count(distinct: Block_Number if: {Block: {GasUsed: {gt: "0"}}})
```

:::note
```if``` attribute is universally applied to all metrics ad have the same structure as
[filters](/docs/graphql/filters)
The ```if``` attribute has the same structure as [filters](/docs/graphql/filters), and applies to
almost all metrics — see the exceptions below.
:::

## Example: buy and sell statistics in one row

`if:` is what lets you split a group without splitting the query. On the Trading cube:

```graphql
{
Trading {
Trades(
where: { Pair: { Market: { Network: { is: "Solana" } } }, Block: { Time: { since: "...", till: "..." } } }
limitBy: { by: Trader_Address, count: 1 }
limit: { count: 100 }
) {
Trader { Address }
buys: count(if: { Side: { is: "Buy" } })
sells: count(if: { Side: { is: "Sell" } })
bought: sum(of: AmountsInUsd_Quote, if: { Side: { is: "Buy" } })
sold: sum(of: AmountsInUsd_Quote, if: { Side: { is: "Sell" } })
PnL: calculate(expression: "$sold - $bought")
}
}
}
```

`if:` also accepts **string dimensions that the `of:` / `with:` arguments reject**, so it is the
escape hatch that makes much of the metric surface usable on categorical columns.

## Exceptions and limits

:::warning `any:` inside `if:` crashes the request
Nesting an `any:` combinator inside an `if:` filter returns
`runtime error: invalid memory address or nil pointer dereference`. Express the alternation a
different way — usually as two separate aliased metrics.
:::

Three metrics do **not** accept `if:` at all: `gini`, `nakamoto` and `theil_index`. Every other
metric, including `entropy`, does.

Combining `if:` with [`selectWhere`](/docs/graphql/metrics/selectWhere) gives a conditional
HAVING — filtering groups on a **slice** of their own data, such as wallets whose buy-side
volume alone clears a threshold.

:::tip
Use [Aliases](/docs/graphql/metrics/alias) to name these metrics
:::
Expand Down
65 changes: 60 additions & 5 deletions docs/graphql/metrics/selectWhere.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,71 @@ description: "Select By Metric in Bitquery GraphQL with clear syntax, examples,
---
# Select By Metric

Metric value can be used to filter out the result by ```selectIf``` attribute to
define the condition applied for results.
This way you can filter the results by the metirc values.
A metric value can be used to filter the result with the ```selectWhere``` attribute,
which defines a condition applied to the **computed metric** rather than to the input rows.
It is the GraphQL equivalent of SQL's `HAVING`.

This expression filters the balances just by positive values:
This expression filters balances to positive values only:
```
sum(of: BalanceUpdate_Amount selectWhere: {gt: "0"})
```

## Where it applies in the pipeline

`selectWhere` runs **after** aggregation and **before** ordering and limiting, so a filtered
result is complete rather than a filtered page:

```
where → GROUP BY → selectWhere (HAVING) → orderBy → limitBy → limit
```

This matches ClickHouse's own clause order, and it determines what `limitBy` means: `limitBy`
takes the top N per key **from the rows that already passed `selectWhere`**. A key with fewer
than N survivors simply returns fewer rows — it is not padded with rows that are then filtered
away.

## Operators

The operator set depends on **what you attach `selectWhere` to** — there are four shapes:

| Attached to | Type | Operators |
| --- | --- | --- |
| An aggregate metric (`sum`, `count`, `median`, …) | `Metric_filter_String` / `_Float` | `gt` `ge` `lt` `le` `eq` `ne` |
| A **numeric** field-level selector | `OLAP_Float` | the same six |
| A **string** field-level selector | `OLAP_String` | the full 15-operator string set — `like`, `startsWith`, `includes`, `not`, … |
| A boolean leaf field | `Boolean` | a bare value: `selectWhere: true` |

There is **no `between`** on any of them. Multiple clauses in one `selectWhere` are combined
with AND, so express a range with `ge` and `le` together:

```
sum(of: Volume_Usd selectWhere: {ge: "10000" le: "1000000"})
```

`in` and `notIn` are absent from the metric filters. They appear in the `OLAP_String` schema but
**fail at runtime**, so use `like` / `startsWith` instead, or move set membership into the cube's
own `where:` clause where `in` is supported normally.

## Literal types

The literal type matches the **metric's own return type**. `sum`, `count` and `uniq` return JSON
strings and therefore take string literals; every Float-returning metric takes a numeric literal.
Passing the wrong one is a clean schema error, not a silent failure.

String literals are compared **numerically, not lexicographically** — `"100"` is greater than
`"20"`.

:::note
You can combine this attribute with other attributes, including conditions in ```if```
You can combine this attribute with other attributes, including conditions in ```if```.
Combining `if` and `selectWhere` on the same metric gives a conditional HAVING — for
example, filtering to wallets whose **buy-side** volume alone exceeds a threshold.
:::

:::caution Not available on every field, and not on streams
On a bare field that has no selector argument, `selectWhere` is accepted and is a
**silent no-op** — it neither filters nor errors. Attach it to a metric.

`selectWhere` is **not available in subscriptions**. See
[what does not survive streaming](/docs/subscriptions/what-does-not-survive-streaming/).
:::

20 changes: 16 additions & 4 deletions docs/graphql/metrics/statistics.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,24 @@ Elements that calculate different statistics with the self-descriptive names:

* ```covariance``` value of Σ((x - x̅)(y - y̅)) / n
* ```correlation``` pearson correlation coefficient: Σ((x - x̅)(y - y̅)) / sqrt(Σ((x - x̅)^2) * Σ((y - y̅)^2))
* ```contingency``` calculates the [contingency coefficient](https://en.wikipedia.org/wiki/Contingency_table#Cram%C3%A9r's_V_and_the_contingency_coefficient_C), a value that measures the association between two columns in a table. The computation is similar to the cramersV function but with a different denominator in the square root
* ```rank_correlation``` rank correlation coefficient of the ranks of x and y. The value of the correlation coefficient ranges from -1 to +1. If less than two arguments are passed, the function will return an exception. The value close to +1 denotes a high linear relationship, and with an increase of one random variable, the second random variable also increases. The value close to -1 denotes a high linear relationship, and with an increase of one random variable, the second random variable decreases. The value close or equal to 0 denotes no relationship between the two random variables.
* ```contingency``` calculates the [contingency coefficient](https://en.wikipedia.org/wiki/Contingency_table#Cram%C3%A9r's_V_and_the_contingency_coefficient_C), a value that measures the association between two columns in a table. The computation is similar to the cramersV function but with a different denominator in the square root. **Note that this coefficient does not reach 1 even for a near-deterministic relationship** — its maximum depends on the dimensions of the underlying table. On data where `cramers` approaches 1, this coefficient sits well below it. Do not read it on a 0–1 scale or compare it directly with Cramér's V; for association strength prefer `cramers_bias_corrected`
* ```rank_correlation``` rank correlation coefficient of the ranks of x and y. The value of the correlation coefficient ranges from -1 to +1. The value close to +1 denotes a high linear relationship, and with an increase of one random variable, the second random variable also increases. The value close to -1 denotes a high linear relationship, and with an increase of one random variable, the second random variable decreases. The value close or equal to 0 denotes no relationship between the two random variables.
* ```cramers``` [Cramér's V](https://en.wikipedia.org/wiki/Cram%C3%A9r%27s_V) (sometimes referred to as Cramér's phi) is a measure of association between two columns in a table. The result of the cramers function ranges from 0 (corresponding to no association between the variables) to 1 and can reach 1 only when each value is completely determined by the other. It may be viewed as the association between two variables as a percentage of their maximum possible variation.
* ```cramers_bias_corrected``` Cramér's V is a measure of association between two columns in a table. The result of the cramersV function ranges from 0 (corresponding to no association between the variables) to 1 and can reach 1 only when each value is completely determined by the other. The function can be heavily biased, so this version of Cramér's V uses the bias correction.
* ```theils``` calculates the [Theil's U uncertainty coefficient](https://en.wikipedia.org/wiki/Contingency_table#Uncertainty_coefficient), a value that measures the association between two columns in a table. Its values range from −1.0 (100% negative association, or perfect inversion) to +1.0 (100% positive association, or perfect agreement). A value of 0.0 indicates the absence of association.
* ```theils_corrected``` calculates the [Theil's U uncertainty coefficient](https://en.wikipedia.org/wiki/Contingency_table#Uncertainty_coefficient), a value that measures the association between two columns in a table. A value of 0.0 indicates the absence of association, and the magnitude grows towards 1.0 as association strengthens.
:::caution The metric is named `theils_corrected`, not `theils`
Querying `theils` fails with `Cannot query field "theils"`. Note also that a strong association returns a value near **−1**, not +1 — interpret magnitude, not sign.
:::

The following are also available and are not listed above:

* ```gini``` Gini coefficient of the values — 0 is perfectly even, 1 is fully concentrated
* ```theil_index``` Theil index, an entropy-based concentration measure
* ```entropy``` Shannon entropy of the value distribution, in bits
* ```nakamoto``` the number of rows that together account for `ratio` of the total of `of` (takes `ratio`, not `if`)
* ```skew```, ```kurtosis```, ```dispersion```, ```median```, ```quantile``` distribution shape and position

:::tip
You can use [condition](/docs/graphql/metrics/if) to any of these metrics
You can use a [condition](/docs/graphql/metrics/if) on any of these metrics **except
`gini`, `nakamoto` and `theil_index`**, which do not accept an `if` argument.
:::
Loading
Loading