diff --git a/README.md b/README.md index 412b72d..3de0ea8 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,118 @@ # polymarket-bot -Bot de paper-trading para Polymarket con estrategia bayesiana, API FastAPI y -dashboard React. Corre en k3s vía GitOps (Gitea Actions → registry → ArgoCD). +Bot de **paper trading** para mercados de predicción de Polymarket: estrategia +bayesiana sobre el precio de mercado como prior, señales externas en log-odds, +gates de riesgo en cascada y un motor de replay determinista para calibración +offline. API FastAPI + dashboard React. Desplegado en k3s vía GitOps +(Gitea Actions → registry → ArgoCD), con PostgreSQL, secrets por Infisical y +observabilidad completa (Grafana, uptime-kuma, Telegram). + +> **📦 Estado del proyecto: ARCHIVADO (julio 2026).** +> El 26 de mayo de 2026 la DGOJ [ordenó el bloqueo cautelar de Polymarket y +> Kalshi en España](https://www.ordenacionjuego.es/novedades/dgoj-abre-expediente-sancionador-plataformas-polymarket-kalshi-ordena-bloqueo-sus-webs) +> por operar sin licencia de juego ([CoinDesk](https://www.coindesk.com/policy/2026/05/26/spain-joins-growing-list-of-countries-shutting-out-polymarket-and-kalshi)). +> Con el bloqueo a nivel de ISP la fuente de datos primaria desaparece, así que +> el proyecto se jubila de forma ordenada: datos respaldados y verificados, +> resultados documentados en el [informe final](docs/informe-final.md), e +> infraestructura apagada vía GitOps. El cierre es parte de la historia del +> proyecto, no un abandono — los módulos centrales son agnósticos de la fuente +> y el pivote natural es Manifold Markets (API abierta, play-money, sin +> fricción regulatoria). + +## El problema y la solución + +Los mercados de predicción publican probabilidades implícitas en el precio. +La hipótesis: en mercados de bajo volumen hay ineficiencias detectables +combinando el precio con señales externas (noticias, sentimiento cripto, +mercados espejo en otras plataformas). El bot la pone a prueba **sin arriesgar +dinero**, con la disciplina de un sistema real: + +1. **Prior desde el precio** de Polymarket (mid del order book CLOB). +2. **Ajuste bayesiano en log-odds** con señales independientes: GNews (con + presupuesto de 5 consultas/día y *guardrail* que limita el ajuste a + prior±0,25), Fear&Greed, momentum BTC, dominancia BTC, y Manifold Markets + como señal cruzada (en modo observacional tras detectarse un bug de + inversión — auditado en 165k filas). +3. **Gates en cascada** antes de operar: prior extremo (<0,08 / >0,92), edge + bruto mínimo por régimen de volatilidad, edge neto positivo tras comisión + (2%) y spread, confianza ≥0,55, conflicto de familias, guard de reentrada. +4. **Agrupación por familias de mercados**: mercados hermanos del mismo evento + (candidatos de una misma elección, umbrales de un mismo precio) comparten + `family_key`; solo se mantiene la posición de mayor edge para no apilar la + misma apuesta con dos nombres. +5. **Sizing por Kelly fraccionado** con techo por posición sobre un bankroll + simulado de $10.000. + +Resultado honesto en 81 días: 12 trades (n estadísticamente irrelevante, y el +informe lo subraya), realized **+$247,78**, y — más interesante — **~223.000 +evaluaciones archivadas con su decisión reproducible**, porque el sistema +prefirió no operar antes que operar sin ventaja medible. +Detalle completo: [docs/informe-final.md](docs/informe-final.md). + +## Arquitectura + +```mermaid +flowchart LR + subgraph ext["Fuentes externas"] + PM["Polymarket
CLOB + Gamma API"] + GN["GNews"] + MF["Manifold Markets"] + CG["CoinGecko /
alternative.me"] + end + + subgraph k3s["k3s · namespace polymarket-bot"] + BOT["bot (ciclo ~64s)
estrategia bayesiana + gates"] + PG[("PostgreSQL 16
trades · signals · replay")] + API["api (FastAPI :8000)"] + DASH["dashboard (React/nginx)"] + CJ1["CronJob metrics-retention 00:10"] + CJ2["CronJob outcomes-joiner 00:30"] + end + + subgraph obs["Observabilidad"] + GRAF["Grafana"] + UK["uptime-kuma"] + TG["Telegram"] + end + + PM --> BOT + GN --> BOT + MF --> BOT + CG --> BOT + BOT --> PG + PG --> API + API --> DASH + API --> GRAF + UK --> DASH + BOT --> TG + PM --> CJ2 + CJ2 --> PG + CJ1 --> PG + + subgraph ci["GitOps"] + GA["Gitea Actions"] --> REG["registry"] --> ARGO["ArgoCD
prune + selfHeal"] + end + ARGO -.-> k3s +``` + +## Decisiones de diseño + +- **Paper trading por diseño, no como demo**: el bot exigía ≥10 mercados + resueltos y ≥30 días antes de considerarse promocionable a dinero real, y + reportaba `n/a (insufficient_sample)` en vez de métricas infladas. +- **Todo skip es un dato**: cada evaluación archiva prior, estimación, edge + bruto/neto, descomposición por feature en log-odds y el gate exacto que la + bloqueó (~55k filas/día en `signals`). +- **Replay determinista** (julio 2026): inyección de reloj + re-ejecución de + ciclos archivados con 22.697/22.697 decisiones idénticas; joiner diario de + resoluciones UMA para calibrar sobre *todas* las evaluaciones, no solo los + trades. +- **Los errores se cierran y se documentan**: el bug de inversión de Manifold + y los conflictos de familia cerraron 5 posiciones en abril; la señal pasó a + observacional-only con auditoría completa en vez de eliminarse. +- **GitOps estricto**: nunca `kubectl` para cambios persistentes (ArgoCD con + `selfHeal` revierte cualquier parche manual); secrets fuera de git vía + Infisical operator; smoke test PostSync con notificación a Telegram. ## Componentes @@ -11,10 +122,19 @@ dashboard React. Corre en k3s vía GitOps (Gitea Actions → registry → ArgoCD | api | `api/` (+ `bot/` como librería) | `polymarket-bot-api` | `uvicorn api.main:app` | | dashboard | `dashboard/` | `polymarket-bot-dashboard` | nginx estático | -Dashboard: https://polymarket.chemavx.xyz +Dashboard (hasta el apagado): https://polymarket.chemavx.xyz + +## Stack + +Python 3 (asyncio) · FastAPI · React + Vite · PostgreSQL 16 · k3s · ArgoCD · +Gitea Actions + BuildKit · Infisical (secrets) · Grafana + Prometheus · +uptime-kuma · Telegram Bot API. ## CI/CD +> ⚠️ **Decomisión**: el trigger automático `push:main` se desactivó en la Fase 1 +> del archivado; el workflow queda solo bajo `workflow_dispatch` manual. + `.gitea/workflows/ci.yml` construye **solo las imágenes cuyos ficheros cambiaron** en el push (diff contra `github.event.before`): @@ -33,3 +153,17 @@ sincroniza vía webhook en segundos. ```bash python3 -m pytest tests/ -q ``` + +## Datos y backup + +Base de datos respaldada y verificada (2026-07-06): `pg_dump -Fc` + exports +CSV.gz de las tablas de señales y auditoría, con checksums y restore de prueba +(recuentos idénticos 11/11 tablas). Ubicación: almacenamiento de backups del +clúster con sync offsite. El dump final se toma en la fase de apagado. + +## Documentación + +- [Informe final de paper trading](docs/informe-final.md) — resultados, + pipeline de datos y estado de la BD al cierre. +- `docs/pivot-manifold.md` — notas de diseño del posible pivote (Fase 5, + pendiente).