Tutorial de Bot de Polymarket · Capítulo 3 de 32
Elige tu stack para el bot de Polymarket: Python (py-clob-client 0.34.6), Node.js (@polymarket/clob-client-v2 v1.0.6) o Rust (sin SDK oficial, basado en ethers-rs). Pros, contras, latencia y ejemplos de código.
Qué cubre este capítulo
La elección del lenguaje importa mucho menos de lo que la mayoría de los builders supone. Polymarket expone los mismos endpoints REST y WebSocket a todos los lenguajes; la elección del SDK principalmente determina cuánto código glue escribes tú mismo. Python y Node tienen SDKs mantenidos oficialmente; Rust no, pero es viable para el hot path. Este capítulo repasa los trade-offs, muestra la misma tarea de "obtener el order book" en cada lenguaje para que la diferencia sea concreta, y termina con un patrón de stack mixto que es en lo que realmente se quedan la mayoría de los bots en producción.
- Marco de decisión
- Python (opción por defecto)
- Node.js (devs full-stack)
- Rust (hot path crítico para latencia)
- Comandos de setup por stack
- Esqueleto de código: obtener order book en 3 lenguajes
- Cuándo mezclar stacks (control plane en Python + hot path en Rust)
Marco de decisión
Tres preguntas resuelven el 90% de la elección del stack.
- ¿Tienes una habilidad existente fuerte? Si escribes Python a diario, escribe el bot en Python. Si escribes TypeScript a diario, escribe el bot en Node. Las diferencias de calidad del SDK abajo son reales, pero menores que el costo de pelearte con un lenguaje que no conoces.
- ¿La estrategia es crítica en latencia? Si tu edge depende de reaccionar en menos de 50ms (mercados cripto de 5 minutos, market making durante noticias), el hot path se beneficia de Rust o Go. La mayoría de las estrategias no necesitan esto.
- ¿Vas a correr más de una estrategia? Un solo proceso de Python puede manejar cómodamente 10-20 mercados. Más allá de eso, Node asíncrono o Python con procesos separados escala mejor.
El punto de partida honesto para un primer bot es Python. Cambia solo cuando una restricción medida te obligue a hacerlo.
Python (opción por defecto)
Python es la opción por defecto porque el SDK es el más completo y el ciclo de iteración es el más rápido. py-clob-client en la versión 0.34.6 (mayo de 2026) cubre todos los endpoints relevantes de CLOB v2: órdenes de mercado y límite, variantes FOK/FAK/GTC, lecturas de order book, lecturas de balance/allowance y operaciones directas en cadena a través de web3.py.
Pros: SDK maduro, análisis de datos fácil con pandas, comunidad grande, web3.py para lecturas on-chain. Contras: la ergonomía async es más incómoda que en JavaScript, el GIL limita las mejoras de velocidad multi-core (casi nunca importa para un bot I/O-bound), el tiempo de arranque en contenedores fríos es lento.
Recomendado para: 80% de los builders. Especialmente para cualquiera cuya estrategia implique backtesting, análisis estadístico o cualquier trabajo de datos junto con la ejecución.
Node.js (devs full-stack)
Node.js es el segundo stack mejor soportado. @polymarket/clob-client-v2 en la versión 1.0.6 cubre los mismos endpoints que el SDK de Python, con tipos TypeScript de principio a fin. Async es nativo y rápido; el manejo de WebSocket es excelente.
Pros: la mejor historia async, tipos TypeScript nativos, ecosistema grande para HTTP + WS, despliegue fácil en el mismo runtime de Node que un dashboard web. Contras: la precisión numérica requiere BigInt o manejar strings para token IDs grandes (los IDs ERC-1155 son de 256 bits), las herramientas de datos equivalentes a pandas son más débiles.
Recomendado para: builders que ya mantienen un stack JavaScript y quieren un solo runtime. También para cualquiera que construya un dashboard junto con el bot: compartir tipos entre el core del bot y un dashboard de Next.js elimina una clase de bugs.
Rust (hot path crítico para latencia)
Rust no tiene SDK oficial de Polymarket. Se construye directamente contra las APIs V2 REST y WebSocket usando reqwest (HTTP), tokio-tungstenite (WebSocket) y ethers-rs o alloy para firmar. Aproximadamente dos días de trabajo de setup frente a 30 minutos en Python.
Pros: firma EIP-712 nativa sin un subproceso JS, construcción de órdenes en sub-milisegundos, perfil de memoria determinista bajo carga, sin pausas de GC. Contras: al no haber SDK, tienes que reimplementar lo que los usuarios de Python obtienen gratis (parseo de clobToken ID, validación de esquemas de respuesta, gestión de salt/nonce). La mejora en latencia es de 20-100ms frente a Python afinado, lo cual solo importa para estrategias de menos de un segundo.
Recomendado para: el hot path de un bot de market making, o la pata de ejecución de un bot de arbitraje por noticias. Casi nunca para todo el bot.
Comandos de setup por stack
Comandos mínimos para obtener una orden firmada funcionando contra mainnet (un solo endpoint de CLOB v2).
Python:
python -m venv venv && source venv/bin/activate
pip install py-clob-client==0.34.6 web3 python-dotenv
# Set POLYGON_RPC, PRIVATE_KEY, POLY_FUNDER in .env
Node:
npm init -y
npm install @polymarket/[email protected] ethers dotenv
# Set POLYGON_RPC, PRIVATE_KEY, POLY_FUNDER in .env
Rust:
cargo new --bin pmt
cd pmt
cargo add tokio reqwest serde serde_json ethers alloy tungstenite tokio-tungstenite
# Hand-write signer + endpoint client; no SDK shortcut.
Tiempo hasta la primera orden: ~10 min en Python, ~15 min en Node, ~4-8 horas en Rust.
Esqueleto de código: obtener order book en 3 lenguajes
La misma tarea - obtener el order book de un token de Polymarket - en cada stack. Los tres usan el mismo endpoint REST de CLOB v2.
Python (py-clob-client):
from py_clob_client.client import ClobClient
client = ClobClient(host="https://clob.polymarket.com", chain_id=137)
book = client.get_order_book("<token_id>")
print(book.bids[:3], book.asks[:3])
Node (@polymarket/clob-client-v2):
import { ClobClient } from "@polymarket/clob-client-v2";
const c = new ClobClient({ host: "https://clob.polymarket.com", chain: 137 });
const book = await c.getOrderBook("<token_id>");
console.log(book.bids.slice(0,3), book.asks.slice(0,3));
Rust (HTTP directo):
let url = format!("https://clob.polymarket.com/book?token_id={}", token);
let book: serde_json::Value = reqwest::get(&url).await?.json().await?;
println!("{:?} {:?}", &book["bids"][..3], &book["asks"][..3]);
La misma forma de respuesta en los tres. El costo de Rust está en todo lo demás - firma, construcción de órdenes, manejo de errores - no en la ruta de lectura.
Cuándo mezclar stacks (control plane en Python + hot path en Rust)
El patrón al que convergen muchos bots en producción: Python para todo lo que involucra decisiones, Rust para la pata de ejecución de milisegundos.
Arquitectura: un proceso de Python lee el estado del mercado, ejecuta la lógica de estrategia y escribe un archivo pequeño de comando (por ejemplo {"action":"buy","token":"...","size":10,"price":0.45}) a un Unix socket. Un daemon en Rust escucha ese socket, firma la orden y la publica en el CLOB. El proceso de Python puede ser lento y cómodo; el daemon en Rust es rápido y minimalista.
El handoff es la clave: al aislar el paso de orden firmada, se recupera el budget de fallos de Python sin sacrificar latencia. Usamos exactamente este patrón en nuestros bots de producción - Python emite intenciones, un daemon de Node en /tmp/clob.sock se encarga de firmar. La versión en Node del daemon está bien para menos de 100ms; Rust solo vale realmente la pena por debajo de 50ms.












