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

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

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

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

ความพร้อมใช้งานของชุดข้อมูลนี้จะแตกต่างกันไปตามแต่ละเครือข่าย; เชนที่ให้บริการชุดข้อมูลนี้เป็นไปตามหน้ารายการ [เชนที่รองรับ](https://docs.blockvectra.com/en/chains/)

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

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

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

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

| พารามิเตอร์ | ตำแหน่ง | ประเภท      | จำเป็น | คำอธิบาย                                                                                        |
| ----------- | ------- | ----------- | ------ | ----------------------------------------------------------------------------------------------- |
| `chain`     | path    | string      | ใช่    | ตัวระบุเชน เช่น `robinhood_mainnet`                                                             |
| `token`     | query   | string      | ใช่    | แอดเดรส base token ขนาด 20 ไบต์, ใส่ `0x` หรือไม่ก็ได้, ตัวพิมพ์เล็กหรือใหญ่ก็ได้               |
| `quote`     | query   | string      | ไม่    | แอดเดรส quote token ขนาด 20 ไบต์ (ระบุหรือไม่ก็ได้) เพื่อจำกัดเฉพาะคู่ base/quote เดียว         |
| `from`      | query   | date string | ใช่    | วันที่เริ่มต้นตามเวลา UTC (รวมวันนั้นด้วย), รูปแบบ `YYYY-MM-DD`                                 |
| `to`        | query   | date 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**

```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())
```


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

แต่ละรายการใน `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 ได้โดยไม่ต้องแปลงเป็นเลขทศนิยม:

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

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

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

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

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

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

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

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

- **น้ำหนักเมธอด:** `data.dex_prices` = 15 CU / คำขอ.
- **ดึงข้อมูลย้อนหลัง 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 ที่คอนโซล [หน้าการเรียกเก็บเงิน](https://console.blockvectra.com/billing/) เพื่ออัปเกรดเป็นบัญชีแบบชำระเงิน สำหรับอัตราปัจจุบันและการแปลงหน่วย โปรดดู [หน้าราคา](https://blockvectra.com/en/pricing/)

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

* [เลือกดูสารบบชุดข้อมูล](https://blockvectra.com/en/data/) เพื่อดูทุกชุดข้อมูลที่ BlockVectra ทำดัชนี
* [ดูแผนบริการฟรีและราคา](https://blockvectra.com/en/pricing/#free) เพื่อตรวจสอบสิ่งที่รวมอยู่ในบัญชีของคุณ
* [เข้าสู่ระบบคอนโซล](https://console.blockvectra.com/login/?next=%2Fkeys%2F) เพื่อสร้าง API key
