apinn.io
Todos os artigos
Valorização8 min de leitura

A mesma aposta, cinco EVs diferentes: escolher um modelo de devig

Numa longshot a 6.00, mudar de modelo de devig altera o teu EV em mais de um ponto inteiro. Aqui está qual usar, mercado a mercado.

Existe um bug silencioso em muitos sistemas de deteção de valor: o EV que mostras depende de uma escolha que ninguém registou por escrito. Essa escolha é o modelo usado para remover a margem da casa de apostas. Muda-o e a mesma aposta passa de +1.2% para +2.6% de EV — sem uma única odd se mexer.

Isto não é um detalhe de implementação. É o pressuposto central de todo o teu stack de pricing: como é que a casa distribui a sua comissão pelos resultados?

O ponto de partida: a soma ultrapassa 100%

Num moneyline a 1.55 / 2.55, o inverso de cada odd dá 64.5% e 39.2%. Total: 103.7%. Esses 3.7 pontos são a margem. Todos os modelos tentam voltar aos 100%; diferem apenas na forma como retiram o excedente.

odds = [1.55, 2.55]
raw = [1 / o for o in odds]
print(f"overround: {sum(raw) - 1:.2%}")   # 3.70 %

Additive: tirar a mesma quantidade a todos

O modelo mais ingénuo: subtrai uma parte igual do excedente a cada probabilidade. Fácil de explicar, mas trata um favorito a 90% e uma longshot a 5% como se carregassem a mesma carga de margem — o que não é verdade em nenhuma casa de apostas.

def additive(odds):
    raw = [1 / o for o in odds]
    excess = (sum(raw) - 1) / len(raw)
    return [p - excess for p in raw]

Num mercado muito desequilibrado, o additive pode devolver uma probabilidade negativa para a odd mais alta. Se o teu código não tiver proteção para isso, vai gerar odds justas absurdas em vez de um erro visível.

Multiplicative: proporcional

Divide cada probabilidade pela soma. Rápido, sem parâmetros, o padrão na maioria das ferramentas. Num mercado a duas vias equilibrado é difícil de bater. O seu pressuposto — margem distribuída como uma percentagem igual — está, no entanto, errado assim que o mercado é assimétrico.

def multiplicative(odds):
    raw = [1 / o for o in odds]
    total = sum(raw)
    return [p / total for p in raw]

# 1.55 / 2.55 → probabilidades 62.22 % / 37.78 %

Power: curvar a distribuição

Encontra um expoente k tal que a soma das probabilidades elevadas a k seja exatamente 1. Em vez de deslocar as probabilidades, distorce a curva: efeito pequeno nos favoritos, efeito grande na cauda. Esse comportamento ajusta-se melhor a mercados com muitos resultados.

from scipy.optimize import brentq

def power(odds):
    raw = [1 / o for o in odds]
    k = brentq(lambda k: sum(p ** k for p in raw) - 1, 0.5, 1.5)
    return [p ** k for p in raw]

Shin: a margem como prémio de seguro

O Shin acrescenta um pressuposto económico: a casa define a sua margem para se proteger de uma proporção z de apostadores mais bem informados do que ela. Essa proporção é inferida a partir das odds e depois removida — o que atribui mais margem às longshots, exatamente como as casas fazem na prática.

def shin(odds, iterations=100):
    raw = [1 / o for o in odds]
    total = sum(raw)
    z = 0.0
    for _ in range(iterations):
        probs = [
            (((z ** 2 + 4 * (1 - z) * p ** 2 / total) ** 0.5) - z) / (2 * (1 - z))
            for p in raw
        ]
        s = sum(probs)
        z += (s - 1) / 2
    return [p / s for p in probs]

Odds ratio: um único parâmetro de distorção

O modelo odds ratio procura um único fator aplicado ao rácio de odds de cada resultado (a "odd" em vez da probabilidade). Fica frequentemente perto do Shin, com uma intuição mais simples: a casa não distorce probabilidades, distorce rácios.

Onde os modelos realmente divergem

Num mercado a duas vias equilibrado, todos ficam muito próximos: a dispersão entre os cinco modelos mantém-se abaixo de 0.3 pontos de probabilidade — dentro do ruído da tua própria estimativa. É longe da paridade que as decisões mudam:

  • Favorito pesado (1.10 contra 9.00): o multiplicative subestima o favorito e sobrestima a longshot; a diferença para o Shin ultrapassa um ponto na longshot.
  • 1X2 com um empate mal cotado: power e Shin concordam, o multiplicative fabrica valor falso no empate.
  • Mercados com muitos resultados (outrights, resultado exato, marcadores): o multiplicative torna-se genuinamente mau nas odds altas. Power ou Shin, nunca ele sozinho.
  • Handicaps asiáticos e totais: duas vias muito líquidas, margem reduzida — a escolha do modelo quase não importa, usa o mais rápido.
Um modelo de devig não é uma configuração cosmética: é o teu pressuposto sobre como a casa se comporta. É melhor escolhê-lo de propósito.

A regra mais importante do que o modelo

Seja qual for a tua escolha, mantém-na. A armadilha mais cara não é escolher o modelo "errado", é mudar entre backtest e produção: o teu EV histórico torna-se incomparável com o teu EV em tempo real, e vais concluir que o teu edge desapareceu quando só a régua de medição mudou.

  1. Fixa um modelo por família de mercado e regista-o algures.
  2. Guarda o modelo usado junto de cada EV que registas — caso contrário o teu histórico deixa de ser interpretável.
  3. Antes de ajustares o teu limiar de EV, confirma que não foi o teu devig que mudou.

Fazê-lo do lado do servidor

Na apinn, os cinco modelos estão implementados do lado do servidor e são aplicados no momento do tick: cada linha chega com o seu preço de mercado e o seu preço justo, segundo o modelo que pedires. Escolhes o teu pressuposto por pedido — ou de uma vez por todas nas preferências da tua conta — e os teus backtests usam exatamente a mesma matemática que o teu bot.

curl -H "X-API-Key: $APINN_KEY" \
  "https://api.apinn.io/api/odds?event_id=1610000123&model=shin"

# odds1/odds2   = preços de mercado
# todds1/todds2 = preços justos
# model = power (predefinido) | multiplicative | additive | shin | odds_ratio

O teu EV reduz-se então a uma divisão — e o debate sobre o devig fica resolvido de uma vez, com calma, em vez de a cada tick.

Estas contas, com dados reais

Odds da Pinnacle em tempo real com true odds incluídas, mais histórico de abertura e fecho — acesso self-serve, chave API em minutos.