Tägliche DEX-OHLC und VWAP für einen Token mit exakten Brüchen
Tägliche DEX-OHLC-Preise und VWAP über die Data-API abfragen, exakte rationale Brüche in TypeScript und Python verarbeiten und historische Daten effizient nacherfassen.
Was der DEX-Tagespreis-Datensatz ist
Der DEX-Datensatz von BlockVectra indiziert Handelsaktivitäten auf dezentralen Börsen und berechnet aggregierte tägliche Preiskennzahlen. Der Endpunkt für tägliche DEX-Preise (getDexPrices) liefert den täglichen volumengewichteten Durchschnittspreis (VWAP), Preisindikatoren (Felder first_price, last_price, min_price und max_price) sowie Volumenkennzahlen für einen bestimmten Token über einen angegebenen Datumsbereich.
Die Verfügbarkeit dieses Datensatzes variiert je nach Netzwerk; Chains, die diesen Datensatz bereitstellen, unterliegen der Seite Unterstützte Chains.
Dieser Endpunkt ist nicht paginiert: Alle übereinstimmenden täglichen Zeilen innerhalb der angeforderten Zeitspanne werden direkt in data zurückgegeben, und next_cursor ist niemals vorhanden. Wenn Ihre Anwendung granulare Swap-Transaktionen anstelle von täglichen Aggregaten benötigt, verwenden Sie GET /{chain}/dex/swaps (siehe die Data-API-Referenz).
Anfrageparameter und Limits
Die Endpunkt-Route lautet GET https://api.blockvectra.com/v1/data/{chain}/dex/prices. Alle Anfragen erfordern eine Authentifizierung durch Angabe Ihres API keys im x-api-key-Header.
Der Endpunkt akzeptiert die folgenden Abfrageparameter:
| Parameter | Position | Typ | Erforderlich | Beschreibung |
|---|---|---|---|---|
chain | path | string | Ja | Chain-Bezeichner, z. B. robinhood_mainnet |
token | query | string | Ja | 20-Byte-Basis-Token-Adresse, 0x optional, Groß-/Kleinschreibung beliebig |
quote | query | string | Nein | Optionale 20-Byte-Quote-Token-Adresse zur Beschränkung auf ein einzelnes Basis/Quote-Paar |
from | query | Datums-String | Ja | UTC-Startdatum, inklusive, YYYY-MM-DD |
to | query | Datums-String | Ja | UTC-Enddatum, inklusive, YYYY-MM-DD. to - from muss <= 90 Tage sein |
Einschränkungen und Fehlercodes
Wenn eine Anfrage gegen Einschränkungen verstößt, gibt die API einen strukturierten Fehler-Body {"error":{"code","message"}} zurück:
- HTTP 400 (
bad_request): Fehlende erforderliche Abfrageparameter (token,fromoderto), ungültigetoken/quote-Adresssyntax, ungültigeYYYY-MM-DD-Kalenderdaten oderfromliegt nachto. - HTTP 409 (
span_exceeded):to - frombeträgt mehr als 90 Tage. - HTTP 404 (
unknown_chain):{chain}ist keine vonGET /chainsaufgelistete Chain. - HTTP 422 (
no_coverage): Die Chain unterstützt diedex_prices-Datensatzfunktion nicht. - HTTP 503 (
unavailable): Dienst vorübergehend nicht verfügbar; gemäß demRetry-After-Header wiederholen.
Anfragebeispiele
Die folgenden Beispiele fragen tägliche DEX-Preise für einen Basis-Token im September 2026 ab:
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"Detaillierte Feldreferenz
Jeder Eintrag in data stellt aggregierte tägliche DEX-Kennzahlen für das Token-Paar an diesem UTC-Datum dar:
Basis- und Quote-Assets
day(String): UTC-Datum im FormatYYYY-MM-DD.token(String): 20-Byte-Basis-Token-Adresse in kleingeschriebenem Hexadezimalformat mit0x-Präfix.token_symbol(String odernull): Symbol des Basis-Tokens.token_name(String odernull): Anzeigename des Basis-Tokens.quote_token(String): Adresse des Quote-Assets. Die reine Null-Adresse (0x0000000000000000000000000000000000000000) repräsentiert natives ETH als Quote-Asset.quote_symbol(String odernull): Symbol des Quote-Assets ("ETH", wennquote_tokendie Null-Adresse ist).quote_name(String odernull): Anzeigename des Quote-Assets ("Ether", wennquote_tokendie Null-Adresse ist).base_decimals(Integer odernull): Dezimalstellen des Basis-Tokens (0–255).quote_decimals(Integer odernull): Dezimalstellen des Quote-Assets (18, wennquote_tokendie Null-Adresse ist).
Volumen und Trade-Zählungen
swap_count(Integer): Swap-Anzahl für diese Zeile.base_volume_raw(String): Atomares Basis-Volumen als vorzeichenloser Integer-Dezimal-String (UInt256String).quote_volume_raw(String): Atomares Quote-Volumen als vorzeichenloser Integer-Dezimal-String (UInt256String).base_volume(String odernull): Für Menschen lesbares Basis-Token-Volumen, skaliert umbase_decimalsalsDecimalString;null, wennbase_decimalsunbekannt ist.quote_volume(String odernull): Quote-Volumen, skaliert um Quote-Dezimalstellen alsDecimalString, odernull.
Preisindikatoren und VWAP
vwap(String odernull): Volumengewichteter Durchschnittspreis alsDecimalStringodernull.first_price(String odernull): Erster Preisindikator alsDecimalStringodernull.last_price(String odernull): Letzter Preisindikator alsDecimalStringodernull.min_price(String odernull): Minimaler Preisindikator alsDecimalStringodernull.max_price(String odernull): Maximaler Preisindikator alsDecimalStringodernull.
Exakte Bruchfelder
first_price_numerator/first_price_denominator(String): Exakter ganzzahliger Zähler und Nenner fürfirst_price(UInt256String).last_price_numerator/last_price_denominator(String): Exakter ganzzahliger Zähler und Nenner fürlast_price(UInt256String).min_price_numerator/min_price_denominator(String): Exakter ganzzahliger Zähler und Nenner fürmin_price(UInt256String).max_price_numerator/max_price_denominator(String): Exakter ganzzahliger Zähler und Nenner fürmax_price(UInt256String).refreshed_at(String): Aktualisierungszeitstempel für diese Zeile (ISO-8601 UTC-Zeitstempel).
Envelope-Metadaten (meta)
chain: Chain-Bezeichner.chain_slug: Kanonischer, großgeschriebener Chain-Slug.chain_external_id: Im CAIP-2-Format formatierter Chain-Bezeichner.as_of_block: Der neueste vollständig geschriebene Block der Chain (von diesem Datensatz gemeldet, nicht mit Anfrageparametern abgeglichen).coverage: Abdeckungsklassifizierung (meldet"full"für diesen Endpunkt).refreshed_at: Zeitstempel der Metadaten-Aktualisierung. Kannnullsein:nullbedeutet, dass der Aktualisierungszeitpunkt dieser Daten unbekannt ist und sie als veraltet betrachtet werden sollten; blockbasierte Endpunkte geben immer einen Wert zurück.
Warum Preise exakte Zähler und Nenner verwenden
Standard-JSON-Zahlen basieren auf IEEE-754-Gleitkommazahlen mit doppelter Genauigkeit, die Präzisionseinschränkungen aufweisen:
- Gleitkomma-Kappung und -Drift: Float64-Werte bieten nur 53 Bit Präzision, und das Teilen von Token-Mengen führt zu Rundungsungenauigkeiten, die sich über Berechnungen hinweg verstärken.
- Übertragungssicherheit: Die Formatierung von Werten als Dezimal-Strings (
UInt256String) stellt sicher, dass Zahlen über HTTP übertragen werden, ohne in JSON-Parsern an Präzision zu verlieren.
Durch die Bereitstellung des exakten ganzzahligen Zählers und Nenners für Preisindikatoren ermöglicht BlockVectra exakte mathematische Berechnungen ohne Gleitkommakonvertierung.
Verarbeitung exakter Brüche in TypeScript (BigInt)
In TypeScript können Sie natives BigInt für Kreuzmultiplikationsvergleiche und Festkommakonvertierungen ohne Gleitkommakonvertierung verwenden:
interface DexDailyPrice {
first_price_numerator: string;
first_price_denominator: string;
last_price_numerator: string;
last_price_denominator: string;
}
// 1. Verhältnisvergleich ohne Gleitkommakonvertierung: prüfen, ob Schlusskurs höher als Eröffnungskurs ist
// a / b > c / d ist äquivalent zu 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. Bruch in Festkomma-Dezimal-String mit beliebiger Skalierung konvertieren (ohne Gleitkommaverlust)
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}`;
}Verarbeitung exakter Brüche in Python
Python bietet Standardbibliotheksmodule, die speziell für rationale und dezimale Berechnungen entwickelt wurden: fractions.Fraction und decimal.Decimal.
from decimal import Decimal, getcontext
from fractions import Fraction
# 1. Exakte rationale Berechnungen mit 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"])
)
# Exakte Preisdifferenz ohne Rundungsfehler durch Gleitkommazahlen
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. Dezimalarithmetik mit beliebiger Genauigkeit mit 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}")Nacherfassung eines Jahres an Tagespreisen
Um Daten für ein ganzes Jahr (365 Tage) innerhalb des 90-Tage-Spanne-Limits nachzuerfassen, teilen Sie den gesamten Datumsbereich in aufeinanderfolgende Fenster von maximal 90 Tagen auf und führen Sie segmentierte Anfragen durch:
interface DateSpan {
from: string;
to: string;
}
/**
* Einen großen Datumsbereich in aufeinanderfolgende Zeitspannen von maximal maxDays aufteilen (Standard: 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;
}
/**
* Tägliche Token-Preise über mehrere 90-Tage-Segmente hinweg nacherfassen
*/
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;
}Kapazität und CU-Verbrauchsberechnungen
Jeder Data-API-Endpunkt erfasst den Verbrauch in Compute Units (CU). Das CU-Gewicht pro Aufruf für data.dex_prices und der geschätzte Verbrauch für Token-Backfills werden unten berechnet:
data.dex_prices: 15 CU / call- Nachträgliches Laden von 1 Jahr täglicher Preise für 200 Token: Bei einer maximalen Spanne von 90 Tagen pro Anfrage erfordert die Abdeckung von 365 Tagen 5 Abschnitte pro Token, insgesamt 1,000 Aufrufe. Der Gesamtverbrauch beträgt 15,000 CU (ca. <0.1% des Freikontingents pro Zyklus), ca. <$0.01 zum Listenpreis.
- Tägliche Wartung (Aktualisierung von 200 Token einmal pro Tag): 200 Aufrufe/Tag (3,000 CU/Tag), insgesamt etwa 6,000 Aufrufe pro 30-Tage-Zyklus (90,000 CU, ca. 0.3% des Freikontingents), ca. <$0.01/Monat zum Listenpreis.
Wenn Sie Ihr Backfill-Volumen skalieren oder eine höhere Anforderungs-Parallelität benötigen, laden Sie On-Chain auf der Abrechnungsseite der Konsole auf, um auf ein kostenpflichtiges Konto hochzustufen. Aktuelle Tarife und Einheitenumrechnungen finden Sie auf der Preisseite.
Nächste Schritte
- Datensatzverzeichnis durchsuchen, um jeden von BlockVectra indizierten Datensatz einzusehen.
- Kostenlosen Tarif und Preise ansehen, um zu prüfen, was Ihr Konto beinhaltet.
- In der Konsole anmelden, um einen API key zu erstellen.
Zuletzt aktualisiert:
Vertragsbereitstellung
Deployen Sie Hello.sol in einem EVM-Netzwerk mit Foundry oder Hardhat 2, verifizieren Sie die Chain ID und prüfen Sie die Transaktionsquittung sowie die Vertragsantwort.
Historischer EVM-State
Unterscheiden Sie authentifizierte State-Fenster, schlüssellosen Verlauf und Log-Spannen. Wählen Sie einen festen Block für eth_call und diagnostizieren Sie state_window-Fehler.