Todos os posts
GuiasBots de tradingAPI da PolymarketPython

Como criar um bot de trading para a Polymarket

A maioria dos tutoriais de bots para a Polymarket usa SDKs que não existem mais. Este é o caminho atual de ponta a ponta — o que instalar em 2026, como a autenticação realmente funciona, onde estão as lacunas de dados e os modos de falha que matam bots na primeira semana.

14 min de leitura

A maioria dos tutoriais de bots para a Polymarket está desatualizada

A Polymarket migrou para SDKs unificados — polymarket-client para Python e @polymarket/client para TypeScript. Eles substituem py-clob-client, @polymarket/clob-client-v2, @polymarket/builder-relayer-client e @polymarket/builder-signing-sdk. Se um guia manda você rodar pip install py-clob-client, ou se o seu assistente de IA gera esse import, ele está trabalhando com material desatualizado. Tudo abaixo usa os pacotes atuais.

Um bot para a Polymarket tem seis partes: descobrir mercados, ler preços, decidir, enviar ordens, gerenciar posições e continuar vivo. As duas primeiras são fáceis, a quarta é chata e a sexta é onde a maioria dos bots realmente morre. Este guia percorre o caminho todo com código verificado e é honesto sobre as partes que são de fato difíceis.

Passo 0: decida o que seu bot vai operar

Vale fazer isso antes de escrever uma linha, porque determina tudo o que vem depois. Os mercados da Polymarket se dividem em duas famílias que não têm quase nada em comum:

Mercados de eventosMercados cripto Up/Down
ExemplosEleições, esportes, premiaçõesbtc-updown-5m, eth-updown-15m
DuraçãoSemanas a meses5 minutos a 24 horas
O que move o preçoNotícias, informação, sentimentoMicroestrutura e fluxo de ordens
A vantagem vem deEstar mais bem informadoSer mais rápido ou precificar melhor
Operações por diaAlgumasCentenas
Sensibilidade à latênciaBaixaAlta

Se você está automatizando, quase certamente se interessa pela segunda família — alta frequência, contínua e mecânica o bastante para ser codificada. Ela é tratada em profundidade em Mercados Up/Down explicados.

Passo 1: instale o SDK atual

Os dois SDKs oferecem uma única interface de cliente para todas as APIs da Polymarket, modelos tipados, paginação consistente e assinatura embutida — um bom volume de trabalho chato que você não quer reimplementar.

pip install polymarket-client
# or: uv add polymarket-client / poetry add polymarket-client

Há quatro clientes Python, e escolher o certo importa mais do que parece:

ClienteDados públicosTradingTempo real
AsyncPublicClientSimNãoSim
AsyncSecureClientSimSimSim
PublicClientSimNãoNão
SecureClientSimSimNão
As assinaturas em tempo real são só assíncronas — os clientes síncronos não implementam subscribe(). Bots precisam das variantes assíncronas; as síncronas são para scripts e notebooks.

Comece pelo cliente público

Você pode construir e testar a descoberta, a leitura de preços, a geração de sinais e todo o seu pipeline de dados com o AsyncPublicClient — sem chaves, sem carteira, sem risco. Só troque para o AsyncSecureClient quando estiver pronto para enviar uma ordem. A maioria dos bugs aparece bem antes disso.

Passo 2: encontre mercados

A descoberta pública de mercados não exige credenciais. O paginador do SDK é consistente em todos os métodos de listagem, então este padrão vale para todos.

import asyncio
from polymarket import AsyncPublicClient


async def main() -> None:
    async with AsyncPublicClient() as client:
        pages = client.list_markets(closed=False, page_size=50)

        # Iterate items directly when page boundaries do not matter.
        async for market in pages.iter_items():
            if "updown" in (market.slug or ""):
                print(market.slug, market.condition_id)


asyncio.run(main())

Duas coisas para guardar aqui. Primeiro, page.next_cursor é um cursor opaco — guarde-o literalmente se quiser retomar uma varredura depois, e não tente fazer parsing nem montar um. Segundo, /markets tem o limite de requisições mais apertado da plataforma inteira, 300 req / 10s, então guarde os metadados dos mercados em cache em vez de listá-los de novo em um loop quente. Os números completos estão na referência de limites de requisições.

Passo 3: autentique-se

Para operar é preciso uma carteira. O SDK Python constrói o signer a partir de uma chave privada local:

import os
from polymarket import AsyncSecureClient

client = await AsyncSecureClient.create(
    private_key=os.environ["POLYMARKET_PRIVATE_KEY"],
    wallet=os.environ["POLYMARKET_WALLET_ADDRESS"],
)

Por baixo, a Polymarket usa duas camadas de autenticação: L1 é uma assinatura de carteira EIP-712 que prova que você controla o endereço e permite criar ou derivar credenciais de API; L2 assina cada requisição privada com essas credenciais usando HMAC-SHA256. O SDK cuida das duas, e esse é o principal motivo para usá-lo.

As duas falhas de autenticação que você vai encontrar

Credenciais incompletas — a L2 precisa da chave, do secret e da passphrase. Duas das três produzem uma requisição bem formada com uma assinatura impossível de verificar. Desvio de relógio — a assinatura inclui um timestamp, então um contêiner com o relógio alguns segundos errado é rejeitado. As duas aparecem como o mesmo e pouco útil Unauthorized/Invalid api key. A explicação completa está na referência de erros.

Cuidado com a chave

Essa chave privada pode movimentar fundos. Guarde-a em variáveis de ambiente ou em um gerenciador de segredos — nunca no código-fonte, nunca em uma imagem de contêiner, nunca no repositório que você está prestes a fazer push. Use uma carteira dedicada, abastecida só com o que o bot tem permissão para perder, para que um bug fique limitado pelo saldo e não pelo seu julgamento às 3 da manhã.

Passo 4: obtenha preços em tempo real

O erro de arquitetura mais comum em um primeiro bot é fazer polling de /book com um timer. Isso queima seu orçamento de limite de requisições, adiciona latência e escala mal. Em vez disso, assine — o SDK junta vários feeds em um único stream de eventos.

from polymarket.streams import MarketSpec

async with await client.subscribe([MarketSpec(token_ids=[token_id])]) as stream:
    async for event in stream:
        # MarketBookEvent | MarketPriceChangeEvent | MarketLastTradePriceEvent
        # | MarketTickSizeChangeEvent | MarketBestBidAskEvent
        # | NewMarketEvent | MarketResolvedEvent
        handle(event)

Se você se conectar ao WebSocket cru em vez de usar o SDK, precisa enviar um PING a cada 10 segundos, ou a conexão cai, e precisa de custom_feature_enabled: true para receber os eventos best_bid_ask, new_market e market_resolved. Isso e os padrões de reconexão estão no guia de WebSocket. À parte, os preços de referência foram para o PolyBolt em 15 de setembro de 2026 — se o seu bot faz streaming de spot, veja o guia de migração.

Passo 5: envie uma ordem

Uma ordem a mercado é a coisa mais simples que funciona, e amount é expresso no valor em pUSD que você está disposto a gastar, e não em cotas:

market = await client.get_market(slug="<market-slug>")
token_id = market.outcomes.yes.token_id
assert token_id is not None

response = await client.place_market_order(
    token_id=token_id,
    side="BUY",
    amount="10",          # spend up to 10 pUSD
)

if not response.ok:
    raise RuntimeError(response.message)

# Settlement is on-chain and asynchronous — this waits for it.
hashes = await client.wait_for_order_fill_settlement(response)

Para ordens limitadas no livro, duas regras vão morder você antes de qualquer outra coisa. Os preços precisam estar na grade de ticks do mercado — chame GET /tick-size para cada mercado em vez de supor 0.01, porque o tick size varia e pode ficar menor à medida que o mercado amadurece. E ordens abaixo do tamanho mínimo do mercado são rejeitadas de cara. As duas voltam como 400 com mensagens específicas, listadas na referência de erros.

Um 200 em um lote não significa sucesso

Quando você envia várias ordens, as falhas de cada ordem voltam dentro do array da resposta 200, como campos errorMsg individuais. Percorra o array e verifique cada entrada. Bots que verificam só o status HTTP acreditam em silêncio que têm posições que não têm — uma classe de bug realmente perigosa.

Passo 6: saiba se a estratégia funciona

Tudo acima é encanamento, e o encanamento é a metade fácil. A pergunta difícil é se a sua estratégia dá dinheiro — e é aqui que criar bots para a Polymarket se afasta bastante de criar bots para cripto spot.

Não existe testnet. Nem sandbox, nem API de demonstração, nem endpoint de paper trading. Essas palavras não aparecem em nenhum lugar da documentação da Polymarket. Sua primeira ordem real é dinheiro real contra contrapartes reais. Veja a Polymarket tem uma testnet? para as quatro alternativas.

E não existe livro de ofertas histórico. Depois que um mercado é resolvido, o livro dele retorna 404. Ele guarda uma série de preços de cerca de um ponto por minuto, e só se você pedir com um início e um fim explícitos:

TOK=<token_id_of_a_resolved_market>
START=<epoch seconds the window opened>
END=$((START + 300))

curl -s "https://clob.polymarket.com/book?token_id=$TOK"
# {"error":"No orderbook exists for the requested token id"}   HTTP 404

curl -s "https://clob.polymarket.com/prices-history?market=$TOK&startTs=$START&endTs=$END&fidelity=1"
# about 6 points for a 5-minute market; interval=max returns [] for older ones

Então você não consegue fazer backtest a partir da Polymarket. Você precisa de snapshots pontuais que alguém gravou enquanto os mercados estavam ativos. É isso que a PolyTest oferece para os mercados cripto Up/Down — mais de 240M de snapshots, 8 níveis de profundidade do livro por lado, timestamps abaixo de um segundo, mercados resolvidos mantidos:

import os, requests

BASE = "https://api.polytest.io/api/v1"
H = {"X-API-Key": os.environ["POLYTEST_KEY"]}

markets = requests.get(f"{BASE}/markets",
                       params={"coin": "btc", "market_type": "5m", "limit": 50},
                       headers=H).json()["markets"]

snaps = requests.get(f"{BASE}/markets/{markets[0]['id']}/snapshots",
                     params={"include_orderbook": "true"},
                     headers=H).json()["snapshots"]


def simulate_fill(levels, qty):
    """Walk the ladder. Mid-price is not a price you can trade at."""
    filled = cost = 0.0
    for lvl in levels:
        take = min(lvl["size"], qty - filled)
        cost += take * lvl["price"]
        filled += take
        if filled >= qty:
            break
    return cost / filled if filled >= qty else None


print(simulate_fill(snaps[0]["orderbook"]["asks"], 500))

O erro que torna um backtest inútil

Se você faz backtest contra o preço médio, está testando uma identidade aritmética, não uma estratégia. Os spreads Up/Down costumam ficar entre 2 e 5 centavos em um contrato que liquida a $1 — frequentemente mais do que a vantagem alegada. Percorra o livro e use a execução que você realmente teria conseguido. Essa única mudança mata a maioria das estratégias, que é exatamente o que você quer que ela faça, de forma barata, antes de colocar dinheiro nelas.

Passo 7: sobreviva ao contato com a produção

Um bot que opera corretamente por uma hora e depois trava é pior do que nenhum bot. Estes são os modos de falha que realmente acontecem, mais ou menos na ordem de frequência:

FalhaO que você vêComo tratar
Limitado por taxaLatência subindo, não errosA Cloudflare atrasa em vez de rejeitar — observe o p99, não a taxa de erros
Reinício do motor de casamento425 Too EarlyTente de novo com backoff; não gere alerta para casos isolados
Exchange pausada503Pare de abrir posições. Cancele se for permitido
Modo somente cancelamento503 em novas ordensO caminho de cancelamento precisa funcionar independentemente do caminho de entrada
Modo somente post-only503 + retry_after_secondsEspere exatamente esse tempo e tente de novo
Divergência de signer400 de erro no signer da ordemCredenciais antigas de outra carteira — derive de novo
Queda do WebSocketSilêncioNenhum dado não é o mesmo que nenhuma mudança — acompanhe a idade da última mensagem
Desvio de relógio401 em um bot que funcionava ontemRode NTP; este é o que mais desperdiça tempo

O silêncio é o estado perigoso

Um WebSocket que caiu não lança exceção — ele só para de entregar mensagens. Um bot com uma posição aberta e sem receber atualizações vai acreditar tranquilamente que o mercado está congelado no último preço que viu. Acompanhe a idade da última mensagem e trate a defasagem como condição de erro, não como calmaria.

  • Teste o caminho de cancelamento antes do caminho de entrada. Não conseguir sair é muito pior do que não conseguir entrar.
  • Limite a exposição no código, não na sua cabeça. Um limite rígido de posição transforma um bug de lógica em uma perda pequena, e não ilimitada.
  • Construa um botão de emergência e teste-o de verdade. Um botão de emergência não testado é só um comentário.
  • Adicione jitter ao trabalho agendado. Workers que acordam exatamente no mesmo segundo criam um pico sincronizado muito acima da sua taxa média.
  • Registre em log todas as requisições e respostas na primeira semana. Você vai precisar delas, e não dá para reconstruí-las depois.
  • Gere alertas por categoria, não por mensagem. A Polymarket inclui IDs de ordens e preços nas strings de erro, então alertas por string crua são puro ruído.

Uma ordem de construção realista

A sequência que desperdiça menos tempo e dinheiro:

  1. Integração somente leitura, cliente público, sem chaves. Prove a descoberta, o parsing, a paginação e o backoff. Um dia, grátis.
  2. Faça backtest da estratégia em livros históricos, com simulação honesta de execuções. A maioria das ideias morre aqui. É esse o objetivo.
  3. Paper trading ao vivo por pelo menos uma semana — registre em log as ordens pretendidas em vez de enviá-las. Prova a disponibilidade, as reconexões e o timing.
  4. Entre ao vivo com o tamanho mínimo, com um limite rígido de exposição e um botão de emergência testado.
  5. Só aumente o tamanho quando os números ao vivo baterem com os do paper trading. Se divergirem, seu modelo de execução estava errado — volte ao passo 2.

Os passos 1, 3 e 4 você constrói em poucos dias. O passo 2 precisa de dados que a Polymarket não guarda, e também é o passo que poupa dinheiro com mais confiabilidade. Comece um teste grátis na PolyTest — o suficiente para descobrir se a sua ideia sobrevive ao spread.

Perguntas frequentes

Como crio um bot de trading para a Polymarket?
Instale o SDK unificado atual — polymarket-client para Python ou @polymarket/client para TypeScript. Use o AsyncPublicClient para descobrir mercados e ler preços sem credenciais e depois o AsyncSecureClient com uma chave privada para operar. Assine o canal market do WebSocket em vez de fazer polling de preços, envie ordens com place_market_order e trate as respostas 425, 429 e 503 com backoff. Antes de entrar ao vivo, faça backtest com snapshots históricos do livro de ofertas e simulação realista de execuções, já que a Polymarket não tem testnet e não guarda histórico do livro de ofertas.
Qual SDK devo usar para um bot da Polymarket em 2026?
Use os SDKs unificados: polymarket-client para Python ou @polymarket/client para TypeScript. Eles substituem os pacotes antigos py-clob-client, @polymarket/clob-client-v2, @polymarket/builder-relayer-client e @polymarket/builder-signing-sdk. Um SDK unificado em Rust está em desenvolvimento. A maioria dos tutoriais e do código gerado por IA ainda faz referência aos pacotes descontinuados, então confira os imports antes de confiar em um trecho de código.
Posso fazer paper trading na Polymarket antes de arriscar dinheiro real?
Não pela Polymarket — não existe testnet, sandbox nem API de demonstração. Você mesmo pode construir uma camada de paper trading rodando o loop da sua estratégia ao vivo contra os dados de mercado de produção e registrando em log as ordens pretendidas, com o estado do livro naquele instante, em vez de enviá-las. Isso prova que seu bot é operacionalmente sólido, mas supõe as execuções, então não vai ensinar nada sobre posição na fila ou impacto no mercado.
Como faço backtest de um bot de trading para a Polymarket?
Você precisa de snapshots históricos do livro de ofertas de terceiros, porque a API da Polymarket retorna 404 para o livro de um mercado resolvido e guarda só cerca de um ponto por minuto de histórico de preços. Puxe snapshots pontuais com profundidade completa, reproduza-os em ordem cronológica sem olhar adiante e simule as execuções percorrendo os níveis do livro em vez de supor o preço médio. Spreads Up/Down de 2-5 centavos em um contrato de $1 costumam ser maiores do que a vantagem alegada, então backtests com preço médio enganam.
Por que meu bot da Polymarket recebe Unauthorized/Invalid api key?
Na maioria das vezes, por um de dois motivos. Ou o seu conjunto de credenciais está incompleto — a autenticação L2 precisa da chave de API, do secret e da passphrase juntos —, ou o relógio do seu sistema está desviado, já que a assinatura da requisição inclui um timestamp e alguns segundos de desvio a invalidam. Menos comum: você derivou as credenciais para uma carteira diferente daquela com que está operando.
Preciso de WebSocket para um bot da Polymarket ou posso fazer polling?
Use o WebSocket. Fazer polling de /book com um timer queima o orçamento de limite de requisições, adiciona latência e escala mal. Assine o canal market do CLOB para atualizações públicas do livro e de preços, e o canal user para atualizações das suas próprias ordens e negociações. Se você se conectar ao WebSocket cru em vez de usar um SDK, envie um PING a cada 10 segundos para manter a conexão viva.

Tenha os dados históricos que a Polymarket não guarda

A PolyTest registra os mercados cripto Up/Down da Polymarket enquanto estão ativos — mais de 240M de snapshots com 8 níveis de profundidade do livro de ofertas, timestamps abaixo de um segundo e mercados resolvidos preservados. Comece com um teste grátis de 3 dias.

Continue lendo