ราคา DEX OHLC และ VWAP รายวันสำหรับโทเค็น พร้อมเศษส่วนแม่นยำสูง

คิวรีราคา DEX OHLC และ VWAP รายวันจาก Data API, จัดการเศษส่วนตรรกยะที่แม่นยำใน TypeScript และ Python ตลอดจนดึงข้อมูลย้อนหลังอย่างมีประสิทธิภาพ

ชุดข้อมูลราคา DEX รายวันคืออะไร

ชุดข้อมูล DEX ของ BlockVectra ทำดัชนีกิจกรรมการซื้อขายบนกระเป๋าเงินและตลาดซื้อขายแบบกระจายศูนย์ (DEX) และคำนวณเมตริกราคาแบบสรุปรายวัน endpoint ราคา DEX รายวัน (getDexPrices) ให้บริการราคาเฉลี่ยถ่วงน้ำหนักด้วยปริมาณการซื้อขายรายวัน (VWAP), ตัวชี้วัดราคา (ฟิลด์ first_price, last_price, min_price และ max_price) ตลอดจนเมตริกปริมาณการซื้อขายสำหรับโทเค็นที่ระบุในช่วงวันที่กำหนด

ความพร้อมใช้งานของชุดข้อมูลนี้จะแตกต่างกันไปตามแต่ละเครือข่าย; เชนที่ให้บริการชุดข้อมูลนี้เป็นไปตามหน้ารายการ เชนที่รองรับ

endpoint นี้ไม่มีการแบ่งหน้า (pagination): แถวข้อมูลรายวันทั้งหมดที่ตรงกันภายในช่วงวันที่ที่ร้องขอจะถูกส่งกลับโดยตรงใน data และจะไม่มี next_cursor ปรากฏ หากแอปพลิเคชันของคุณต้องการธุรกรรม swap แบบละเอียดรายธุรกรรมแทนที่จะเป็นข้อมูลสรุปรายวัน ให้ใช้ GET /{chain}/dex/swaps (ดู ข้อมูลอ้างอิง Data API)

พารามิเตอร์และขีดจำกัดของคำขอ

เส้นทาง endpoint คือ GET https://api.blockvectra.com/v1/data/{chain}/dex/prices ทุกคำขอต้องมีการยืนยันตัวตนโดยส่ง API key ของคุณในส่วนหัว x-api-key

endpoint รองรับ query parameter ดังต่อไปนี้:

พารามิเตอร์ตำแหน่งประเภทจำเป็นคำอธิบาย
chainpathstringใช่ตัวระบุเชน เช่น robinhood_mainnet
tokenquerystringใช่แอดเดรส base token ขนาด 20 ไบต์, ใส่ 0x หรือไม่ก็ได้, ตัวพิมพ์เล็กหรือใหญ่ก็ได้
quotequerystringไม่แอดเดรส quote token ขนาด 20 ไบต์ (ระบุหรือไม่ก็ได้) เพื่อจำกัดเฉพาะคู่ base/quote เดียว
fromquerydate stringใช่วันที่เริ่มต้นตามเวลา UTC (รวมวันนั้นด้วย), รูปแบบ YYYY-MM-DD
toquerydate stringใช่วันที่สิ้นสุดตามเวลา UTC (รวมวันนั้นด้วย), รูปแบบ YYYY-MM-DD โดย to - from ต้อง <= 90 วัน

ข้อจำกัดและรหัสข้อผิดพลาด

เมื่อคำขอละเมิดข้อจำกัด 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

ตัวอย่างคำขอ

ตัวอย่างต่อไปนี้จะคิวรีราคา DEX รายวันสำหรับ base token ตลอดช่วงเดือนกันยายน 2026:

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"

ข้อมูลอ้างอิงฟิลด์โดยละเอียด

แต่ละรายการใน data แสดงถึงเมตริก DEX รายวันแบบสรุปสำหรับคู่โทเค็นในวันที่นั้นตามเวลา UTC:

สินทรัพย์โทเค็นและ quote

  • day (string): วันที่ตามเวลา UTC ในรูปแบบ YYYY-MM-DD
  • token (string): แอดเดรส base token ขนาด 20 ไบต์ในรูปแบบเลขฐานสิบหกนำหน้าด้วย 0x ตัวพิมพ์เล็ก
  • token_symbol (string หรือ null): สัญลักษณ์ของ base token
  • token_name (string หรือ null): ชื่อที่แสดงของ base token
  • quote_token (string): แอดเดรสของสินทรัพย์ quote โดยแอดเดรสที่เป็นศูนย์ทั้งหมด (0x0000000000000000000000000000000000000000) จะแสดงถึง native ETH ในฐานะสินทรัพย์ quote
  • quote_symbol (string หรือ null): สัญลักษณ์ของสินทรัพย์ quote ("ETH" เมื่อ quote_token เป็นแอดเดรสศูนย์ทั้งหมด)
  • quote_name (string หรือ null): ชื่อที่แสดงของสินทรัพย์ quote ("Ether" เมื่อ quote_token เป็นแอดเดรสศูนย์ทั้งหมด)
  • base_decimals (integer หรือ null): ทศนิยมของ base token (0–255)
  • quote_decimals (integer หรือ null): ทศนิยมของสินทรัพย์ quote (18 เมื่อ quote_token เป็นแอดเดรสศูนย์ทั้งหมด)

ปริมาณและจำนวนการซื้อขาย

  • swap_count (integer): จำนวนครั้งของ swap สำหรับแถวนี้
  • base_volume_raw (string): ปริมาณ base ระดับอะตอมในรูปแบบสตริงทศนิยมจำนวนเต็มแบบไม่มีเครื่องหมาย (UInt256String)
  • quote_volume_raw (string): ปริมาณ quote ระดับอะตอมในรูปแบบสตริงทศนิยมจำนวนเต็มแบบไม่มีเครื่องหมาย (UInt256String)
  • base_volume (string หรือ null): ปริมาณ base token ที่มนุษย์อ่านได้ซึ่งปรับขนาดตาม base_decimals ในรูปแบบ DecimalString; เป็น null เมื่อไม่ทราบ base_decimals
  • quote_volume (string หรือ null): ปริมาณ quote ที่ปรับขนาดตามทศนิยมของ quote ในรูปแบบ DecimalString หรือ null

ตัวชี้วัดราคาและ 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

ฟิลด์เศษส่วนแม่นยำสูง

  • 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 (meta)

  • chain: ตัวระบุเชน
  • chain_slug: slug ของเชนตัวพิมพ์ใหญ่ตามรูปแบบมาตรฐาน
  • chain_external_id: ตัวระบุเชนในรูปแบบ CAIP-2
  • as_of_block: บล็อกใหม่ล่าสุดที่เขียนสมบูรณ์แล้วของเชน (รายงานโดยชุดข้อมูลนี้ ไม่ได้ตรวจสอบเทียบกับพารามิเตอร์ของคำขอ)
  • coverage: การจัดระดับความครอบคลุม (รายงาน "full" สำหรับ endpoint นี้)
  • refreshed_at: การประทับเวลารีเฟรชของเมทาดาทา อาจเป็น null: ค่า null หมายถึงไม่ทราบเวลาอัปเดตของข้อมูลนี้และควรปฏิบัติเสมือนว่าเป็นข้อมูลเก่า; endpoint ที่อิงตามบล็อกจะส่งคืนค่าเสมอ

เหตุใดราคาจึงใช้ตัวเศษและตัวส่วนที่แม่นยำ

ตัวเลข JSON มาตรฐานใช้เลขทศนิยมความแม่นยำสองเท่า (double-precision float) ตามมาตรฐาน IEEE-754 ซึ่งมีข้อจำกัดด้านความแม่นยำ:

  1. การตัดทอนและการคลาดเคลื่อนของเลขทศนิยม (Floating-point truncation and drift): ค่า Float64 ให้ความแม่นยำเพียง 53 บิต และการหารปริมาณโทเค็นจะทำให้เกิดการปัดเศษคลาดเคลื่อนซึ่งจะสะสมทับถมกันในการคำนวณหลายขั้นตอน
  2. ความปลอดภัยในการส่งผ่านข้อมูล (Transport safety): การจัดรูปแบบค่าเป็นสตริงทศนิยม (UInt256String) ช่วยให้มั่นใจได้ว่าตัวเลขจะถูกส่งผ่าน HTTP โดยไม่สูญเสียความแม่นยำในตัวแจงส่วน JSON

ด้วยการให้ตัวเศษและตัวส่วนจำนวนเต็มที่แม่นยำสำหรับตัวชี้วัดราคา BlockVectra ช่วยให้สามารถคำนวณทางคณิตศาสตร์ได้อย่างแม่นยำโดยไม่ต้องแปลงเป็นเลขทศนิยม

การจัดการเศษส่วนที่แม่นยำใน TypeScript (BigInt)

ใน TypeScript คุณสามารถใช้ BigInt ดั้งเดิมสำหรับการเปรียบเทียบด้วยการคูณไขว้และการแปลงเป็น fixed-point ได้โดยไม่ต้องแปลงเป็นเลขทศนิยม:

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}`;
}

การจัดการเศษส่วนที่แม่นยำใน Python

Python มีโมดูลไลบรารีมาตรฐานที่สร้างขึ้นโดยเฉพาะสำหรับการคำนวณจำนวนตรรกยะและเลขทศนิยม: 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}")

การดึงข้อมูลราคารายวันย้อนหลังหนึ่งปี

ในการดึงข้อมูลย้อนหลังหนึ่งปี (365 วัน) ให้อยู่ภายในขีดจำกัดช่วง 90 วัน ให้แบ่งช่วงวันที่ทั้งหมดออกเป็นกรอบเวลาต่อเนื่องกันไม่เกิน 90 วัน แล้วส่งคำขอแบบแบ่งส่วน (chunked requests):

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;
}

การคำนวณความจุและการใช้งาน CU

ทุก endpoint ของ Data API จะวัดปริมาณการใช้งานเป็น Compute Units (CU) ค่าน้ำหนัก CU ต่อการเรียกสำหรับ data.dex_prices และการประมาณการปริมาณการใช้งานสำหรับการดึงข้อมูลโทเค็นย้อนหลังได้รับการคำนวณด้านล่างนี้:

น้ำหนักเมธอดdata.dex_prices: 15 CU / call
  • ดึงข้อมูลย้อนหลัง 1 ปีของราคารายวันสำหรับ 200 โทเค็น: ด้วยช่วงสูงสุด 90 วันต่อคำขอ การครอบคลุม 365 วันใช้ 5 ส่วนต่อโทเค็น รวมเป็น 1,000 คำขอ การใช้งานทั้งหมดคือ 15,000 CU (ประมาณ <0.1% ของโควตารอบแพ็กเกจฟรี), ประมาณ <$0.01 ตามราคามาตรฐาน.
  • การบำรุงรักษารายวัน (รีเฟรช 200 โทเค็นวันละครั้ง): 200 คำขอ/วัน (3,000 CU/วัน), รวมประมาณ 6,000 คำขอต่อรอบ 30 วัน (90,000 CU, ประมาณ 0.3% ของโควตาฟรี), ประมาณ <$0.01/เดือน ตามราคามาตรฐาน.

เมื่อขยายปริมาณการดึงข้อมูลย้อนหลังหรือต้องการความพร้อมกันของคำขอที่สูงขึ้น ให้เติมเงิน on-chain ที่คอนโซล หน้าการเรียกเก็บเงิน เพื่ออัปเกรดเป็นบัญชีแบบชำระเงิน สำหรับอัตราปัจจุบันและการแปลงหน่วย โปรดดู หน้าราคา

ขั้นตอนถัดไป

อัปเดตล่าสุด:

ในหน้านี้