# OHLC y VWAP diarios de DEX para un token, con fracciones exactas

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

## Qué es el conjunto de datos de precios diarios de DEX

El conjunto de datos DEX de BlockVectra indexa la actividad de operaciones de exchanges descentralizados y calcula métricas de precios agregadas por día. El endpoint de precios diarios de DEX (`getDexPrices`) proporciona el precio medio ponderado por volumen (VWAP) diario, indicadores de precio (campos `first_price`, `last_price`, `min_price` y `max_price`) y métricas de volumen para un token específico en un rango de fechas determinado.

La disponibilidad de este conjunto de datos varía entre redes; consulte las cadenas que lo ofrecen en la página de [Cadenas admitidas](https://docs.blockvectra.com/es/chains/).

Este endpoint no tiene paginación: todas las filas diarias coincidentes dentro del intervalo de fechas solicitado se devuelven directamente en `data`, y `next_cursor` nunca está presente. Si su aplicación necesita transacciones de swap individuales en lugar de agregados diarios, use `GET /{chain}/dex/swaps` (consulte la [referencia de la Data API](https://docs.blockvectra.com/en/api/data/)).

## Parámetros de solicitud y límites

La ruta del endpoint es `GET https://api.blockvectra.com/v1/data/{chain}/dex/prices`. Todas las solicitudes requieren autenticación mediante su API key en el encabezado `x-api-key`.

El endpoint acepta los siguientes parámetros de consulta:

| Parámetro | Ubicación | Tipo        | Obligatorio | Descripción                                                                                           |
| --------- | --------- | ----------- | ----------- | ----------------------------------------------------------------------------------------------------- |
| `chain`   | path      | string      | Sí          | Identificador de cadena, p. ej., `robinhood_mainnet`                                                  |
| `token`   | query     | string      | Sí          | Dirección del token base de 20 bytes, `0x` opcional, en mayúsculas o minúsculas                       |
| `quote`   | query     | string      | No          | Dirección opcional del token de cotización de 20 bytes para restringir a un único par base/cotización |
| `from`    | query     | date string | Sí          | Fecha de inicio UTC, inclusive, `YYYY-MM-DD`                                                          |
| `to`      | query     | date string | Sí          | Fecha de fin UTC, inclusive, `YYYY-MM-DD`. `to - from` debe ser `<= 90` días                          |

### Restricciones y códigos de error

Cuando una solicitud incumple las restricciones, la API devuelve un cuerpo de error estructurado `{"error":{"code","message"}}`:

* **HTTP 400 (`bad_request`)**: Faltan parámetros de consulta obligatorios (`token`, `from` o `to`), la sintaxis de las direcciones `token`/`quote` no es válida, las fechas del calendario `YYYY-MM-DD` no son válidas, o `from` es posterior a `to`.
* **HTTP 409 (`span_exceeded`)**: `to - from` supera los 90 días.
* **HTTP 404 (`unknown_chain`)**: `{chain}` no es una cadena listada por `GET /chains`.
* **HTTP 422 (`no_coverage`)**: La cadena no admite la capacidad del conjunto de datos `dex_prices`.
* **HTTP 503 (`unavailable`)**: Servicio temporalmente no disponible; reintente según el encabezado `Retry-After`.

## Ejemplos de solicitudes

Los ejemplos siguientes consultan los precios diarios de DEX de un token base durante septiembre de 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())
```


## Referencia detallada de campos

Cada entrada de `data` representa métricas diarias agregadas de DEX para el par de tokens en esa fecha UTC:

### Token y activos de cotización

* `day` (string): Fecha UTC en formato `YYYY-MM-DD`.
* `token` (string): Dirección del token base de 20 bytes en hexadecimal en minúsculas con prefijo `0x`.
* `token_symbol` (string o `null`): Símbolo del token base.
* `token_name` (string o `null`): Nombre para mostrar del token base.
* `quote_token` (string): Dirección del activo de cotización. La dirección de ceros (`0x0000000000000000000000000000000000000000`) representa ETH nativo como activo de cotización.
* `quote_symbol` (string o `null`): Símbolo del activo de cotización (`"ETH"` cuando `quote_token` es la dirección de ceros).
* `quote_name` (string o `null`): Nombre para mostrar del activo de cotización (`"Ether"` cuando `quote_token` es la dirección de ceros).
* `base_decimals` (integer o `null`): Decimales del token base (0–255).
* `quote_decimals` (integer o `null`): Decimales del activo de cotización (`18` cuando `quote_token` es la dirección de ceros).

### Volumen y recuento de operaciones

* `swap_count` (integer): Número de swaps de esta fila.
* `base_volume_raw` (string): Volumen base en unidades atómicas como cadena decimal de entero sin signo (`UInt256String`).
* `quote_volume_raw` (string): Volumen de cotización en unidades atómicas como cadena decimal de entero sin signo (`UInt256String`).
* `base_volume` (string o `null`): Volumen del token base legible para humanos, escalado según `base_decimals` como `DecimalString`; `null` cuando se desconoce `base_decimals`.
* `quote_volume` (string o `null`): Volumen de cotización escalado según los decimales de cotización como `DecimalString`, o `null`.

### Indicadores de precio y VWAP

* `vwap` (string o `null`): Precio medio ponderado por volumen como `DecimalString`, o `null`.
* `first_price` (string o `null`): Indicador del primer precio como `DecimalString`, o `null`.
* `last_price` (string o `null`): Indicador del último precio como `DecimalString`, o `null`.
* `min_price` (string o `null`): Indicador de precio mínimo como `DecimalString`, o `null`.
* `max_price` (string o `null`): Indicador de precio máximo como `DecimalString`, o `null`.

### Campos de fracciones exactas

* `first_price_numerator` / `first_price_denominator` (string): Numerador y denominador enteros exactos de `first_price` (`UInt256String`).
* `last_price_numerator` / `last_price_denominator` (string): Numerador y denominador enteros exactos de `last_price` (`UInt256String`).
* `min_price_numerator` / `min_price_denominator` (string): Numerador y denominador enteros exactos de `min_price` (`UInt256String`).
* `max_price_numerator` / `max_price_denominator` (string): Numerador y denominador enteros exactos de `max_price` (`UInt256String`).
* `refreshed_at` (string): Marca de tiempo de actualización de esta fila (marca de tiempo UTC ISO-8601).

### Metadatos de la estructura de respuesta (`meta`)

* `chain`: Identificador de cadena.
* `chain_slug`: Slug canónico de la cadena en mayúsculas.
* `chain_external_id`: Identificador de cadena en formato CAIP-2.
* `as_of_block`: Último bloque de la cadena completamente escrito (comunicado por este conjunto de datos, sin comprobarlo frente a los parámetros de solicitud).
* `coverage`: Clasificación de cobertura (comunica `"full"` para este endpoint).
* `refreshed_at`: Marca de tiempo de actualización de los metadatos. Puede ser `null`: `null` significa que se desconoce cuándo se actualizaron estos datos y deben tratarse como obsoletos; los endpoints basados en bloques siempre devuelven un valor.

## Por qué los precios usan numeradores y denominadores exactos

Los números JSON estándar dependen de valores de coma flotante de doble precisión IEEE-754, que tienen limitaciones de precisión:

1. **Truncamiento y desviación de coma flotante**: Los valores Float64 solo ofrecen 53 bits de precisión, y dividir cantidades de tokens genera desviaciones de redondeo que se acumulan entre cálculos.
2. **Seguridad en la transmisión**: Dar formato a los valores como cadenas decimales (`UInt256String`) garantiza que los números se transmitan por HTTP sin perder precisión en los analizadores JSON.

Al proporcionar el numerador y el denominador enteros exactos de los indicadores de precio, BlockVectra permite cálculos matemáticos exactos sin conversión a coma flotante.

### Manejo de fracciones exactas en TypeScript (BigInt)

En TypeScript, puede usar `BigInt` nativo para comparaciones mediante multiplicación cruzada y conversiones a punto fijo sin conversión a coma flotante:

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

### Manejo de fracciones exactas en Python

Python proporciona módulos de la biblioteca estándar diseñados específicamente para cálculos racionales y decimales: `fractions.Fraction` y `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}")
```

## Carga histórica de un año de precios diarios

Para cargar un año de datos (365 días) dentro del límite de intervalo de 90 días, divida el rango completo de fechas en ventanas consecutivas de un máximo de 90 días y envíe solicitudes por segmentos:

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

## Cálculos de capacidad y consumo de CU

Cada endpoint de la Data API mide el consumo en unidades de cómputo (CU). A continuación se calculan el peso CU por llamada de `data.dex_prices` y el consumo estimado de las cargas históricas de tokens:

- **Peso del método:** `data.dex_prices` = 15 CU / llamada.
- **Carga histórica de 1 año de precios diarios para 200 tokens:** con un rango máximo de 90 días por solicitud, cubrir 365 días toma 5 fragmentos por token, con un total de 1,000 llamadas. El consumo total es de 15,000 CU (aprox. <0.1% de la cuota del ciclo del plan gratuito), aprox. <$0.01 a precio de lista.
- **Mantenimiento diario (actualización de 200 tokens una vez al día):** 200 llamadas/día (3,000 CU/día), con un total de aprox. 6,000 llamadas por ciclo de 30 días (90,000 CU, aprox. 0.3% de la cuota gratuita), aprox. <$0.01/mes a precio de lista.

Cuando aumente el volumen de carga histórica o necesite mayor concurrencia de solicitudes, recargue on-chain en la [página de Facturación](https://console.blockvectra.com/billing/) de la consola para pasar a una cuenta de pago. Para conocer las tarifas vigentes y las conversiones de unidades, consulte la [página de Precios](https://blockvectra.com/es/pricing/).

## Próximos pasos

* [Explore el catálogo de conjuntos de datos](https://blockvectra.com/es/data/) para ver todos los conjuntos de datos que indexa BlockVectra.
* [Consulte el plan gratuito y los precios](https://blockvectra.com/es/pricing/#free) para comprobar qué incluye su cuenta.
* [Inicie sesión en la consola](https://console.blockvectra.com/login/?next=%2Fkeys%2F) para crear una API key.
