Type/to search
2
Follow
490
Followers
Entre arbitragem e previsão: um experimento ingênuo de estratégia de convergência de caminhos da Copa do Mundo
Discussions
Created 2026-06-18 09:09:14  Updated 2026-06-22 15:37:13
 0
 210

img

Assim que a Copa do Mundo começou, o mercado nos deu uma pequena lição educativa: equipas fortes não são imunes a surpresas, apenas as suas formas de surpreender costumam ser mais criativas do que imaginamos.

Por exemplo, Espanha 0:0 Cabo Verde. Antes do jogo, olhando apenas para força, ranking e profundidade do plantel, a maioria das pessoas teria um instinto simples: a Espanha devia ganhar, certo? Mas o futebol é mais interessante, e também o que mais atormenta os traders, exatamente aqui. Pensas que estás a comprar “vitória da equipa forte”, mas na realidade estás a comprar um drama contínuo de 90 minutos. Nos primeiros 15 minutos sem golo, as odds mexem-se; meia hora ainda 0:0, o mercado começa a franzir a testa; aos 70 minutos sem novidades, a vitória da equipa forte, que parecia tão estável, de repente já não é tão estável.

img

É aqui que surge um clássico dilema: arbitragem é boa, previsão é difícil.

A verdadeira arbitragem, em teoria, deve ser livre de risco. Por exemplo, encontrar um conjunto de contratos mutuamente exclusivos e exaustivos: independentemente do que acontecer, a combinação paga e o custo de compra é inferior ao valor do pagamento. Parece ótimo, como a sesta de um trader. Mas o problema é que essas oportunidades são muito raras, desaparecem rapidamente e, muitas vezes, não têm capacidade suficiente.

A previsão é outra história. Podes avaliar que a equipa forte provavelmente vence, podes analisar o plantel, forma, calendário, lesões, podes também olhar para as probabilidades implícitas das odds, mas o jogo não vai colaborar só porque analisámos com atenção. No futebol, especialmente, um cartão vermelho precoce, uma bola no poste, um VAR absurdo, pode transformar uma lógica bonita num silêncio constrangedor de três segundos na análise pós-jogo.

img

Então, a questão é: se a arbitragem pura é demasiado escassa e a previsão pura é demasiado aleatória, podemos situar-nos entre os dois? O mercado já nos dá algumas probabilidades prévias, como o preço da vitória da equipa forte, o preço do 0:0, o preço do 0:1. Estes preços não surgem do nada; refletem a precificação coletiva do mercado para diferentes caminhos. Podemos então usar essas probabilidades prévias, juntamente com um modelo matemático próprio, para construir uma combinação imperfeita mas mais protetora, e abrir uma janela de “convergência de caminhos”?

Este é o ponto de partida desta ideia.

Não é arbitragem livre de risco tradicional, nem pura previsão de cabeça. É mais um meio-termo: primeiro, reconhece-se que a probabilidade principal que o mercado dá tem valor de referência; depois, usam-se caminhos de baixa probabilidade para proteger a parte mais frágil do julgamento principal, enquanto um modelo simples verifica se o preço ainda é aceitável.

Suponhamos um jogo em que o Brasil é claramente superior ao Haiti. O mercado dá o preço de vitória do Brasil a 0,89, indicando que a vitória brasileira é um caminho principal forte. Mas não compramos apenas a vitória do Brasil; em vez disso, observamos dois caminhos de proteção: 0:0 e 0:1. Porque, para um julgamento de vitória de uma equipa forte, o cenário inicial mais doloroso não é todos os resultados, mas sim o jogo que não desbloqueia ou a equipa mais fraca que marca um golo de surpresa.

Assim, a combinação inicial torna-se:

text
Brasil vence Sim 0:0 Sim 0:1 Sim

Suponhamos os preços:

text
Brasil vence = 0.89 0:0 = 0.016 0:1 = 0.011

Custo total das três pernas:

text
C = 0.89 + 0.016 + 0.011 = 0.917

Este conjunto não é um evento completo. Não cobre 1:1, 0:2, 2:2, nem todos os cenários estranhos. Portanto, se for mantido até ao fim, claro que pode perder, e pode perder de forma direta. Mas tem uma caraterística importante: junta as três probabilidades já dadas pelo mercado, formando um cesto de caminhos em torno da vitória principal.

Se o Brasil vencer, a combinação paga 1. Se acabar 0:0 ou 0:1, também paga 1. Ou seja, compramos:

img

text
Brasil vence ∪ 0:0 ∪ 0:1

Se um destes caminhos ocorrer, o pagamento no vencimento é 1. O custo é 0,917, com um espaço de 0,083 dentro dos caminhos cobertos. Mas o verdadeiro ponto crucial não é o fim do jogo, é a meio.

Se o Brasil marcar cedo, fazendo 1:0, então as duas pernas de proteção (0:0 e 0:1) basicamente vão a zero, mas o preço da vitória do Brasil sobe. Desde que o preço de venda do Brasil a esse ponto ultrapasse o custo total inicial, mais uma pequena margem de lucro, podemos fechar a vitória principal e encerrar a combinação antecipadamente.

A fórmula é simples:

text
Condição de take profit = bid do Brasil vence >= custo total inicial C + lucro alvo

Por exemplo, com lucro alvo de 0,02:

text
Preço de gatilho = 0.917 + 0.02 = 0.937

Se após o 1:0 o bid do Brasil vence chegar a 0,95, então:

text
Lucro bloqueado = 0.95 - 0.917 = 0.033

Aqui, não estamos a ganhar dinheiro com o resultado final, mas sim a aproveitar a entrada do jogo num ramo favorável, vendendo a combinação antecipadamente. Este processo é um pouco como o mercado abrir uma pequena janela para ti; não fiques a fazer poesia à janela, passa primeiro.

Mas ainda há um problema: as três pernas parecem baratas, mas valerá sempre a pena comprá-las? Nem sempre. O preço de mercado é apenas a primeira camada de informação. Precisamos também da nossa própria régua de referência, mesmo que simples.

Aqui, usei o modelo mais básico de Poisson para golos.

O resultado do futebol pode ser visto grosseiramente como processos aleatórios de cada equipa a marcar golos em 90 minutos. Supondo que o número esperado de golos da equipa da casa em 90 minutos é λ_casa, e o da equipa visitante é λ_visitante, então a probabilidade de a equipa da casa marcar i golos e a visitante marcar j golos pode ser escrita como:

text
P(i, j) = Pois(i; λ_casa) × Pois(j; λ_visitante)

onde:

text
Pois(k; λ) = e^(-λ) × λ^k / k!

img

Claro que é muito simplista. O futebol não são duas máquinas de sorteio independentes; as táticas mudam após golos, cartões vermelhos, estados de espírito. Mas a vantagem é ser simples e transparente, pelo menos para não tomarmos decisões apenas com base no palpite.

Antes do jogo, o modelo de Poisson pode dar-nos uma referência inicial. Podemos definir manualmente λ_casa e λ_visitante, ou fazer o programa inferi-los a partir dos mercados de resultado exato (placares). Por exemplo, os mercados de 0:0, 0:1, 1:0, 1:1, 2:0, 2:1, 3:0; cada um equivale a um ponto de probabilidade dado pelo mercado. O programa procura um par λ_casa e λ_visitante que faça as probabilidades do modelo de Poisson para esses resultados aproximarem-se o máximo possível desses preços de mercado.

Por outras palavras, o mercado diz: “Acho que estes placares valem aproximadamente este dinheiro.” O modelo de Poisson murmura ao lado: “Então vou tentar ajustar, para ver que intensidade de golo está implícita nesses preços.”

Na estratégia, pode-se configurar:

python
CALIBRATE_LAMBDA_FROM_MARKET = True MODEL_SCORE_SAMPLES = "0-0,0-1,1-0,1-1,2-0,2-1,3-0"

Estes resultados são usados apenas para modelagem, não para ordens de compra. As pernas realmente negociadas continuam a ser:

text
Vitória da equipa alvo 0:0 0:1

O código usa uma busca em grade para ajustar λ. Não é complexo, mas é intuitivo:

python
def fit_lambdas_from_score_markets(quotes, model_score_legs, event_state=None): samples = [] live_score = event_state.get("score_tuple") if event_state else None minute = event_state.get("elapsed") if event_state else None is_live = bool(live_score and minute not in [None, ""]) for leg in model_score_legs: q = quotes.get(leg["name"]) p_market = quote_probability(q) if p_market is None: continue target_h, target_a = parse_score_text(leg["score"]) if is_live: current_h, current_a = live_score if current_h > target_h or current_a > target_a: continue samples.append((target_h - current_h, target_a - current_a, p_market, leg["score"])) else: samples.append((target_h, target_a, p_market, leg["score"])) if len(samples) < 2: return None best = None for ih in range(5, 501, 5): lh = ih / 100.0 for ia in range(5, 501, 5): la = ia / 100.0 err = 0.0 for add_h, add_a, p_market, _score in samples: p_model = poisson_pmf(add_h, lh) * poisson_pmf(add_a, la) err += (p_model - p_market) ** 2 if best is None or err < best["err"]: best = {"lambda_home": lh, "lambda_away": la, "err": err, "samples": samples} if is_live: ratio = max(0.01, max(0.0, 90.0 - float(minute)) / 90.0) best["lambda_home"] = best["lambda_home"] / ratio best["lambda_away"] = best["lambda_away"] / ratio best["source"] = "live_score_markets" else: best["source"] = "pre_match_score_markets" return best

Antes do jogo, este λ é apenas uma calibração inicial. Porque o jogo ainda não começou, não há caminho em tempo real para atualizar, o placar padrão ainda é 0:0, e o tempo restante é de 90 minutos. Nesta fase, usamos isso para filtrar a entrada:

text
Probabilidade de cobertura do modelo = P(vitória do time alvo) + P(0:0) + P(0:1)

Então exige-se:

text
Probabilidade de cobertura do modelo - custo de mercado >= margem de segurança

Somente quando o preço de mercado for suficientemente barato e o modelo considerar que este cesto tem alguma vantagem, é permitido abrir posição.

O que realmente interessa é depois do início do jogo.

Assim que o jogo começa, o modelo de Poisson deixa de ser estático. Suponha que o jogo esteja no minuto 30, o placar atual ainda seja 0:0, então o tempo restante é de apenas 60 minutos, e a intensidade futura de gols deve ser reduzida proporcionalmente ao tempo restante:

text
λ_home_remaining = λ_home × (90 - t) / 90 λ_away_remaining = λ_away × (90 - t) / 90

Se o placar atual já é 1:0, então 0:0 e 0:1 não podem mais ocorrer. Neste momento, o modelo deve partir do placar atual e calcular apenas quantos gols ainda serão marcados no tempo restante. Placares finais como 2:0, 2:1, 3:0, 1:1, que ainda são possíveis, são elegíveis para participar da nova estimativa.

Esta é a chave da atualização em tempo real de Poisson: não reduzir mecanicamente o λ pré-jogo a cada minuto, mas combinar o placar atual, o tempo restante e os mercados de placar exato ainda possíveis para reestimar como o jogo pode se desenrolar daqui para frente.

A estratégia final se torna uma decisão de três camadas.

A primeira camada é o custo de mercado:

text
win_ask + 0:0_ask + 0:1_ask <= custo máximo permitido

A segunda camada é o filtro de Poisson:

text
Probabilidade de cobertura do modelo - custo de mercado >= margem de segurança

A terceira camada é a convergência de caminho:

text
Valor atual do bid do portfólio >= custo inicial + lucro alvo

Somente quando a primeira e a segunda camadas são satisfeitas simultaneamente, considera-se a entrada. Após a entrada, não depende mais do modelo para fantasiar o resultado final, mas usa o bid real do mercado para decidir se pode fechar a posição. O modelo é responsável por melhorar a qualidade da abertura de posição, e o mercado é responsável por decidir se pode realizar o lucro.

A busca por contratos também é feita da forma mais simples possível. Os slugs do mercado da Copa do Mundo da Polymarket são muito regulares. Por exemplo, o event slug de uma partida é:

python
EVENT_SLUG = "fifwc-aut-jor-2026-06-17"

Se protegermos a vitória da Jordânia, o sufixo do contrato de vitória correspondente é:

python
WIN_SUFFIX = "jor"

Então os três contratos necessários para a negociação podem ser montados diretamente:

python
def yes_symbol(slug): return slug + "_USDC.Yes" def build_legs(): legs = [ { "name": "win", "slug": EVENT_SLUG + "-" + WIN_SUFFIX, "symbol": yes_symbol(EVENT_SLUG + "-" + WIN_SUFFIX), "kind": "win", } ] for score in parse_scores(PROTECT_SCORES): legs.append( { "name": "score_" + score.replace("-", "_"), "slug": EVENT_SLUG + "-exact-score-" + score, "symbol": yes_symbol(EVENT_SLUG + "-exact-score-" + score), "kind": "score", "score": score, } ) return legs

Aqui, tente não usar o nome do time para pesquisa difusa. Por exemplo, pesquisar Jordan pode facilmente encontrar Michael B. Jordan, Jordan Pickford, Jordan Spieth, e antes que a estratégia de futebol comece, entretenimento, goleiro inglês e golfe já estão na mesa. Usar o event slug para montar contratos é muito mais limpo.

Durante o jogo, também é necessário o placar em tempo real. A primeira versão pode obter diretamente do evento Polymarket Gamma:

python
def get_event_state(): data = get_json(GAMMA_BASE + "/events", slug=EVENT_SLUG) e = data[0] return { "title": e.get("title"), "score": e.get("score"), "score_tuple": parse_score(e.get("score")), "elapsed": e.get("elapsed"), "period": e.get("period"), "live": bool(e.get("live")), "ended": bool(e.get("ended")), "start_time": e.get("startTime"), }

Valor vendável atual da cesta usando o bid real do livro de ofertas:

python
def basket_bid_value(legs, quotes): total = 0.0 for leg in legs: pos = positions.get(leg["name"], {}) amount = float(pos.get("amount", 0)) if amount <= 0: continue q = quotes.get(leg["name"]) if not q or q["bid"] is None: continue total += amount * q["bid"] return total

Verificação de take profit:

python
cost = current_position_cost() value = basket_bid_value(legs, quotes) target = cost + TARGET_PROFIT * SHARES if value >= target: close_all()

Esta é a versão mínima. Ela não finge ter resolvido a previsão de futebol, nem declara que pode fazer arbitragem estável. Apenas tenta estudar a zona cinzenta entre "arbitragem" e "previsão".

A beleza da arbitragem está na certeza, mas a certeza é escassa. A tentação da previsão está no grande espaço de possibilidades, mas a aleatoriedade também é grande. O que essa estratégia faz é pegar os preços previstos fornecidos pelo mercado como matéria-prima, usar uma aposta principal de alta probabilidade, mais duas rotas de proteção de baixa probabilidade, e depois usar um modelo de Poisson para fazer uma filtragem grossa, tentando construir uma janela que possa convergir antecipadamente durante a partida.

Os riscos devem ser claros. Esta combinação não é um evento completo, não é arbitragem sem risco. É adequada para jogos com diferença de força grande o suficiente, com rota principal clara e preços das rotas de proteção suficientemente baixos. Se o jogo é equilibrado ou as pernas de proteção já estão caras, forçar a execução não faz sentido. Mais problemático é que ela não cobre todos os caminhos adversos, como 1:1, 0:2, 2:2, que podem causar perdas significativas no portfólio. Portanto, é necessário definir limites de posição, perda máxima e regras de stop loss, sem tratar isso como arbitragem só porque "parece arbitragem".

O modelo de Poisson também não é mágica. É apenas uma base matemática muito simples, que nos ajuda a ir de "acho que esse preço está bom" para "pelo menos verifiquei esse preço com um modelo transparente". Ele pode errar, o mercado pode errar, e nós mesmos erramos ainda mais. A parte mais honesta do trading é provavelmente admitir que todos podem errar, e então tentar garantir que o erro não vire a mesa de uma só vez.

Esta tentativa é muito superficial. Ela se parece mais com fazer uma pergunta: quando as oportunidades de arbitragem pura estão cada vez mais raras e a previsão pura é muito difícil, podemos usar as probabilidades já fornecidas pelo mercado para construir transações mais estruturadas? Não é uma fantasia de eliminar o risco, mas sim desmembrá-lo e ver claramente de quais caminhos ele vem.

Talvez não seja a resposta, mas é um buraco que vale a pena continuar cavando. A previsão diz qual estrada principal pode ser mais larga, e a ideia de arbitragem nos lembra de não olhar apenas para a direção, mas também para a estrutura do portfólio. Entre os dois, talvez haja muito espaço para explorar.

Código-fonte da estratégia: Estratégia de Convergência de Caminhos de Futebol do Polymarket

Comment
All comments (0)
No data
No data
  • 1
Forums
PINE Language
Get the app
iPhone Download
© 2015 - ∞ INVENTOR PTE LTD (SG)