M
en
Arbitraje en mercados de predicción
En Progreso

Arbitraje en mercados de predicción

Python Prediction-Markets

SurePred es un bot automatizado que detecta y ejecuta oportunidades de arbitraje entre dos plataformas de mercados de predicción: Kalshi y Polymarket. El objetivo es encontrar situaciones donde se pueda apostar a ambos lados de un mismo evento (sí y no) en diferentes plataformas, garantizando una ganancia sin importar el resultado final del evento.

¿Qué son los Mercados de Predicción?

Los mercados de predicción son plataformas donde las personas pueden comprar y vender "contratos" sobre el resultado de eventos futuros. Funcionan como mercados financieros, pero en lugar de acciones, se comercian predicciones.

Ejemplo

Imagina un mercado sobre: "¿Subirá la Reserva Federal los tipos de interés en la próxima reunión?"

  • Si crees que , compras un contrato "Yes" por, digamos, $0.40
  • Si crees que no, compras un contrato "No" por $0.60

Cuando el evento se resuelve:

  • Si la Fed sube los tipos → el contrato "Yes" vale $1.00, el "No" vale $0.00
  • Si la Fed no sube los tipos → el contrato "Yes" vale $0.00, el "No" vale $1.00

¿Qué es el Arbitraje?

El arbitraje es una estrategia que aprovecha las diferencias de precios entre mercados para obtener una ganancia garantizada, independientemente del resultado.

Ejemplo de arbitraje

Supongamos que tenemos el mismo evento en dos plataformas:

Evento: "¿Ganará Jeannette Jara la primera ronda de las elecciones presidenciales de Chile 2025?"

Plataforma Precio YES Precio NO
Polymarket $0.45 $0.57
Kalshi $0.52 $0.46

Estrategia de arbitraje:

  • Comprar YES en Polymarket: $0.45
  • Comprar NO en Kalshi: $0.46
  • Costo total: $0.45 + $0.46 = $0.91

Resultados posibles:

  • Si Jara gana → ganamos $1.00 de Polymarket (YES) → Beneficio = $1.00 - $0.91 = $0.09 (9.89% ROI)
  • Si Jara no gana → ganamos $1.00 de Kalshi (NO) → Beneficio = $1.00 - $0.91 = $0.09 (9.89% ROI)

Ganamos lo mismo sin importar el resultado.

Fórmula del arbitraje

Para que exista arbitraje, la suma de los precios complementarios debe ser menor a 1:

PyesPolymarket+PnoKalshi<1P_{yes}^{Polymarket} + P_{no}^{Kalshi} < 1

o

PnoPolymarket+PyesKalshi<1P_{no}^{Polymarket} + P_{yes}^{Kalshi} < 1

El ROI (Return on Investment) se calcula como:

ROI=1(P1+P2)P1+P2×100%ROI = \frac{1 - (P_1 + P_2)}{P_1 + P_2} \times 100\%

Donde P1P_1 y P2P_2 son los precios de las posiciones complementarias.

¿Cuánto dinero invertir en cada plataforma?

Para ejecutar el arbitraje, necesitamos comprar el mismo número de contratos en ambas plataformas. Cada contrato paga $1.00 si gana.

Paso 1: Calcular el máximo de contratos posibles

Dado un presupuesto total BB, el número máximo de contratos está limitado por la plataforma más cara:

Ncontratos=min(BPolymarketPyesPoly,BKalshiPnoKalshi)N_{contratos} = \left\lfloor \min\left(\frac{B_{Polymarket}}{P_{yes}^{Poly}}, \frac{B_{Kalshi}}{P_{no}^{Kalshi}}\right) \right\rfloor

Paso 2: Calcular el dinero a invertir en cada plataforma

DineroPolymarket=Ncontratos×PyesPolymarketDinero_{Polymarket} = N_{contratos} \times P_{yes}^{Polymarket} DineroKalshi=Ncontratos×PnoKalshiDinero_{Kalshi} = N_{contratos} \times P_{no}^{Kalshi}

Ejemplo con presupuesto de $100:

Supongamos que tenemos $50 en cada plataforma con los precios del ejemplo anterior:

  • Precio YES Polymarket: $0.45
  • Precio NO Kalshi: $0.46

Contratos máximos: N=min(500.45,500.46)=min(111.1,108.7)=108N = \left\lfloor \min\left(\frac{50}{0.45}, \frac{50}{0.46}\right) \right\rfloor = \left\lfloor \min(111.1, 108.7) \right\rfloor = 108

Inversión por plataforma:

  • Polymarket: 108×0.45=$48.60108 \times 0.45 = \$48.60
  • Kalshi: 108×0.46=$49.68108 \times 0.46 = \$49.68
  • Total invertido: $98.28

Ganancia garantizada:

  • Pago al resolver: 108×1.00=$108.00108 \times 1.00 = \$108.00
  • Beneficio neto: $108.00 - $98.28 = $9.72 (9.89% ROI)

El problema: econtrar parejas de mercados entre plataformas

Uno de los mayores desafíos del proyecto es identificar cuándo dos mercados en diferentes plataformas se refieren al mismo evento. Las plataformas no usan los mismos identificadores ni la misma redacción.

Ejemplo del problema

El mismo evento político puede aparecer como:

  • Polymarket: "Will Jeannette Jara win the 1st round of the 2025 Chilean presidential election?"
  • Kalshi: "Will Jeannette Jara win the 2025 Chile Presidential election first round?"

O un evento económico:

  • Polymarket: "Will the Fed raise interest rates in December 2025?"
  • Kalshi: "Federal Reserve December 2025 rate decision: Raise?"

Las preguntas son similares pero no idénticas, lo que complica el matching automático.


Solución actual: embeddings + similitud del coseno

Para resolver el problema del matching, el sistema utiliza TF-IDF (Term Frequency-Inverse Document Frequency) para convertir las preguntas de texto en vectores numéricos, y luego calcula la similitud del coseno entre ellos.

¿Qué es TF-IDF?

TF-IDF es una técnica de procesamiento de lenguaje natural que convierte texto en vectores numéricos, asignando más peso a las palabras que son:

  1. Frecuentes en el documento (TF - Term Frequency)
  2. Poco frecuentes en el conjunto de documentos (IDF - Inverse Document Frequency)
TF-IDF(t,d)=TF(t,d)×IDF(t)TF\text{-}IDF(t, d) = TF(t, d) \times IDF(t)

Donde:

  • TF(t,d)TF(t, d) = frecuencia del término tt en el documento dd
  • IDF(t)=log(Ndf(t))IDF(t) = \log\left(\frac{N}{df(t)}\right)
  • NN = número total de documentos
  • df(t)df(t) = número de documentos que contienen el término tt

¿Qué es la similitud del coseno?

Una vez que tenemos los vectores TF-IDF, medimos qué tan similares son calculando el coseno del ángulo entre ellos:

similitud(A,B)=cos(θ)=ABA×B\text{similitud}(\vec{A}, \vec{B}) = \cos(\theta) = \frac{\vec{A} \cdot \vec{B}}{||\vec{A}|| \times ||\vec{B}||}

Donde:

  • AB\vec{A} \cdot \vec{B} = producto punto de los vectores
  • A||\vec{A}|| = magnitud (norma) del vector A
  • El resultado está en el rango [0,1][0, 1]

Interpretación:

  • 1.0 = Los textos son idénticos
  • 0.7-1.0 = Alta similitud, probablemente el mismo evento
  • 0.4-0.7 = Similitud media, requiere revisión
  • 0.0-0.4 = Baja similitud, probablemente eventos diferentes

Ejemplo

El siguiente gráfico 3D interactivo muestra cómo funciona la similitud del coseno. En realidad, el espacio tiene miles de dimensiones, pero aquí se representan solo tres para poder visualizar el ejemplo.

Los vectores más cercanos (ángulo pequeño, coseno alto) representan mercados similares, mientras que los vectores alejados representan mercados diferentes:

Arrastra y selecciona las parejas para rotar el gráfico.

Proceso actual

Actualmente, el proceso de emparejar mercados se realiza de forma semi-automática:

  1. Descarga de mercados: Se obtienen todos los mercados disponibles de ambas plataformas
  2. Matching automático: El algoritmo de TF-IDF + similitud del coseno encuentra candidatos
  3. Revisión manual: Se revisan los matches y se confirma cuáles son correctos
  4. Guardado en JSON: Los mercados validados se almacenan en monitoring_markets.json

Monitoreo de precios en tiempo real

Una vez que tenemos los mercados emparejados, el sistema monitorea sus precios en tiempo real:

Arquitectura del Streaming

graph LR
    P[Polymarket<br>WebSocket] -->|Market Data| M[MarketPairMonitor]
    K[Kalshi<br>WebSocket] -->|Market Data| M
    
    subgraph Stream[Stream Processing]
        M -->|Updates| DF[DataFrame<br>con precios]
        DF -->|Data Stream| AC[ArbitrageCalculator<br>Detecta arbitraje]
    end
    
    AC -->|Signal| AT[ArbitrageTrader<br>Ejecuta órdenes]
    
    style P fill:#2d2d2d,stroke:#fff,stroke-width:2px
    style K fill:#2d2d2d,stroke:#fff,stroke-width:2px
    style M fill:#1a1a1a,stroke:#3b82f6,stroke-width:2px
    style DF fill:#1a1a1a,stroke:#3b82f6,stroke-width:2px
    style AC fill:#1a1a1a,stroke:#10b981,stroke-width:2px
    style AT fill:#1a1a1a,stroke:#f59e0b,stroke-width:2px

Configuración del bot: config.json

El comportamiento del bot se controla mediante el archivo config.json:

Parámetros:

Parámetro Tipo Descripción
mode string "betting": Ejecuta órdenes automáticamente
"listening": Solo monitorea, guarda oportunidades sin ejecutar
"off": Bot inactivo
max_absolute_bet number Máximo dinero ($) a invertir en cada lado de un mercado
min_absolute_bet number Mínimo dinero requerido para ejecutar una operación
min_ROI_per_bet number ROI mínimo (%) requerido para considerar una oportunidad
max_end_days integer Solo considera mercados que terminan en los próximos N días
debug_stop_first_bet boolean Si es true, el bot se detiene después de la primera operación (testing)