---
id: "RF-DATA-001"
title: "Sincronizacion Batch de Datos de Activos con Priorizacion"
type: "Requirement"
status: "To Do"
priority: "Alta"
epic: "Transversal"
project: "trading-platform"
version: "1.0.0"
created_date: "2026-01-04"
updated_date: "2026-01-04"
---

# RF-DATA-001: Sincronizacion Batch de Datos de Activos con Priorizacion

**Version:** 1.0.0
**Fecha:** 2026-01-04
**Modulo:** Data Service
**Prioridad:** P0
**Story Points:** 13

---

## Descripcion

El sistema debe implementar un proceso batch automatizado que actualice los datos de activos financieros desde la API de Polygon.io/Massive.com hacia la base de datos PostgreSQL cada 5 minutos, respetando el rate limit de 5 llamadas API por minuto (cuenta gratuita) y priorizando la actualizacion de activos criticos (Oro/XAU, EUR/USD, Bitcoin/BTC).

---

## Requisitos Funcionales

### RF-DATA-001.1: Ejecucion Programada del Batch

El sistema debe:
- Ejecutar un proceso batch cada 5 minutos
- Iniciar automaticamente al arrancar el Data Service
- Permitir ejecucion manual via API endpoint
- Registrar logs de cada ejecucion

**Configuracion:**
```yaml
batch:
  interval_minutes: 5
  auto_start: true
  retry_on_failure: true
  max_retries: 3
```

### RF-DATA-001.2: Priorizacion de Activos

El sistema debe actualizar primero los activos prioritarios antes que cualquier otro:

| Prioridad | Simbolo | Tipo | Ticker Polygon |
|-----------|---------|------|----------------|
| 1 | XAU/USD | Commodity | C:XAUUSD |
| 2 | EUR/USD | Forex | C:EURUSD |
| 3 | BTC/USD | Crypto | X:BTCUSD |

**Comportamiento:**
- Los 3 activos prioritarios se actualizan en CADA ciclo de 5 minutos
- Utilizan 3 de las 5 llamadas API disponibles por minuto
- No pueden ser omitidos por ningun motivo

### RF-DATA-001.3: Rate Limiting

El sistema debe:
- Respetar el limite de 5 llamadas API por minuto
- Distribuir las llamadas de manera uniforme (espaciado de ~12 segundos)
- Esperar automaticamente si se alcanza el limite
- Registrar metricas de uso de API

**Distribucion de Llamadas por Ciclo:**
```
Minuto 0:
  - 0s:  Llamada 1 - XAU/USD (Priority)
  - 12s: Llamada 2 - EUR/USD (Priority)
  - 24s: Llamada 3 - BTC/USD (Priority)
  - 36s: Llamada 4 - Asset de cola
  - 48s: Llamada 5 - Asset de cola
```

### RF-DATA-001.4: Sistema de Cola para Activos Secundarios

El sistema debe:
- Mantener una cola de prioridad para activos no prioritarios
- Procesar activos encolados con las 2 llamadas API restantes por minuto
- Implementar deduplicacion (no encolar duplicados)
- Soportar reintentos con backoff exponencial

**Activos Secundarios (ejemplos):**
- ETH/USDT (Crypto)
- GBP/USD (Forex)
- USD/JPY (Forex)
- XAG/USD (Plata)
- Indices (SPX, NDX)

### RF-DATA-001.5: Actualizacion de Base de Datos

El sistema debe actualizar las siguientes tablas:

**Tabla `trading.symbols`:**
- `updated_at`: Timestamp de ultima actualizacion
- `metadata`: JSON con precios actuales (bid, ask, last_price)

**Tabla `data_sources.data_sync_status`:**
- `last_sync_timestamp`: Cuando se sincronizo
- `sync_status`: success | failed | pending
- `last_sync_rows`: Cantidad de datos actualizados

### RF-DATA-001.6: Notificacion de Actualizaciones

El sistema debe:
- Publicar eventos via Redis Pub/Sub al actualizar un activo
- Formato del canal: `asset:update:{SYMBOL}`
- Incluir en el mensaje: symbol, bid, ask, last_price, timestamp
- Permitir a otros servicios suscribirse a actualizaciones

---

## Datos de Entrada

| Campo | Tipo | Descripcion | Requerido |
|-------|------|-------------|-----------|
| symbol | string | Simbolo del activo (ej: XAUUSD) | Si |
| polygon_ticker | string | Ticker en formato Polygon (ej: C:XAUUSD) | Si |
| asset_type | enum | forex, crypto, index, commodity | Si |
| priority | enum | CRITICAL, HIGH, MEDIUM, LOW | No (default: MEDIUM) |

---

## Datos de Salida

### Respuesta de Snapshot por Activo

```typescript
interface AssetSnapshot {
  symbol: string;
  bid: number;
  ask: number;
  spread: number;
  last_price: number;
  daily_open: number;
  daily_high: number;
  daily_low: number;
  daily_close: number;
  daily_volume: number;
  timestamp: string;  // ISO 8601
}
```

### Resultado del Batch Job

```typescript
interface BatchResult {
  started_at: string;
  completed_at: string;
  duration_ms: number;
  priority_assets: {
    updated: string[];
    failed: Array<{ symbol: string; error: string }>;
  };
  queued_assets: {
    processed: number;
    remaining: number;
  };
  api_calls_used: number;
  rate_limit_waits: number;
}
```

**Ejemplo:**
```json
{
  "started_at": "2026-01-04T18:00:00.000Z",
  "completed_at": "2026-01-04T18:00:48.250Z",
  "duration_ms": 48250,
  "priority_assets": {
    "updated": ["XAUUSD", "EURUSD", "BTCUSD"],
    "failed": []
  },
  "queued_assets": {
    "processed": 2,
    "remaining": 15
  },
  "api_calls_used": 5,
  "rate_limit_waits": 0
}
```

---

## Reglas de Negocio

1. **Activos Prioritarios Obligatorios:** XAU, EURUSD y BTCUSD SIEMPRE se actualizan primero
2. **Rate Limit Estricto:** Nunca exceder 5 llamadas por minuto
3. **Reintentos:** Maximo 3 reintentos por activo fallido
4. **Timeout:** 30 segundos maximo por llamada API
5. **Datos Stale:** Marcar activo como stale si no se actualiza en 15 minutos
6. **Cache:** Las llamadas exitosas actualizan cache Redis (TTL: 5 min)

---

## Criterios de Aceptacion

```gherkin
Escenario: Actualizacion exitosa de activos prioritarios
  DADO que el servicio Data Service esta corriendo
  Y la API de Polygon.io esta disponible
  CUANDO el batch job se ejecuta
  ENTONCES los activos XAU, EURUSD y BTCUSD se actualizan
  Y la tabla trading.symbols tiene datos recientes
  Y se publica un evento por cada activo actualizado

Escenario: Respeto del rate limit
  DADO que el rate limit es de 5 llamadas/minuto
  CUANDO el batch intenta hacer mas de 5 llamadas
  ENTONCES espera hasta que el minuto reinicie
  Y registra la espera en los logs

Escenario: Activos secundarios en cola
  DADO que hay 10 activos secundarios pendientes
  Y quedan 2 llamadas API disponibles en el minuto
  CUANDO el batch procesa la cola
  ENTONCES solo se procesan 2 activos
  Y los 8 restantes permanecen en cola para el siguiente ciclo

Escenario: Fallo de API
  DADO que la API de Polygon.io retorna error 500
  CUANDO el batch intenta actualizar un activo
  ENTONCES registra el error en data_sources.data_sync_status
  Y reintenta hasta 3 veces con backoff exponencial
  Y notifica si todos los reintentos fallan

Escenario: Ejecucion manual del batch
  DADO que el usuario tiene permisos de admin
  CUANDO hace POST /api/data/batch/run
  ENTONCES se ejecuta el batch inmediatamente
  Y retorna el resultado del batch job
```

---

## Dependencias

### Tecnicas:
- **PolygonClient** (existente): `apps/data-service/src/providers/polygon_client.py`
- **APScheduler 3.x:** Programacion de jobs
- **asyncpg:** Conexion a PostgreSQL
- **aioredis:** Publicacion de eventos
- **aiohttp:** Cliente HTTP async

### Funcionales:
- **INT-DATA-001:** Integracion base de Data Service
- **OQI-006 ML Signals:** Consume datos actualizados

---

## Notas Tecnicas

### API Key

```
POLYGON_API_KEY=f09bA2V7OG7bHn4HxIT6Xs45ujg_pRXk
```

**Nota:** Esta key es para cuenta gratuita. Para produccion, considerar upgrade a plan Starter ($47/mes) para rate limit ilimitado.

### Endpoints de Polygon.io Utilizados

| Endpoint | Uso |
|----------|-----|
| `/v2/snapshot/locale/global/markets/forex/tickers/{ticker}` | Snapshot Forex/Commodities |
| `/v2/snapshot/locale/global/markets/crypto/tickers/{ticker}` | Snapshot Crypto |
| `/v3/snapshot?ticker.any_of={tickers}` | Universal snapshot (multiple) |

### Consideraciones de Performance

- Usar conexiones HTTP persistentes (connection pooling)
- Implementar circuit breaker para fallos de API
- Mantener metricas de latencia para monitoreo
- Considerar batch de snapshots cuando se tenga plan de pago

---

## Historias de Usuario Relacionadas

| ID | Titulo | SP |
|----|--------|-----|
| US-DATA-001 | Como sistema, quiero actualizar precios de XAU cada 5 min | 3 |
| US-DATA-002 | Como sistema, quiero actualizar precios de EURUSD cada 5 min | 3 |
| US-DATA-003 | Como sistema, quiero actualizar precios de BTC cada 5 min | 3 |
| US-DATA-004 | Como sistema, quiero encolar activos secundarios | 5 |
| US-DATA-005 | Como admin, quiero ejecutar batch manualmente | 2 |
| US-DATA-006 | Como sistema, quiero publicar eventos de actualizacion | 3 |

**Total Story Points: 19**

---

## Referencias

- [Polygon.io Documentation](https://polygon.io/docs)
- [INT-DATA-001: Data Service Base](../integraciones/INT-DATA-001-data-service.md)
- [INT-DATA-003: Batch Actualizacion Activos](../integraciones/INT-DATA-003-batch-actualizacion-activos.md)

---

**Creado por:** Orquestador Agent
**Fecha:** 2026-01-04
**Ultima actualizacion:** 2026-01-04
