Antecedentes de la estrategia
A principios de este año, corrió el rumor en la comunidad sobre alguien que había ganado una casa de la noche a la mañana en Polymarket. Con curiosidad, busqué el marco de trading específico, pero todo eran titulares sensacionalistas, sin una sola línea de código. Al no tener más remedio, tuve que hacerlo yo mismo.
Al principio no tenía ni idea. Polymarket es la plataforma de mercados de predicción descentralizada más grande, con más de 60,000 activos listados que cubren política, deportes, macroeconomía y prácticamente cualquier evento predecible. Cada activo es esencialmente un contrato de opción binaria: si el resultado ocurre, el precio converge a 1; si no, a cero. Para ganar dinero, lo mejor es la información privilegiada. Pero la gente común no sabe cuántos tuits publicará Elon Musk la próxima semana, ni si la Fed bajará las tasas en la próxima reunión, y no tiene tiempo ni energía para seguir el mercado, analizar cotizaciones o tomar decisiones.
Entonces pensé: ¿podría cambiar de enfoque? En lugar de perseguir la información, perseguir el capital. Quienes tienen ventaja informativa se posicionan con anticipación, y sus compras inevitablemente dejan huellas en el precio y el volumen. Incluso sin conocer los «secretos», se puede inferir si alguien está acumulando posiciones observando el comportamiento del capital. Siguiendo esta idea, construí un sistema de trading inteligente con múltiples roles, que integra la detección de señales en velas, verificación de sentimiento, juicio de IA y ejecución automática de órdenes con control de riesgos en una línea de producción completa.
Arquitectura del sistema
Todo el sistema se ejecuta en el flujo de trabajo del inventor, con dos rutas de programación paralelas: la principal y la secundaria, completamente desacopladas y sin bloqueo mutuo.
| Ruta de programación | Frecuencia de activación | Módulos responsables | Tarea central |
|---|---|---|---|
| Línea principal de trading | Cada 10 minutos | Selección de activos → Procesamiento cíclico → Agente IA → Ejecución de trading | Buscar oportunidades, abrir posiciones |
| Línea secundaria de trading | Cada 30 segundos | Take profit / Stop loss | Monitoreo de posiciones, trailing stop, rescate al vencimiento |
La línea principal se encarga de «buscar oportunidades y abrir posiciones». Cada ronda de ejecución incluye cuatro fases secuenciales: selección preliminar → detección de anomalías en velas → búsqueda de noticias → análisis multi-rol de IA, para finalmente generar una señal de compra y ejecutar la orden. La línea secundaria solo se ocupa de «las posiciones existentes», ejecutándose continuamente en ciclos de 30 segundos, sin detenerse independientemente de si la línea principal tiene tareas en curso.
Este diseño separado resuelve un problema real: los cambios de precio en los mercados de predicción son continuos, pero el análisis de selección de activos es pesado en cálculo y de alta latencia. Si el monitoreo de stop loss se incluyera en la línea principal, cuando el análisis de IA sea lento, la respuesta de stop loss se retrasaría gravemente. La programación independiente es una compensación de ingeniería necesaria.
Explicación detallada de cada módulo
Selección preliminar: eliminar primero los activos basura
No es posible analizar 60,000 activos uno por uno, por lo que el primer filtro es puramente basado en reglas, con un solo objetivo: eliminar rápidamente los activos que claramente no merecen atención, dejando los recursos computacionales para los que realmente tienen valor.
Las condiciones de filtro incluyen: límite inferior de liquidez (demasiado baja significa dificultad para comprar/vender), límite inferior de volumen en 24 horas (activos casi sin transacciones carecen de valor de referencia), límite superior de diferencial de compra-venta (diferencial grande implica alto costo de deslizamiento), límite superior de competencia, y un rango de precio: solo se consideran activos con probabilidad implícita del mercado entre el 5% y el 50%. Los demasiado altos ya están completamente valorados y tienen poco espacio al alza; los demasiado bajos son dudosos y se acercan más a una lotería que a una oportunidad de arbitraje.
Después del filtro, para el mismo evento suele haber dos direcciones listadas (Sí y No). La estrategia solo retiene la dirección con el precio más bajo, porque el extremo de menor precio tiene mayor elasticidad de cuotas y un retorno potencial más alto.
javascript
let truePrice = parseFloat(outcomePrices[outcomeIndex] || 0)
if (truePrice < CONFIG.MIN_TRUE_PRICE || truePrice > CONFIG.MAX_TRUE_PRICE) continue
let isActive = (
info.active === true && info.approved === true &&
info.closed === false && info.archived === false &&
info.acceptingOrders === true && info.pendingDeployment === false
)
if (!isActive) continue
let spreadPct = (ask - bid) / ask
if (spreadPct > CONFIG.MAX_SPREAD_PCT) continue
// Mismo evento: solo mantener la dirección de menor precio
if (!marketMap[baseSymbol]) {
marketMap[baseSymbol] = entry
} else if (truePrice < marketMap[baseSymbol].price) {
marketMap[baseSymbol] = entry
}
Todos los umbrales de filtro se exponen como parámetros externos a través de la variable $vars, que se pueden ajustar libremente según la tolerancia al riesgo y el tamaño del capital, sin necesidad de modificar el código.
Detección de anomalías en velas: encontrar las huellas del capital
Después del filtro grueso, para cada activo aprobado se obtienen las últimas 240 velas de 60 minutos y se ejecutan cinco tipos de detección de anomalías. Esta es la capa de señal central de la estrategia y la diferencia más esencial entre todo el sistema y «simplemente pasar el evento a la IA para su análisis»: no adivinamos el resultado del evento, buscamos el comportamiento del capital.
Ascenso lento: El aumento total de las últimas 120 velas supera el 5%, pero el aumento máximo de una sola vela es inferior al 1.5%. Esta característica describe una postura de acumulación en la que el capital se contiene deliberadamente para evitar llamar la atención.
Crecimiento lineal del volumen: Se realiza una regresión lineal en la secuencia de volumen de las últimas 60 velas, con pendiente positiva y R² mayor a 0.5, lo que indica que el volumen aumenta de manera constante y estable, no por impulsos aleatorios. R² es clave: filtra los casos de «un solo pico de volumen, el resto silencioso».
Reducción de retrocesos: Se calcula la profundidad máxima de cada retroceso después del máximo histórico. Si el retroceso promedio reciente es inferior al 60% del retroceso temprano, indica que la presión de venta está disminuyendo y las posiciones se están estabilizando; alguien está absorbiendo. Durante cada retroceso, se rastrea continuamente el precio mínimo para calcular la amplitud completa del retroceso.
Ruptura de rango lateral: La desviación entre MA60 y MA120 es inferior al 2% (estado lateral), mientras que el precio actual supera MA60 en un 3%, lo que se interpreta como una ruptura del nivel de resistencia anterior.
Aumento repentino del volumen: El volumen promedio de las últimas 5 velas supera 2.5 veces el volumen base de las últimas 60 velas, lo que se interpreta como una aceleración de la entrada de capital.
javascript
function linearRegression(values) {
let n = values.length
let sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0
for (let i = 0; i < n; i++) {
sumX += i; sumY += values[i]
sumXY += i * values[i]; sumX2 += i * i
}
let slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX)
let intercept = (sumY - slope * sumX) / n
let meanY = sumY / n
let ssTot = 0, ssRes = 0
for (let i = 0; i < n; i++) {
ssTot += Math.pow(values[i] - meanY, 2)
ssRes += Math.pow(values[i] - (slope * i + intercept), 2)
}
let r2 = ssTot === 0 ? 0 : 1 - ssRes / ssTot
return { slope, intercept, r2 }
}
function detectAnomaly(closes, volumes) {
if (closes.length < 60) return null
let anomalies = [], score = 0
let slice120 = closes.slice(-Math.min(120, closes.length))
// ── 异常1:缓慢爬升 ──────────────────────────────────────
let totalChange = (slice120[slice120.length - 1] - slice120[0]) / slice120[0]
let maxSingle = 0
for (let i = 1; i < slice120.length; i++) {
let change = Math.abs(slice120[i] - slice120[i - 1]) / slice120[i - 1]
if (change > maxSingle) maxSingle = change
}
if (totalChange > 0.05 && maxSingle < 0.015) {
score++
anomalies.push(`缓慢爬升 总涨${(totalChange * 100).toFixed(1)}% 单根最大${(maxSingle * 100).toFixed(2)}%`)
}
// ── 异常2:成交量线性增长 ─────────────────────────────────
let volSlice = volumes.slice(-60)
let volReg = linearRegression(volSlice)
if (volReg.slope > 0 && volReg.r2 > 0.5) {
score++
anomalies.push(`成交量线性增长 斜率${volReg.slope.toFixed(4)} R²${volReg.r2.toFixed(2)}`)
}
// ── 异常3:回调收窄(追踪每次回调最低价,计算完整深度)────
let pullbacks = [], localHigh = closes[0]
let inPullback = false, pullbackLow = closes[0]
for (let i = 1; i < slice120.length; i++) {
if (closes[i] > localHigh) {
if (inPullback) {
pullbacks.push((localHigh - pullbackLow) / localHigh)
inPullback = false
}
localHigh = closes[i]
} else if (closes[i] < localHigh * 0.99) {
if (!inPullback) { inPullback = true; pullbackLow = closes[i] }
else if (closes[i] < pullbackLow) { pullbackLow = closes[i] }
}
}
if (pullbacks.length >= 3) {
let first = pullbacks.slice(0, Math.floor(pullbacks.length / 2))
let last = pullbacks.slice(Math.floor(pullbacks.length / 2))
let firstAvg = first.reduce((a, b) => a + b, 0) / first.length
let lastAvg = last.reduce((a, b) => a + b, 0) / last.length
if (lastAvg < firstAvg * 0.6) {
score++
anomalies.push(`回调收窄 早期${(firstAvg * 100).toFixed(2)}% 近期${(lastAvg * 100).toFixed(2)}%`)
}
}
// ── 异常4:横盘突破 ───────────────────────────────────────
let ma60 = closes.slice(-60).reduce((a, b) => a + b, 0) / 60
let ma120 = closes.length >= 120
? closes.slice(-120).reduce((a, b) => a + b, 0) / 120
: ma60
let currentPrice = closes[closes.length - 1]
if (Math.abs(ma60 - ma120) / ma120 < 0.02 && currentPrice > ma60 * 1.03) {
score++
anomalies.push(`横盘突破 MA60=${ma60.toFixed(3)} MA120=${ma120.toFixed(3)} 当前=${currentPrice.toFixed(3)}`)
}
// ── 异常5:成交量突增 ─────────────────────────────────────
let recentVol = volumes.slice(-5).reduce((a, b) => a + b, 0) / 5
let baseVol = volumes.slice(-65, -5).reduce((a, b) => a + b, 0) / 60
if (baseVol > 0 && recentVol > baseVol * 2.5) {
score++
anomalies.push(`成交量突增 近5根均量是基准${(recentVol / baseVol).toFixed(1)}倍`)
}
return { score, anomalies }
}
Cada anomalía detectada suma un punto, con un máximo de 5 puntos. Solo aquellas con una puntuación total de al menos 2 pasan a la siguiente etapa. Una señal individual puede ser ruido aleatorio; solo cuando se acumulan, indican cierta credibilidad en el comportamiento del capital: esta es la hipótesis central de toda la lógica de detección de velas.
Búsqueda de noticias: encontrar una explicación fundamental para las anomalías
Las señales de velas son evidencia de que «hay capital en movimiento», pero es necesario verificar por qué se mueve el capital y si el movimiento tiene fundamento. Este paso consiste en buscar noticias para cada objetivo con anomalías de velas, para ver si hay eventos correspondientes que lo respalden.
Aquí se utiliza la API de Brave Search, que ofrece 2000 consultas gratuitas al mes, suficientes para el ritmo principal de una ronda cada 10 minutos. Las palabras clave de búsqueda se extraen del símbolo, eliminando sufijos de dirección y separadores para reconstruir términos descriptivos legibles del evento.
javascript
const q = item.symbol
.replace("_USDC.No", "")
.replace("_USDC.Yes", "")
.replace(/-/g, "+")
const rawResponse = HttpQuery(
"https://api.search.brave.com/res/v1/web/search?q=" + q,
{ method: "GET", headers: { "X-Subscription-Token": CONFIG.BRAVE_API_KEY } }
)
// 遍历所有返回分区(网页、新闻等),统一提取结构化字段
Object.keys(data).forEach(key => {
const section = data[key]
if (section && section.results && Array.isArray(section.results)) {
section.results.forEach(r => {
news.push({ type: key, title: r.title, description: r.description, age: r.age })
})
}
})
Las noticias encontradas se empaquetan junto con los datos de las velas y pasan a la siguiente etapa de análisis de IA: ambas líneas se verifican simultáneamente, lo que es mucho más fiable que mirar solo un lado.
Análisis de IA con múltiples roles: cuatro perspectivas para evitar la autoconvicción
Una vez que los datos están listos, se ingresa al nodo de análisis de IA, donde el modelo elige según sus necesidades. En el prompt se definen cuatro roles independientes; esta es la decisión de diseño más importante de todo el sistema y merece una explicación detallada.
Si una IA ve simultáneamente las velas y las noticias, es fácil que se validen mutuamente, llegando a una conclusión que parece razonable pero que en realidad carece de verificación independiente: respaldar la señal de capital con noticias y las noticias con la señal de capital, para finalmente producir un resultado autorreforzado del tipo «creo que se puede comprar». El aislamiento de roles fuerza la independencia de las fuentes de información: cada rol solo ve sus propios datos, solo emite conclusiones desde su dimensión, y el rol de decisión final solo ve las conclusiones, no el proceso.
Rol 1: Analista de velas y flujo de capital. No ve noticias, solo analiza anomalías en precio y volumen para determinar si hay capital real comprando de forma sostenida. Emite una intensidad de señal de capital (fuerte/media/base).
Rol 2: Analista de opinión pública y noticias. No ve velas, solo evalúa el panorama informativo para determinar si hay eventos positivos que aún no han sido descontados por el mercado. Emite un nivel de soporte noticioso (fuerte/débil/ninguno).
Rol 3: Analista de valoración de precios. Combina las conclusiones de los dos roles anteriores, estima el rango de probabilidad real del evento y lo compara con el precio de mercado actual, dando una evaluación de infravalorado/razonable/sobrevalorado. Este rol incorpora una regla de ponderación según el vencimiento: si faltan más de 7 días, se estima con normalidad; si faltan 3 días o menos y el precio de mercado es superior a 0,15, se fuerza a reducir el rango de probabilidad y se prohíbe emitir «gravemente infravalorado». La razón es directa: cerca del vencimiento, los participantes del mercado tienen información en tiempo real más completa que los datos de entrenamiento de la IA, por lo que el juicio de la IA debe ceder ante el precio de mercado.
Rol 4: Analista de decisión final. Según una matriz de decisión, resume las conclusiones de los tres roles anteriores y emite la acción final. La lógica de la matriz es: la señal de capital es un requisito previo, las noticias son una verificación, y ambas determinan juntas el nivel de confianza; pero sin importar cuán alto sea el nivel de confianza, si la valoración del precio no alcanza «infravalorado», no se opera.
La verificación de noticias aquí no consiste en buscar información, sino en determinar si el comportamiento del capital ya tiene un respaldo fundamental. Cuando el capital interno está acumulando posiciones, la información no aparece en las noticias públicas, pero la señal de capital combinada con el soporte noticioso indica que la información está en una fase intermedia de difusión y el mercado aún tiene rezago en la fijación de precios; esa es precisamente la ventana que la estrategia busca capturar.
| Señal de capital \ Soporte noticioso | Verificación fuerte | Verificación débil | Sin verificación |
|---|---|---|---|
| Fuerte (score 4~5) | Comprar, confianza = alta | Comprar, confianza = media | No operar |
| Media (score 3) | Comprar, confianza = media | Observar | No operar |
| Base (score 2) | Observar | No operar | No operar |
El formato de salida de la IA es JSON estricto, que incluye las conclusiones de cada rol, el rango de probabilidad real, la valoración del precio, la decisión final, el nivel de confianza y una lista de riesgos, listo para ser consumido por el nodo de ejecución descendente.
Ejecución de la operación: solo comprar la mejor
Después de que la IA puntúa cada activo del lote, la capa de ejecución no coloca órdenes para todas las señales de compra; el sistema solo selecciona la mejor puntuación. El orden de clasificación es: nivel de confianza (alto > medio > bajo) → valoración del precio (gravemente infravalorado > infravalorado) → amplitud del rango de probabilidad real (cuanto más estrecho, más determinante).
javascript
const buySignals = signals.filter(s => s.signal === 'buy')
bestSignal = buySignals.sort((a, b) => {
const confDiff = (confidenceRank[b.confidence] || 0) - (confidenceRank[a.confidence] || 0)
if (confDiff !== 0) return confDiff
const assessDiff = (assessmentRank[b.priceAssessment] || 0) - (assessmentRank[a.priceAssessment] || 0)
if (assessDiff !== 0) return assessDiff
// Cuanto más estrecho el rango, más determinante; se prefiere el más estrecho
const aWidth = (a.trueProb.max || 0) - (a.trueProb.min || 0)
const bWidth = (b.trueProb.max || 0) - (b.trueProb.min || 0)
return aWidth - bWidth
})[0]
Una vez seleccionado el activo, se obtiene en tiempo real el precio Ask de la cartera de órdenes, se confirma que el saldo es suficiente y se envía una orden limitada. Tras enviar la orden, se consulta el estado, con un tiempo máximo de espera de 30 segundos; si se supera, se cancela la orden para evitar la acumulación de órdenes pendientes. Si el precio Ask actual multiplicado por la cantidad configurada es inferior al umbral mínimo de 1 USDC, el sistema redondea automáticamente hacia arriba usando ceil(1/askPrice) para alcanzar la cantidad mínima ejecutable.
Módulo de stop loss: trailing stop loss + red de seguridad absoluta
La línea secundaria se ejecuta cada 30 segundos. La lógica consta de dos pasos: primero procesar los reembolsos por vencimiento y luego verificar el trailing stop loss para las posiciones activas.
Polymarket tiene un mecanismo especial: cuando un contrato vence, los fondos no vuelven automáticamente a la cuenta; es necesario llamar a redeem de forma activa. La estrategia, al inicio de cada ronda de la línea secundaria, escanea todas las posiciones reembolsables y libera los fondos de forma masiva, evitando que el capital quede bloqueado durante mucho tiempo.
El núcleo del trailing stop loss es un diseño de doble línea: la línea de trailing stop loss (precio bid histórico máximo menos una caída fija LOSS_AMOUNT) y la línea de red de seguridad absoluta (precio de entrada × 50%). El precio de stop real se toma como el mayor de los dos.
javascript
function calcStopPrice(entryPrice, maxPrice) {
const trailingStopPrice = maxPrice - CONFIG.LOSS_AMOUNT
const absoluteStopPrice = entryPrice * CONFIG.FALLBACK_STOP_RATIO // fijo 0.50
const usingFallback = trailingStopPrice < absoluteStopPrice
const effectiveStopPrice = usingFallback ? absoluteStopPrice : trailingStopPrice
return { effectiveStopPrice, trailingStopPrice, absoluteStopPrice, usingFallback }
}
Este diseño de doble línea corresponde a dos escenarios típicos de tenencia: en fase de ganancias, la línea de trailing stop loss sube con el precio, asegurando las ganancias flotantes; cuando se entra en pérdidas, la línea de trailing stop loss puede caer a valores negativos o cercanos a cero, momento en el que la línea de red de seguridad absoluta (precio de entrada × 50%) toma el control, evitando que la posición caiga hasta cero antes de salir. Ambas líneas cumplen funciones distintas y son indispensables.
Al activarse el stop loss, se ejecuta una venta a mercado, se borra el caché del precio máximo histórico de ese activo y se espera la próxima señal de apertura. El panel de control muestra en tiempo real el espacio restante de cada posición respecto a su línea de stop loss, con colores que indican el nivel de alerta para facilitar la revisión manual.
Decisiones clave de diseño
¿Por qué usar múltiples roles en lugar de un solo prompt unificado? Esta pregunta ya se mencionó parcialmente en el módulo de análisis, pero vale la pena aclararla más. El problema de un solo prompt no es solo la «autoconvicción»; hay un riesgo aún más sutil: cuando la IA procesa simultáneamente datos de velas y texto de noticias, tiende a explicar los primeros con el segundo, «racionalizando» las anomalías de las velas como una consecuencia inevitable de las noticias, en lugar de evaluar ambas como señales independientes. El aislamiento de roles fuerza la introducción de dos cadenas de información independientes; al final, si ambas cadenas apuntan en la misma dirección, la credibilidad es real.
¿Por qué solo comprar la mejor opción en cada ronda en lugar de diversificar? La diversificación tiene un fundamento teórico sólido en las finanzas tradicionales, pero en los mercados de predicción la lógica no es completamente aplicable. Los resultados de los activos en los mercados de predicción son binarios y el riesgo de caer a cero es real. Si se mantienen tres activos con confianza media y dos de ellos se vuelven cero mientras uno sube, es posible que no se recupere la inversión total. La estrategia actual elige concentrar la apuesta en la precisión, en lugar de diluir la calidad con cantidad. Esta compensación puede no ser óptima, pero es lógicamente coherente.
¿Por qué la regla de ponderación por vencimiento debe ser una restricción estricta? Cerca del vencimiento, el precio de mercado refleja las expectativas en tiempo real de los participantes, y una gran proporción de ellos tiene información más actualizada que los datos de entrenamiento de la IA. Si en ese momento la IA sigue emitiendo «precio gravemente infravalorado, se debe comprar», es muy probable que su información ya esté desactualizada. Convertir esta regla en una restricción en lugar de una recomendación se debe a que no es realista que la IA reconozca por sí misma que «mi información ya no es suficientemente nueva»; se necesita una intervención externa forzada.
Observaciones en vivo
Según los registros de ejecución real, el funnel ratio de la estrategia es bastante pronunciado. En una ejecución con 141 activos que pasaron el filtro preliminar, tras la detección de anomalías en velas K solo quedaron 3, y finalmente solo 1 cumplió simultáneamente la señal de capital, respaldo de noticias y evaluación de precio para desencadenar la orden; los otros dos se omitieron por tener una evaluación de precio "razonable" y una calificación integral insuficiente. Esto indica que la estrategia es bastante conservadora: prefiere no tener posiciones antes que bajar los estándares. Durante períodos de mercado estables y sin eventos noticiosos evidentes, el sistema puede no generar ninguna señal de compra durante todo el día. Es una elección de diseño, no un error. También se han encontrado casos de anomalías en velas K que luego resultaron ser falsas rupturas: los fondos entraron brevemente y luego se retiraron, con el stop loss móvil interviniendo para la salida. El análisis de noticias también tiene ruido; la cobertura de eventos relevantes puede ser tardía o sesgada, y la IA por sí sola no puede identificarlos completamente.
El panel muestra en tiempo real el patrimonio de la cuenta, el estado de las posiciones (Bid/Ask actual, precio máximo, distancia de retroceso desde el nivel de stop loss, modo de stop loss) y los detalles de las decisiones de la IA, facilitando la revisión manual.
Conclusión
Honestamente, este sistema es más un marco conceptual ejecutable que una máquina de hacer dinero lista para usar. La lógica central —rastreo del comportamiento del capital, verificación dual de noticias, juicio de IA con múltiples roles— tiene cierta razonabilidad teórica, pero en el mercado real la calidad de las señales es desigual, la IA también se equivoca, y el riesgo de convergencia de precios cerca del vencimiento siempre está presente.
Hay muchos aspectos que se pueden mejorar: los activos de trading se pueden enfocar más en áreas familiares, los prompts de IA se pueden rediseñar según el propio estilo de trading, los pesos y umbrales de los cinco tipos de anomalías en velas K se pueden ajustar, y el coeficiente de stop loss también merece iteración según el rendimiento real de las posiciones. Todo el código es de código abierto, siéntase libre de modificarlo.
Aviso de riesgo
Los activos del mercado de predicción tienen resultados binarios, y las posiciones conllevan riesgo de pérdida total. Las señales de anomalías en velas K y las conclusiones del análisis de IA no constituyen asesoramiento de inversión, y el rendimiento histórico de las señales no garantiza resultados futuros. La estrategia no ha sido validada en operaciones reales a largo plazo, y los parámetros tienen un impacto significativo en los resultados. Antes de utilizar esta estrategia para operaciones reales, comprenda completamente las reglas de la plataforma Polymarket, los mecanismos de vencimiento de contratos y los riesgos de liquidez, y evalúe por sí mismo su capacidad para asumir la pérdida del capital.
Código fuente de la estrategia: Estrategia de trading inteligente con múltiples roles para Polymarket
- 1




