Polymarket Bot Tutorial · Capítulo 18 de 32
Bots de previsão de disputa da UMA na Polymarket: detecte propostas do Optimistic Oracle, preveja a probabilidade de disputa, explore a assimetria de preço pré e pós-disputa e evite espirais de morte em mercados disputados.
O que este capítulo cobre
O Optimistic Oracle (OO) da UMA resolve os mercados da Polymarket, e as disputas criam anomalias de preço antes e depois de acontecerem. Padrões negociáveis existem em ambos os lados de uma disputa, mas a estratégia é operacionalmente complexa e já queimou mais bots do que alimentou. Este capítulo é o playbook honesto.
- Como o UMA Optimistic Oracle funciona
- Detectando uma proposal on-chain
- Preditores de disputa (volume, ambiguidade, histórico)
- Assimetria de preço pré-disputa
- Setups de trade pós-disputa
- Quando NÃO negociar mercados disputados
- Código: assinar eventos proposed/disputed da UMA
Como o UMA Optimistic Oracle funciona
O Optimistic Oracle (OO) da UMA é a camada de resolução de disputas da Polymarket. Toda resolução de mercado passa pelo OO; a maioria não é contestada e é liquidada automaticamente. As contestadas - disputas - disparam um período de votação de 24 a 72 horas durante o qual os detentores do token da UMA decidem o resultado.
O ciclo de vida: o resolver da Polymarket propõe um preço (0 = NO venceu, 1 = YES venceu). Após uma janela de contestação de 2 horas, se ninguém disputar, o preço é finalizado e o contrato CTF distribui os pagamentos. Se alguém disputar, o mercado entra em uma janela de votação; os holders de UMA votam, e a maioria vence.
Para um bot, os eventos relevantes são ProposePrice (proposta registrada, janela de contestação aberta) e DisputePrice (disputa registrada, período de votação iniciado). Assine esses eventos para acompanhar o estado de resolução do mercado em tempo real.
Detectando uma proposal on-chain
O contrato OO da UMA na Polygon emite um evento ProposePrice com os parâmetros (requester, identifier, timestamp, ancillaryData, proposer, proposedPrice). Filtre pelo endereço conhecido de requester da Polymarket para limitar às proposals relevantes.
POLY_REQUESTER = "0x..." # Polymarket Adjudicator
filt = oo_contract.events.ProposePrice.create_filter(
fromBlock="latest",
argument_filters={"requester": POLY_REQUESTER}
)
for event in filt.get_new_entries():
market_id = decode_ancillary(event.args.ancillaryData)
proposed = "YES" if event.args.proposedPrice == 1e18 else "NO"
print(f"PROPOSE: market {market_id} → {proposed}")
O campo ancillaryData é JSON codificado em hex que descreve a pergunta do mercado. Decodificá-lo fornece o identificador do mercado, que você pode cruzar com suas posições abertas.
Preditores de disputa (volume, ambiguidade, histórico)
Três sinais pré-disputa se correlacionam com disputas reais posteriores.
- Volume total: mercados com > US$ 1 milhão em volume ao longo da vida são disputados a uma taxa 4x maior do que mercados pequenos. Mais capital em jogo = mais incentivo para contestar.
- Formulação ambígua: qualquer mercado com "ou similar", "oficialmente confirmado" ou condições compostas (data E resultado específico) tem taxas elevadas de disputa.
- Disputas anteriores no mesmo evento: se uma proposal anterior já foi disputada e reapresentada, a segunda proposal é disputada a uma taxa 2 a 3x maior que o normal.
Um bot pode calcular um score de "probabilidade de disputa" com base nesses fatores e evitar abrir posições em mercados acima de um limiar perto da resolução.
Assimetria de preço pré-disputa
Nas horas anteriores a uma disputa provável, o preço de mercado frequentemente mostra movimento assimétrico: o lado que o proposer nomeou como YES deriva para baixo (porque os traders temem que uma disputa reverta o resultado), enquanto o outro lado deriva para cima.
Se você tiver uma visão direcional sobre como a disputa vai se resolver, essa é uma janela negociável. O risco: se a disputa não acontecer, a assimetria se inverte quando a janela de contestação fecha sem incidentes e os preços retornam bruscamente para a direção proposta.
Sendo honesto: a maioria dos trades de assimetria pré-disputa perde dinheiro, porque a maioria das contestações se resolve a favor da proposta original. A estratégia só funciona quando você tem informação específica sobre por que essa disputa provavelmente será mantida.
Setups de trade pós-disputa
Depois que uma disputa é registrada, o mercado negocia por 24 a 72 horas em "limbo" - sabendo-se que está disputado, com o resultado a ser votado. Existem dois setups.
Convergência para o consenso da UMA: se o desfecho da disputa for sinalizado cedo (por exemplo, um votante proeminente da UMA toma publicamente um lado), o preço se move em direção a esse resultado. Um bot que monitora sinais do Discord / Twitter da UMA + price action pode capturar isso 30 a 60% das vezes.
Volatility farming: períodos de limbo têm spreads amplos. Um market maker paciente pode ganhar o spread entre vários traders que entram e saem durante a janela de votação. O risco de inventário é alto; dimensione a posição de acordo.
Ambos exigem conforto com a possibilidade real de a resolução ir contra sua posição. Trate o inventário durante a disputa como, no máximo, metade do tamanho normal.
Quando NÃO negociar mercados disputados
Três situações em que o trade de disputa está errado por padrão.
- Você não tem uma visão específica da UMA. Se sua única vantagem é "a proposta original me parece correta", você não tem vantagem sobre o proposer original - e quem abriu a disputa pensa o oposto. O resultado da votação é uma moeda que você não consegue prever.
- A disputa é sobre uma formulação ambígua. Os votantes da UMA geralmente seguem a leitura estrita da pergunta. Se o mercado dizia "até 31 de janeiro" e o evento aconteceu em 1º de fevereiro, a UMA vai resolver NO independentemente da intuição da base de traders.
- Você já carrega inventário antes da disputa. Aumentar uma posição existente para "baixar o preço médio" durante o limbo é o padrão clássico de destruição de capital. Mantenha ou saia, nunca aumente.
Código: assinar eventos proposed/disputed da UMA
Referência: assinatura WebSocket para eventos da UMA OO, filtrados pelo requester da Polymarket.
from web3 import Web3
w3 = Web3(Web3.WebsocketProvider(POLYGON_WSS))
oo = w3.eth.contract(address=UMA_OO_ADDR, abi=UMA_OO_ABI)
POLY = "0x...".lower()
dispute_filter = oo.events.DisputePrice.create_filter(fromBlock="latest")
propose_filter = oo.events.ProposePrice.create_filter(fromBlock="latest")
while True:
for event in dispute_filter.get_new_entries():
if event.args.requester.lower() == POLY:
on_dispute(event)
for event in propose_filter.get_new_entries():
if event.args.requester.lower() == POLY:
on_propose(event)
time.sleep(2)
def on_dispute(event):
market_q = decode_ancillary_to_question(event.args.ancillaryData)
send_telegram(f"DISPUTE: {market_q}")
# If we hold a position in this market, alert + consider exit
if market_q in our_positions:
flag_position_for_review(market_q)
O padrão: assinar, decodificar, alertar. Agir sobre disputas de forma algorítmica é de alto risco; normalmente o trabalho do bot é apenas levar o evento a um revisor humano.





