apinn.io
Todos los artículos
Valoración8 min de lectura

Misma apuesta, cinco EV distintos: cómo elegir un modelo de devig

En un forastero a 6.00, cambiar de modelo de devig mueve tu EV más de un punto entero. Aquí está cuál usar, mercado por mercado.

Un bug silencioso se esconde en muchos sistemas de detección de valor: el EV que muestras depende de una decisión que nadie dejó por escrito. Esa decisión es el modelo usado para quitar el margen del bookmaker. Cámbialo, y la misma apuesta pasa de +1.2% a +2.6% de EV — sin que se mueva un solo precio.

Esto no es un detalle de implementación. Es el supuesto central de todo tu stack de pricing: ¿cómo reparte la casa su comisión entre los resultados?

El punto de partida: la suma supera el 100%

En un moneyline a 1.55 / 2.55, el inverso de cada cuota da 64.5% y 39.2%. Total: 103.7%. Esos 3.7 puntos son el margen. Cada modelo busca volver al 100%; solo difieren en cómo retiran ese excedente.

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

Aditivo: quitar la misma cantidad a todos

El modelo más ingenuo: resta una parte igual del excedente a cada probabilidad. Fácil de explicar, pero trata a un favorito del 90% y a un forastero del 5% como si cargaran el mismo peso de margen — algo que no ocurre en ningún bookmaker.

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

En un mercado muy desequilibrado, el aditivo puede devolver una probabilidad negativa para la cuota más larga. Si tu código no tiene una protección para eso, generará fair odds absurdas en lugar de un error visible.

Multiplicativo: proporcional

Divide cada probabilidad entre la suma. Rápido, sin parámetros, el default en la mayoría de las herramientas. En un mercado dos vías ajustado es difícil de superar. Su supuesto — el margen repartido como un porcentaje igual — es, aun así, incorrecto en cuanto el mercado es asimé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: doblar la curva

Encuentra un exponente k tal que la suma de las probabilidades elevadas a k sea exactamente 1. En lugar de desplazar probabilidades, deformas la curva: efecto pequeño en los favoritos, efecto grande en la cola. Ese comportamiento se ajusta mejor a mercados con muchos 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: el margen como prima de seguro

Shin añade un supuesto económico: la casa fija su margen para cubrirse frente a una proporción z de apostadores mejor informados que ella. Esa proporción se infiere a partir de las cuotas y luego se elimina — lo que carga más margen sobre los forasteros, tal como hacen las casas en la práctica.

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: un solo parámetro de distorsión

El modelo odds ratio busca un único factor aplicado al ratio de cada resultado (la "razón" en vez de la probabilidad). A menudo se acerca mucho a Shin, con una intuición más simple: la casa no distorsiona las probabilidades, distorsiona los ratios.

Dónde divergen de verdad los modelos

En un mercado dos vías equilibrado, todos quedan muy cerca: la dispersión entre los cinco modelos se mantiene por debajo de 0.3 puntos de probabilidad — dentro del ruido de tu propia estimación. Es lejos de la paridad donde las decisiones cambian:

  • Favorito muy marcado (1.10 contra 9.00): el multiplicativo subestima al favorito y sobreestima al forastero; la brecha con Shin supera un punto en el forastero.
  • 1X2 con un empate mal fijado: power y Shin coinciden, el multiplicativo fabrica valor falso en el empate.
  • Mercados con muchos resultados (outrights, resultado exacto, goleadores): el multiplicativo se vuelve realmente malo en cuotas largas. Power o Shin, nunca él solo.
  • Hándicaps asiáticos y totales: dos vías muy líquidas, margen fino — la elección del modelo apenas importa, usa el más rápido.
Un modelo de devig no es un ajuste cosmético: es tu supuesto sobre cómo se comporta el bookmaker. Mejor elegirlo a propósito.

La regla que importa más que el modelo

Elijas el que elijas, mantenlo. La trampa más costosa no es escoger el modelo "equivocado", es cambiar entre backtest y producción: tu EV histórico se vuelve incomparable con tu EV en vivo, y concluirás que tu edge colapsó cuando lo único que se movió fue la vara de medir.

  1. Fija un modelo por familia de mercado, y déjalo escrito en algún lugar.
  2. Guarda el modelo usado junto a cada EV que registres — de lo contrario tu historial deja de ser interpretable.
  3. Antes de ajustar tu umbral de EV, verifica que no haya sido tu devig lo que cambió.

Hacerlo del lado del servidor

En apinn los cinco modelos están implementados del lado del servidor y se aplican en el momento del tick: cada línea llega con su precio de mercado y su precio justo, bajo el modelo que pidas. Eliges tu supuesto por request — o de una vez por todas en las preferencias de tu cuenta — y tus backtests usan exactamente las mismas matemáticas que tu bot.

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

# odds1/odds2   = precios de mercado
# todds1/todds2 = precios justos
# model = power (default) | multiplicative | additive | shin | odds_ratio

Tu EV se reduce entonces a una división — y el debate sobre el devig se resuelve una sola vez, con calma, en lugar de en cada tick.

Estas cuentas, con datos reales

Cuotas de Pinnacle en tiempo real con true odds incluidas, más histórico de apertura y cierre — acceso self-serve, clave API en minutos.