# Tägliche DEX-OHLC und VWAP für einen Token mit exakten Brüchen

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

## 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](https://docs.blockvectra.com/de/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](https://docs.blockvectra.com/de/api/data/)).

## 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`, `from` oder `to`), ungültige `token`/`quote`-Adresssyntax, ungültige `YYYY-MM-DD`-Kalenderdaten oder `from` liegt nach `to`.
* **HTTP 409 (`span_exceeded`)**: `to - from` beträgt mehr als 90 Tage.
* **HTTP 404 (`unknown_chain`)**: `{chain}` ist keine von `GET /chains` aufgelistete Chain.
* **HTTP 422 (`no_coverage`)**: Die Chain unterstützt die `dex_prices`-Datensatzfunktion nicht.
* **HTTP 503 (`unavailable`)**: Dienst vorübergehend nicht verfügbar; gemäß dem `Retry-After`-Header wiederholen.

## Anfragebeispiele

Die folgenden Beispiele fragen tägliche DEX-Preise für einen Basis-Token im September 2026 ab:

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


## 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 Format `YYYY-MM-DD`.
* `token` (String): 20-Byte-Basis-Token-Adresse in kleingeschriebenem Hexadezimalformat mit `0x`-Präfix.
* `token_symbol` (String oder `null`): Symbol des Basis-Tokens.
* `token_name` (String oder `null`): 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 oder `null`): Symbol des Quote-Assets (`"ETH"`, wenn `quote_token` die Null-Adresse ist).
* `quote_name` (String oder `null`): Anzeigename des Quote-Assets (`"Ether"`, wenn `quote_token` die Null-Adresse ist).
* `base_decimals` (Integer oder `null`): Dezimalstellen des Basis-Tokens (0–255).
* `quote_decimals` (Integer oder `null`): Dezimalstellen des Quote-Assets (`18`, wenn `quote_token` die 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 oder `null`): Für Menschen lesbares Basis-Token-Volumen, skaliert um `base_decimals` als `DecimalString`; `null`, wenn `base_decimals` unbekannt ist.
* `quote_volume` (String oder `null`): Quote-Volumen, skaliert um Quote-Dezimalstellen als `DecimalString`, oder `null`.

### Preisindikatoren und VWAP

* `vwap` (String oder `null`): Volumengewichteter Durchschnittspreis als `DecimalString` oder `null`.
* `first_price` (String oder `null`): Erster Preisindikator als `DecimalString` oder `null`.
* `last_price` (String oder `null`): Letzter Preisindikator als `DecimalString` oder `null`.
* `min_price` (String oder `null`): Minimaler Preisindikator als `DecimalString` oder `null`.
* `max_price` (String oder `null`): Maximaler Preisindikator als `DecimalString` oder `null`.

### Exakte Bruchfelder

* `first_price_numerator` / `first_price_denominator` (String): Exakter ganzzahliger Zähler und Nenner für `first_price` (`UInt256String`).
* `last_price_numerator` / `last_price_denominator` (String): Exakter ganzzahliger Zähler und Nenner für `last_price` (`UInt256String`).
* `min_price_numerator` / `min_price_denominator` (String): Exakter ganzzahliger Zähler und Nenner für `min_price` (`UInt256String`).
* `max_price_numerator` / `max_price_denominator` (String): Exakter ganzzahliger Zähler und Nenner für `max_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. Kann `null` sein: `null` bedeutet, 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:

1. **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.
2. **Ü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:

```ts
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`.

```python
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:

```ts
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:

- **Methodengewichtung:** `data.dex_prices` = 15 CU / Aufruf.
- **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 {formatNumber(windowDays)}-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](https://console.blockvectra.com/billing/) der Konsole auf, um auf ein kostenpflichtiges Konto hochzustufen. Aktuelle Tarife und Einheitenumrechnungen finden Sie auf der [Preisseite](https://blockvectra.com/de/pricing/).

## Nächste Schritte

* [Datensatzverzeichnis durchsuchen](https://blockvectra.com/de/data/), um jeden von BlockVectra indizierten Datensatz einzusehen.
* [Kostenlosen Tarif und Preise ansehen](https://blockvectra.com/de/pricing/#free), um zu prüfen, was Ihr Konto beinhaltet.
* [In der Konsole anmelden](https://console.blockvectra.com/login/?next=%2Fkeys%2F), um einen API key zu erstellen.
