# OHLC et VWAP quotidiens DEX pour un token, avec fractions exactes

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

## En quoi consiste le jeu de données des prix quotidiens DEX

Le jeu de données DEX de BlockVectra indexe l'activité d'échange sur les plateformes décentralisées et calcule des métriques de prix quotidiennes agrégées. Le point de terminaison des prix quotidiens DEX (`getDexPrices`) fournit le prix moyen pondéré par le volume quotidien (VWAP), des indicateurs de prix (champs `first_price`, `last_price`, `min_price` et `max_price`), ainsi que des métriques de volume pour un token spécifique sur une plage de dates donnée.

La disponibilité de ce jeu de données varie selon les réseaux ; les chaînes fournissant ce jeu de données sont régies par la page des [Chaînes prises en charge](https://docs.blockvectra.com/fr/chains/).

Ce point de terminaison n'est pas paginé : toutes les lignes quotidiennes correspondantes dans la plage de dates demandée sont renvoyées directement dans `data`, et `next_cursor` n'est jamais présent. Si votre application nécessite des transactions de swap granulaires plutôt que des agrégats quotidiens, utilisez `GET /{chain}/dex/swaps` (voir la [Référence de la Data API](https://docs.blockvectra.com/fr/api/data/)).

## Paramètres de requête et limites

La route du point de terminaison est `GET https://api.blockvectra.com/v1/data/{chain}/dex/prices`. Toutes les requêtes nécessitent une authentification en fournissant votre clé API dans l'en-tête `x-api-key`.

Le point de terminaison accepte les paramètres de requête suivants :

| Paramètre | Emplacement | Type        | Requis | Description                                                                                    |
| --------- | ----------- | ----------- | ------ | ---------------------------------------------------------------------------------------------- |
| `chain`   | path        | string      | Oui    | Identifiant de la chaîne, par ex. `robinhood_mainnet`                                          |
| `token`   | query       | string      | Oui    | Adresse du base token sur 20 octets, `0x` facultatif, indifférent à la casse                   |
| `quote`   | query       | string      | Non    | Adresse facultative du quote token sur 20 octets pour restreindre à une seule paire base/quote |
| `from`    | query       | date string | Oui    | Date de début UTC, incluse, `YYYY-MM-DD`                                                       |
| `to`      | query       | date string | Oui    | Date de fin UTC, incluse, `YYYY-MM-DD`. `to - from` doit être `<= 90` jours                    |

### Contraintes et codes d'erreur

Lorsqu'une requête enfreint les contraintes, l'API renvoie un corps d'erreur structuré `{"error":{"code","message"}}` :

* **HTTP 400 (`bad_request`)** : paramètres de requête requis manquants (`token`, `from` ou `to`), syntaxe d'adresse `token`/`quote` invalide, dates calendaires `YYYY-MM-DD` invalides, ou `from` est postérieur à `to`.
* **HTTP 409 (`span_exceeded`)** : `to - from` est supérieur à 90 jours.
* **HTTP 404 (`unknown_chain`)** : `{chain}` n'est pas une chaîne répertoriée par `GET /chains`.
* **HTTP 422 (`no_coverage`)** : la chaîne ne prend pas en charge la fonctionnalité du jeu de données `dex_prices`.
* **HTTP 503 (`unavailable`)** : service temporairement indisponible ; réessayez selon l'en-tête `Retry-After`.

## Exemples de requêtes

Les exemples suivants interrogent les prix quotidiens DEX pour un base token sur l'ensemble du mois de septembre 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())
```


## Référence détaillée des champs

Chaque entrée dans `data` représente des métriques quotidiennes agrégées DEX pour la paire de tokens à cette date UTC :

### Actifs token et quote

* `day` (string) : date UTC au format `YYYY-MM-DD`.
* `token` (string) : adresse du base token sur 20 octets en hexadécimal préfixé par `0x` en minuscules.
* `token_symbol` (string ou `null`) : symbole du base token.
* `token_name` (string ou `null`) : nom d'affichage du base token.
* `quote_token` (string) : adresse de l'actif quote. L'adresse composée uniquement de zéros (`0x0000000000000000000000000000000000000000`) représente l'ETH natif comme actif quote.
* `quote_symbol` (string ou `null`) : symbole de l'actif quote (`"ETH"` lorsque `quote_token` est l'adresse de zéros).
* `quote_name` (string ou `null`) : nom d'affichage de l'actif quote (`"Ether"` lorsque `quote_token` est l'adresse de zéros).
* `base_decimals` (integer ou `null`) : décimales du base token (0–255).
* `quote_decimals` (integer ou `null`) : décimales de l'actif quote (`18` lorsque `quote_token` est l'adresse de zéros).

### Volume et décompte des transactions

* `swap_count` (integer) : nombre de swaps pour cette ligne.
* `base_volume_raw` (string) : volume atomique du token de base sous forme de chaîne décimale d'entier non signé (`UInt256String`).
* `quote_volume_raw` (string) : volume atomique de la quote sous forme de chaîne décimale d'entier non signé (`UInt256String`).
* `base_volume` (string ou `null`) : volume du base token lisible par l'humain ajusté par `base_decimals` sous forme de `DecimalString` ; `null` lorsque `base_decimals` est inconnu.
* `quote_volume` (string ou `null`) : volume de la quote ajusté par les décimales de la quote sous forme de `DecimalString`, ou `null`.

### Indicateurs de prix et VWAP

* `vwap` (string ou `null`) : prix moyen pondéré par le volume sous forme de `DecimalString`, ou `null`.
* `first_price` (string ou `null`) : indicateur de premier prix sous forme de `DecimalString`, ou `null`.
* `last_price` (string ou `null`) : indicateur de dernier prix sous forme de `DecimalString`, ou `null`.
* `min_price` (string ou `null`) : indicateur de prix minimum sous forme de `DecimalString`, ou `null`.
* `max_price` (string ou `null`) : indicateur de prix maximum sous forme de `DecimalString`, ou `null`.

### Champs de fraction exacte

* `first_price_numerator` / `first_price_denominator` (string) : numérateur et dénominateur entiers exacts pour `first_price` (`UInt256String`).
* `last_price_numerator` / `last_price_denominator` (string) : numérateur et dénominateur entiers exacts pour `last_price` (`UInt256String`).
* `min_price_numerator` / `min_price_denominator` (string) : numérateur et dénominateur entiers exacts pour `min_price` (`UInt256String`).
* `max_price_numerator` / `max_price_denominator` (string) : numérateur et dénominateur entiers exacts pour `max_price` (`UInt256String`).
* `refreshed_at` (string) : horodatage d'actualisation pour cette ligne (horodatage UTC ISO-8601).

### Métadonnées d'enveloppe (`meta`)

* `chain` : identifiant de la chaîne.
* `chain_slug` : slug canonique de la chaîne en majuscules.
* `chain_external_id` : identifiant de chaîne formaté selon CAIP-2.
* `as_of_block` : le bloc le plus récent entièrement écrit de la chaîne (rapporté par ce jeu de données, non vérifié par rapport aux paramètres de requête).
* `coverage` : classification de la couverture (indique `"full"` pour ce point de terminaison).
* `refreshed_at` : horodatage d'actualisation des métadonnées. Peut être `null` : `null` signifie que l'heure de mise à jour de ces données est inconnue et qu'elles doivent être traitées comme périmées ; les points de terminaison basés sur les blocs renvoient toujours une valeur.

## Pourquoi les prix utilisent des numérateurs et dénominateurs exacts

Les nombres JSON standards reposent sur des nombres à virgule flottante double précision IEEE-754, qui présentent des limites de précision :

1. **Troncature et dérive en virgule flottante** : les valeurs Float64 n'offrent que 53 bits de précision, et la division de quantités de tokens produit une dérive d'arrondi qui se cumule au fil des calculs.
2. **Sécurité de transport** : le formatage des valeurs sous forme de chaînes décimales (`UInt256String`) garantit que les nombres circulent sur HTTP sans perte de précision dans les parseurs JSON.

En fournissant le numérateur et le dénominateur entiers exacts pour les indicateurs de prix, BlockVectra permet des calculs mathématiques exacts sans conversion en virgule flottante.

### Gestion des fractions exactes en TypeScript (BigInt)

En TypeScript, vous pouvez utiliser les `BigInt` natifs pour les comparaisons par produits en croix et les conversions en virgule fixe sans conversion en virgule flottante :

```ts
interface DexDailyPrice {
  first_price_numerator: string;
  first_price_denominator: string;
  last_price_numerator: string;
  last_price_denominator: string;
}

// 1. Comparaison de ratios sans conversion en virgule flottante : vérifier si le cours de clôture est supérieur au cours d'ouverture
// a / b > c / d  équivaut à  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. Convertir la fraction en une chaîne décimale à virgule fixe avec une échelle arbitraire (sans perte de virgule flottante)
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}`;
}
```

### Gestion des fractions exactes en Python

Python propose des modules de bibliothèque standard spécialement conçus pour les calculs rationnels et décimaux : `fractions.Fraction` et `decimal.Decimal`.

```python
from decimal import Decimal, getcontext
from fractions import Fraction

# 1. Calculs rationnels exacts avec 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"])
)

# Delta de prix exact sans erreur d'arrondi en virgule flottante
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. Arithmétique décimale à précision arbitraire avec 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}")
```

## Rattrapage d'une année de prix quotidiens

Pour rattraper une année de données (365 jours) dans la limite d'intervalle de 90 jours, divisez la plage complète de dates en fenêtres consécutives d'au maximum 90 jours et envoyez des requêtes par segments :

```ts
interface DateSpan {
  from: string;
  to: string;
}

/**
 * Divise une grande plage de dates en intervalles consécutifs d'au maximum maxDays (par défaut : 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;
}

/**
 * Rattrape les prix quotidiens de tokens sur plusieurs segments de 90 jours
 */
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;
}
```

## Calculs de capacité et d'utilisation des CU

Chaque point de terminaison de la Data API mesure la consommation en Compute Units (CU). La pondération en CU par appel pour `data.dex_prices` et la consommation estimée pour les rattrapages de tokens sont calculées ci-dessous :

- **Poids de la méthode :** `data.dex_prices` = 15 CU / appel.
- **Rattrapage d'un an de prix quotidiens pour 200 tokens :** avec une durée maximale de 90 jours par requête, couvrir 365 jours nécessite 5 segments par token, soit un total de 1,000 appels. La consommation totale est de 15,000 CU (env. <0.1% du quota de cycle du forfait gratuit), environ <$0.01 au tarif catalogue.
- **Maintenance quotidienne (actualisation de 200 tokens une fois par jour) :** 200 appels/jour (3,000 CU/jour), pour un total d'environ 6,000 appels par cycle de 30 jours (90,000 CU, env. 0.3% du quota gratuit), environ <$0.01/mois au tarif catalogue.

Pour augmenter votre volume de rattrapage ou obtenir une concurrence de requêtes plus élevée, rechargez on-chain sur la [page Facturation](https://console.blockvectra.com/billing/) de la console pour passer à un compte payant. Pour les tarifs actifs et les conversions d'unités, consultez la [page Tarifs](https://blockvectra.com/fr/pricing/).

## Prochaines étapes

* [Parcourir le répertoire des jeux de données](https://blockvectra.com/fr/data/) pour voir chaque jeu de données indexé par BlockVectra.
* [Consulter le forfait gratuit et les tarifs](https://blockvectra.com/fr/pricing/#free) pour vérifier ce que comprend votre compte.
* [Se connecter à la console](https://console.blockvectra.com/login/?next=%2Fkeys%2F) pour créer une clé API.
