El Trend Tracker escucha X, Reddit, YouTube, prensa y GDELT en español, agrupa lo que de verdad se está moviendo en República Dominicana y LATAM, y redacta la pregunta de mercado con su regla de resolución y su fuente oficial. Ningún mercado sale sin que una persona lo apruebe.
Ocho pasos, todos automáticos menos uno: la aprobación. Cada paso corre en su propio beat de Celery, así que una fuente caída nunca detiene al resto de la cadena.
Seis ingestores traen posts, videos, hilos y notas de prensa en español. Cada uno con su propia cadencia y su propio manejo de límites de API.
ingestion/*_ingestor.pySimHash con ventana de 24 horas y umbral Hamming de 6 (~93% de similitud). El retuit copiado mil veces entra una sola vez al corpus.
utils/dedup.pyModelo multilingüe E5 sobre cada post, guardado en Qdrant. El español dominicano, el mexicano y el titular de prensa caen cerca cuando hablan de lo mismo.
embeddings/encoder.pyHDBSCAN sobre una ventana de 72 horas. Los clústeres nuevos se reconectan con los existentes por similitud de centroide, así una tendencia mantiene su identidad entre pasadas.
clustering/clusterer.pyVelocidad, volumen, relevancia geográfica, dispersión entre plataformas y novedad. Los componentes que no informan nada se descartan y los pesos se renormalizan.
clustering/scorer.pyClaude lee los ocho posts más representativos y devuelve de una a tres variantes con salida estructurada: pregunta, resultados, regla de resolución, fuente y banderas de riesgo.
market_scorer/pipeline.pyCada pregunta se compara contra los mercados que ya existen en PREDIX. Por encima de 0.90 de similitud coseno se marca duplicada y no llega a la cola.
market_scorer/dedup.pyUna persona aprueba o rechaza. Lo aprobado sale por webhook firmado con HMAC-SHA256, con clave de idempotencia y hasta cinco reintentos.
webhook/sender.pyLa dispersión entre plataformas vale 15% del puntaje: un tema que solo vive en X pesa menos que uno que además aparece en prensa y en Reddit. Cada fuente corre en su propio intervalo y se apaga sola si le faltan credenciales.
Cuatro consultas en español afinadas para RD: LIDOM y béisbol, política y Congreso, deportes LATAM, y cripto y mercados.
Nueve subreddits de la región, de r/Dominican y r/SantoDomingo a r/mexico, r/argentina y r/PuertoRico.
Tendencias por país en siete mercados más los canales dominicanos que marcan la conversación: Alofoke, Cachicha, Z101.
Feeds de medios dominicanos y regionales. El cuerpo del artículo se extrae completo y viaja al prompt, no solo el titular.
Cobertura global indexada, útil cuando una historia internacional empieza a tocar la región antes de que la prensa local la levante.
Ingestor escrito y probado, apagado por bandera hasta que el acceso a la API de contenido quede aprobado.
Esta es la fórmula real del motor, no una animación. Los cinco componentes se normalizan a [0,1], se ponderan y se suman. Si un componente no puede variar en este despliegue, se descarta y su peso se reparte entre los que sí informan.
Por encima de 0.70 el clúster entra en la cola del curador y Claude redacta sus variantes.
Seis clústeres reales del 25 de agosto de 2026. Elige uno y verás exactamente lo que Claude devolvió: la pregunta en español, la regla que la resuelve, la fuente oficial, las banderas de riesgo y el resultado del contraste contra los mercados existentes.
El curador marca is_marketable: false y explica por qué. Estos rechazos no son un filtro posterior: son parte del contrato de salida del modelo, y quedan guardados para alimentar los ejemplos del próximo prompt.
Enfermedad, muerte o daño a alguien identificable. Se rechaza aunque la conversación sea enorme.
Cualquier pregunta que gire alrededor de un menor, sin excepción.
Y todo lo que dependa de que alguien salga lastimado para resolverse.
Preguntas que apuntan a grupos protegidos o que se apoyan en un prejuicio.
Si dos personas de buena fe pueden leer el resultado distinto, no hay mercado.
Sin un box score, un boletín oficial o un precio de referencia, la propuesta no pasa.
La aprobación queda registrada aparte del estado de envío, porque son dos cosas distintas: una es la decisión humana, la otra es si el paquete llegó.
Cada envío va firmado con un secreto compartido. El receptor de PREDIX verifica la firma antes de mirar el cuerpo.
La idempotency_key es única en base de datos. Cinco reintentos con la misma clave crean un mercado, no cinco.
Con predix_webhook_dry_run encendido el paquete se registra completo pero no sale. Así se probó toda la cadena antes de que existiera el receptor.
El beat de despacho mueve approved → sent en menos de 60 segundos. Por eso decision y decided_at se guardan por separado: si no, los ejemplos aprobados desaparecerían del prompt casi al instante.
El campo schema_version viaja en cada paquete, así el contrato puede evolucionar sin romper receptores viejos.
// X-Predix-Signature: sha256=8f2c…d41b { "schema_version": "1.0", "event": "market.create", "idempotency_key": "mp_10482_a41f9c", "proposal": { "id": 10482, "group_id": "a41f9c2e-7b30-4d1a-9f85-2c6e0b3d5417", "variant_label": "binary", "category": "sports", "question": "¿Conectará Vladimir Guerrero Jr. su jonrón número 50 antes del 15 de septiembre?", "outcome_type": "binary", "outcomes": ["Sí", "No"], "resolution_source": "MLB.com — box score oficial", "expiry_at": "2026-09-15T03:59:00Z", "initial_probability": 0.41, "scorer_confidence": 0.88, "risk_flags": [], "model_used": "claude-opus-5" }, "trend": { "cluster_id": "c_7f3a91", "trend_score": 0.81, "volume": 523, "velocity_z": 3.8, "country_codes": ["DO", "PR", "US"], "source_counts": { "x": 412, "news": 51, "reddit": 38, "youtube": 22 }, "source_diversity": 0.61 }, "source_metadata": { "platform": "trend-tracker", "platform_version": "0.8" } }
Este motor lo diseñamos, lo escribimos y lo operamos nosotros — de la ingesta al webhook firmado. Lo mismo aplica a cualquier flujo donde alguien está leyendo a mano lo que una máquina debería estar leyendo sola.