# トークンの日次 DEX OHLC と VWAP（厳密な分数付き）

> Source: https://docs.blockvectra.com/ja/guides/dex-daily-prices/

## What the DEX daily prices dataset is

BlockVectra の DEX データセットは、分散型取引所での取引アクティビティをインデックス化し、集計された日次価格指標を計算します。DEX 日次価格エンドポイント（`getDexPrices`）は、指定された日付範囲における指定トークンの日次出来高加重平均価格（VWAP）、価格指標（`first_price`、`last_price`、`min_price`、`max_price` フィールド）、および出来高指標を提供します。

このデータセットの提供状況はネットワークによって異なります。このデータセットを提供するチェーンについては、[対応チェーン](https://docs.blockvectra.com/en/chains/)ページを参照してください。

このエンドポイントはページネーションされません。要求された日付範囲内のすべての一致する日次行が `data` 内に直接返され、`next_cursor` は一切存在しません。日次集計ではなく詳細なスワップトランザクションをアプリケーションが必要とする場合は、`GET /{chain}/dex/swaps` を使用してください（[Data API リファレンス](https://docs.blockvectra.com/en/api/data/)を参照）。

## Request parameters and limits

エンドポイントのルートは `GET https://api.blockvectra.com/v1/data/{chain}/dex/prices` です。すべてのリクエストにおいて、`x-api-key` ヘッダーに API key を指定して認証を行う必要があります。

このエンドポイントは以下のクエリパラメータを受け付けます：

| Parameter | Location | Type        | Required | Description                                                  |
| --------- | -------- | ----------- | -------- | ------------------------------------------------------------ |
| `chain`   | path     | string      | Yes      | チェーン識別子（例：`robinhood_mainnet`）                               |
| `token`   | query    | string      | Yes      | 20 バイトのベーストークンアドレス（`0x` は任意、大文字小文字不問）                        |
| `quote`   | query    | string      | No       | 特定のベース/クォートペアに限定するための任意の 20 バイトクォートトークンアドレス                  |
| `from`    | query    | date string | Yes      | UTC 開始日（当日含む）、`YYYY-MM-DD`                                   |
| `to`      | query    | date string | Yes      | UTC 終了日（当日含む）、`YYYY-MM-DD`。`to - from` は `<= 90` 日である必要があります |

### Constraints and error codes

リクエストが制約に違反した場合、API は構造化されたエラーボディ `{"error":{"code","message"}}` を返します：

* **HTTP 400 (`bad_request`)**：必須クエリパラメータ（`token`、`from`、`to`）の不足、無効な `token`/`quote` アドレス構文、無効な `YYYY-MM-DD` カレンダー日付、または `from` が `to` より後である場合。
* **HTTP 409 (`span_exceeded`)**：`to - from` が 90 日を超えている場合。
* **HTTP 404 (`unknown_chain`)**：`{chain}` が `GET /chains` にリストされているチェーンではない場合。
* **HTTP 422 (`no_coverage`)**：チェーンが `dex_prices` データセット機能に対応していない場合。
* **HTTP 503 (`unavailable`)**：サービスが一時的に利用不可。`Retry-After` ヘッダーに従って再試行してください。

## Request examples

以下の例では、2026 年 9 月のベーストークンの日次 DEX 価格を照会します：

**cURL**

```bash
curl -s "https://api.blockvectra.com/v1/data/robinhood_mainnet/dex/prices?token=0x1Cdad396DB64BDa184d5182A97Dd9B3C62100b7D&from=2026-09-01&to=2026-09-30" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY"
```


  **TypeScript**

```ts
const url = new URL("https://api.blockvectra.com/v1/data/robinhood_mainnet/dex/prices");
url.searchParams.set("token", "0x1Cdad396DB64BDa184d5182A97Dd9B3C62100b7D");
url.searchParams.set("from", "2026-09-01");
url.searchParams.set("to", "2026-09-30");

const res = await fetch(url, {
  headers: {
    "x-api-key": process.env.BLOCKVECTRA_API_KEY!,
  },
});

if (!res.ok) {
  throw new Error(`Request failed with status ${res.status}`);
}

const body = await res.json();
console.log(body);
```


  **Python**

```python
import os
import requests

res = requests.get(
    "https://api.blockvectra.com/v1/data/robinhood_mainnet/dex/prices",
    params={
        "token": "0x1Cdad396DB64BDa184d5182A97Dd9B3C62100b7D",
        "from": "2026-09-01",
        "to": "2026-09-30",
    },
    headers={
        "x-api-key": os.environ["BLOCKVECTRA_API_KEY"],
    },
)
res.raise_for_status()
print(res.json())
```


## Detailed field reference

`data` 内の各エントリは、その UTC 日付におけるトークンペアの集計された日次 DEX 指標を表します：

### Token and quote assets

* `day` (string)：`YYYY-MM-DD` 形式の UTC 日付。
* `token` (string)：先頭に `0x` が付いた小文字の 16 進数表記の 20 バイトのベーストークンアドレス。
* `token_symbol` (string または `null`)：ベーストークンのシンボル。
* `token_name` (string または `null`)：ベーストークンの表示名。
* `quote_token` (string)：クォート資産のアドレス。すべてゼロのアドレス（`0x0000000000000000000000000000000000000000`）は、クォート資産としてのネイティブ ETH を表します。
* `quote_symbol` (string または `null`)：クォート資産のシンボル（`quote_token` が全ゼロアドレスの場合は `"ETH"`）。
* `quote_name` (string または `null`)：クォート資産の表示名（`quote_token` が全ゼロアドレスの場合は `"Ether"`）。
* `base_decimals` (integer または `null`)：ベーストークンの小数点桁数（0〜255）。
* `quote_decimals` (integer または `null`)：クォート資産の小数点桁数（`quote_token` が全ゼロアドレスの場合は `18`）。

### Volume and trade counts

* `swap_count` (integer)：この行のスワップ回数。
* `base_volume_raw` (string)：符号なし整数の 10 進数文字列（`UInt256String`）としての原子単位ベース出来高。
* `quote_volume_raw` (string)：符号なし整数の 10 進数文字列（`UInt256String`）としての原子単位クォート出来高。
* `base_volume` (string または `null`)：`DecimalString` として `base_decimals` でスケールされた可読なベーストークン出来高。`base_decimals` が不明な場合は `null`。
* `quote_volume` (string または `null`)：`DecimalString` としてクォートの小数点桁数でスケールされたクォート出来高、または `null`。

### Price indicators and VWAP

* `vwap` (string または `null`)：`DecimalString` としての出来高加重平均価格、または `null`。
* `first_price` (string または `null`)：`DecimalString` としての始値指標、または `null`。
* `last_price` (string または `null`)：`DecimalString` としての終値指標、または `null`。
* `min_price` (string または `null`)：`DecimalString` としての最安値指標、または `null`。
* `max_price` (string または `null`)：`DecimalString` としての最高値指標、または `null`。

### Exact fraction fields

* `first_price_numerator` / `first_price_denominator` (string)：`first_price` の厳密な整数の分子と分母（`UInt256String`）。
* `last_price_numerator` / `last_price_denominator` (string)：`last_price` の厳密な整数の分子と分母（`UInt256String`）。
* `min_price_numerator` / `min_price_denominator` (string)：`min_price` の厳密な整数の分子と分母（`UInt256String`）。
* `max_price_numerator` / `max_price_denominator` (string)：`max_price` の厳密な整数の分子と分母（`UInt256String`）。
* `refreshed_at` (string)：この行の更新タイムスタンプ（ISO-8601 UTC タイムスタンプ）。

### Envelope metadata (`meta`)

* `chain`：チェーン識別子。
* `chain_slug`：大文字の正規チェーンスラッグ。
* `chain_external_id`：CAIP-2 形式のチェーン識別子。
* `as_of_block`：チェーンの完全に書き込まれた最新ブロック（このデータセットによって報告され、リクエストパラメータとは照合されません）。
* `coverage`：対応範囲の分類（このエンドポイントでは `"full"` を報告）。
* `refreshed_at`：メタデータの更新タイムスタンプ。`null` の場合があります：`null` はこのデータの更新時刻が不明であり、古くなったデータとして扱う必要があることを意味します。ブロックベースのエンドポイントは常に値を返します。

## Why prices use exact numerators and denominators

標準的な JSON の数値は IEEE-754 倍精度浮動小数点数に依存しており、精度の限界が存在します：

1. **浮動小数点の切り捨てと誤差の蓄積**：Float64 の値は 53 ビットの精度しか提供せず、トークン数量の除算では計算を重ねるごとに丸め誤差が蓄積します。
2. **送信の安全性**：値を 10 進数文字列（`UInt256String`）としてフォーマットすることで、JSON パーサーで精度を損なうことなく数値が HTTP 経由で転送されます。

価格指標に対して厳密な整数の分子と分母を提供することで、BlockVectra は浮動小数点変換を行わずに厳密な数学的計算を可能にします。

### Handling exact fractions in TypeScript (BigInt)

TypeScript では、浮動小数点変換を行わずに、ネイティブの `BigInt` を使用してたすき掛けによる比較や固定小数点変換を実行できます：

```ts
interface DexDailyPrice {
  first_price_numerator: string;
  first_price_denominator: string;
  last_price_numerator: string;
  last_price_denominator: string;
}

// 1. Ratio comparison without floating-point conversion: check if close price is higher than open price
// a / b > c / d  is equivalent to  a * d > c * b
export function isPriceUp(row: DexDailyPrice): boolean {
  const openNum = BigInt(row.first_price_numerator);
  const openDen = BigInt(row.first_price_denominator);
  const closeNum = BigInt(row.last_price_numerator);
  const closeDen = BigInt(row.last_price_denominator);

  return closeNum * openDen > openNum * closeDen;
}

// 2. Convert fraction to a fixed-point decimal string with arbitrary scale (without floating-point loss)
export function fractionToFixedString(
  numeratorStr: string,
  denominatorStr: string,
  decimals = 18
): string {
  const num = BigInt(numeratorStr);
  const den = BigInt(denominatorStr);
  if (decimals === 0) {
    return (num / den).toString();
  }
  const scaleFactor = 10n ** BigInt(decimals);

  const scaled = (num * scaleFactor) / den;
  const intPart = scaled / scaleFactor;
  const remainder = scaled % scaleFactor;
  const fracPart = remainder.toString().padStart(decimals, "0");

  return `${intPart}.${fracPart}`;
}
```

### Handling exact fractions in Python

Python は、有理数および 10 進数の計算専用に構築された標準ライブラリモジュール `fractions.Fraction` および `decimal.Decimal` を提供しています。

```python
from decimal import Decimal, getcontext
from fractions import Fraction

# 1. Exact rational calculations with fractions.Fraction
open_price = Fraction(
    int(row["first_price_numerator"]),
    int(row["first_price_denominator"])
)
close_price = Fraction(
    int(row["last_price_numerator"]),
    int(row["last_price_denominator"])
)

# Exact price delta without floating-point rounding error
price_delta = close_price - open_price
print(f"Price delta (fraction): {price_delta}")

if open_price != 0:
    percentage_change = (price_delta / open_price) * 100
    print(f"Percentage change: {float(percentage_change):.4f}%")

# 2. Arbitrary-precision decimal arithmetic with decimal.Decimal
getcontext().prec = 50

if int(row["first_price_denominator"]) != 0:
    open_decimal = Decimal(row["first_price_numerator"]) / Decimal(row["first_price_denominator"])
    print(f"High-precision open: {open_decimal}")
```

## Backfilling one year of daily prices

90 日間の期間制限内で 1 年分のデータ（365 日）をバックフィルするには、日付範囲全体を最大 90 日間の連続したウィンドウに分割し、チャンク化されたリクエストを発行します：

```ts
interface DateSpan {
  from: string;
  to: string;
}

/**
 * Split a large date range into consecutive spans of at most maxDays (default: 90)
 */
export function splitDateRange(startDateStr: string, endDateStr: string, maxDays = 90): DateSpan[] {
  const spans: DateSpan[] = [];
  let currentStart = new Date(startDateStr);
  const end = new Date(endDateStr);

  while (currentStart <= end) {
    const chunkEnd = new Date(currentStart);
    chunkEnd.setUTCDate(chunkEnd.getUTCDate() + (maxDays - 1));
    const effectiveEnd = chunkEnd < end ? chunkEnd : end;

    spans.push({
      from: currentStart.toISOString().slice(0, 10),
      to: effectiveEnd.toISOString().slice(0, 10),
    });

    const nextStart = new Date(effectiveEnd);
    nextStart.setUTCDate(nextStart.getUTCDate() + 1);
    currentStart = nextStart;
  }

  return spans;
}

/**
 * Backfill token daily prices across multiple 90-day chunks
 */
export async function backfillTokenDailyPrices(
  chain: string,
  token: string,
  startDate: string,
  endDate: string,
  apiKey: string
) {
  const chunks = splitDateRange(startDate, endDate, 90);
  const allDailyPrices = [];

  for (const chunk of chunks) {
    const url = new URL(`https://api.blockvectra.com/v1/data/${chain}/dex/prices`);
    url.searchParams.set("token", token);
    url.searchParams.set("from", chunk.from);
    url.searchParams.set("to", chunk.to);

    const res = await fetch(url, {
      headers: { "x-api-key": apiKey },
    });

    if (!res.ok) {
      throw new Error(`Failed to fetch span ${chunk.from}..${chunk.to}: HTTP ${res.status}`);
    }

    const json = await res.json();
    allDailyPrices.push(...json.data);
  }

  return allDailyPrices;
}
```

## Capacity and CU usage calculations

Data API のすべてのエンドポイントは、消費量を Compute Units（CU）単位で計測します。`data.dex_prices` のコールあたりの CU 重み付けと、トークンバックフィルの推定消費量は以下のように計算されます：

- **メソッドの重み付け：** `data.dex_prices` = 15 CU / コール。
- **200 トークンの 1 年分の日次価格をバックフィル：** リクエストあたりの最大範囲は 90 日であり、365 日分をカバーするにはトークンあたり 5 チャンク、合計 1,000 回の呼び出しが必要です。総消費量は 15,000 CU（無料プランのサイクル枠の約 <0.1%）、定価換算で約 <$0.01。
- **日常のメンテナンス（毎日 200 トークンを 1 回更新）：** 200 コール/日（3,000 CU/日）、30 日のサイクルあたり約 6,000 コール（90,000 CU、無料枠の約 0.3%）、定価換算で月額約 <$0.01。

バックフィル量を拡張する場合や、より高いリクエスト同時実行数が必要な場合は、コンソールの[請求ページ](https://console.blockvectra.com/billing/)でオンチェーンチャージを行い、有料アカウントにアップグレードしてください。有効な料金レートとユニット換算については、[料金ページ](https://blockvectra.com/en/pricing/)を参照してください。

## Next steps

* [データセットディレクトリを見る](https://blockvectra.com/en/data/)と、BlockVectra がインデックスしているすべてのデータセットを確認できます。
* [無料プランと料金を見る](https://blockvectra.com/en/pricing/#free)と、アカウントに含まれる内容を確認できます。
* [コンソールにログイン](https://console.blockvectra.com/login/?next=%2Fkeys%2F)して、API key を作成してください。
