トークンの日次 DEX OHLC と VWAP(厳密な分数付き)
Data API から日次 DEX OHLC 価格と VWAP を照会し、TypeScript と Python で厳密な有理分数を処理し、過去データを効率的にバックフィルします。
What the DEX daily prices dataset is
BlockVectra の DEX データセットは、分散型取引所での取引アクティビティをインデックス化し、集計された日次価格指標を計算します。DEX 日次価格エンドポイント(getDexPrices)は、指定された日付範囲における指定トークンの日次出来高加重平均価格(VWAP)、価格指標(first_price、last_price、min_price、max_price フィールド)、および出来高指標を提供します。
このデータセットの提供状況はネットワークによって異なります。このデータセットを提供するチェーンについては、対応チェーンページを参照してください。
このエンドポイントはページネーションされません。要求された日付範囲内のすべての一致する日次行が data 内に直接返され、next_cursor は一切存在しません。日次集計ではなく詳細なスワップトランザクションをアプリケーションが必要とする場合は、GET /{chain}/dex/swaps を使用してください(Data API リファレンスを参照)。
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 -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"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 倍精度浮動小数点数に依存しており、精度の限界が存在します:
- 浮動小数点の切り捨てと誤差の蓄積:Float64 の値は 53 ビットの精度しか提供せず、トークン数量の除算では計算を重ねるごとに丸め誤差が蓄積します。
- 送信の安全性:値を 10 進数文字列(
UInt256String)としてフォーマットすることで、JSON パーサーで精度を損なうことなく数値が HTTP 経由で転送されます。
価格指標に対して厳密な整数の分子と分母を提供することで、BlockVectra は浮動小数点変換を行わずに厳密な数学的計算を可能にします。
Handling exact fractions in TypeScript (BigInt)
TypeScript では、浮動小数点変換を行わずに、ネイティブの BigInt を使用してたすき掛けによる比較や固定小数点変換を実行できます:
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 を提供しています。
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 日間の連続したウィンドウに分割し、チャンク化されたリクエストを発行します:
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 / call- 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。
バックフィル量を拡張する場合や、より高いリクエスト同時実行数が必要な場合は、コンソールの請求ページでオンチェーンチャージを行い、有料アカウントにアップグレードしてください。有効な料金レートとユニット換算については、料金ページを参照してください。
Next steps
- データセットディレクトリを見ると、BlockVectra がインデックスしているすべてのデータセットを確認できます。
- 無料プランと料金を見ると、アカウントに含まれる内容を確認できます。
- コンソールにログインして、API key を作成してください。
最終更新: