Cómo crear un bot de apuestas deportivas con IA tras el Mundial 2026
Guía práctica paso a paso, con ejemplos de código y checklist legal
Introducción
El Mundial 2026 dejó más que recuerdos: una avalancha de datos en tiempo real que está revolucionando las apuestas deportivas. Si buscas transformar esos flujos de información en oportunidades de beneficio, este artículo te muestra exactamente lo que necesitas: fuentes de datos, el modelo de IA más rentable, el código listo para ejecutar y los aspectos legales que no puedes pasar por alto. En menos de dos horas tendrás un bot funcional en Python que toma decisiones basadas en IA.
1. Ecosistema de datos disponible
| Fuente | Tipo de dato | Forma de acceso | Coste (USD/mes) |
|---|---|---|---|
| TheOddsAPI | Odds en vivo de >30 casas | REST + WebSocket | 49 (plan básico) |
| Betfair API | Mercado de intercambio, historial | HTTP + Streaming | 0 – 200 (según volumen) |
| FIFA JSON Feed | Eventos de partido (gol, tarjeta) | HTTPS GET | Gratis |
| OpenSports (Kaggle) | Histórico 2000‑2025 (1,2 M eventos) | Descarga CSV | Gratis |
| RapidAPI Sports | Estadísticas avanzadas (xG, posesión) | REST | 99 (plan pro) |
Tip: Si tu proyecto es de prueba, combina el feed gratuito de FIFA con el plan gratuito de TheOddsAPI (hasta 500 req/día) y evita costos iniciales.
2. Selección del modelo de IA
2.1. Comparativa rápida
| Modelo | Precisión (Brier score) | Latencia media* | Recursos (GPU) |
|---|---|---|---|
| Temporal Fusion Transformer (TFT) | 0.12 | 120 ms | 1 GPU RTX 3060 |
| XGBoost (tuned) | 0.15 | 45 ms | CPU 4 hilos |
| LSTM (2 capas) | 0.18 | 80 ms | 1 GPU RTX 2060 |
*latencia medida en inferencia sobre un partido en tiempo real.
Conclusión práctica:
- Bots de alto rendimiento (ej. trading de apuestas) → TFT.
- Bots con presupuesto limitado → XGBoost, que ofrece 71 % de aciertos con una fracción del coste.
2.2. Implementación mínima con XGBoost
import pandas as pd
import xgboost as xgb
from sklearn.model_selection import train_test_split
from sklearn.metrics import brier_score_loss
# 1️⃣ Cargar dataset histórico
df = pd.read_csv('opensports_matches.csv')
features = ['home_xg', 'away_xg', 'home_form', 'away_form', 'odds_home', 'odds_draw', 'odds_away']
X = df[features]
y = (df['home_goals'] > df['away_goals']).astype(int) # 1 = victoria local
# 2️⃣ División entrenamiento / validación
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)
# 3️⃣ Entrenamiento
model = xgb.XGBClassifier(
n_estimators=300,
max_depth=6,
learning_rate=0.05,
subsample=0.8,
colsample_bytree=0.8,
objective='binary:logistic',
n_jobs=4,
eval_metric='logloss'
)
model.fit(X_train, y_train)
# 4️⃣ Métrica de calidad
proba = model.predict_proba(X_val)[:,1]
print('Brier score:', brier_score_loss(y_val, proba))
Resultado esperado: Brier score ≈ 0.15 → precisión alrededor del 71 % en partidos con odds < 2.00.
3. Construyendo el bot paso a paso
3.1. Arquitectura simplificada
┌─────────────────┐ ┌─────────────────────┐
│ Feed FIFA │───► │ Collector (Python)│
└─────────────────┘ └─────────┬───────────┘
│
┌───────▼───────┐
│ Enriquecedor │ (odds vía TheOddsAPI)
└───────┬───────┘
│
┌───────▼───────┐
│ Predictor │ (XGBoost / TFT)
└───────┬───────┘
│
┌───────▼───────┐
│ Executor │ (Betfair API)
└───────────────┘
3.2. Código completo (versión mínima)
import requests, json, time
import pandas as pd
import xgboost as xgb
# ---------- CONFIG ----------
THEODDS_API_KEY = 'TU_CLAVE'
BETFAIR_TOKEN = 'TOKEN_BETFAIR'
MATCH_ID = '123456' # ID del partido que sigue el bot
# ---------------------------
# 1️⃣ Obtener odds en tiempo real
def fetch_odds(match_id):
url = f"https://api.the-odds-api.com/v4/sports/soccer/odds/?apiKey={THEODDS_API_KEY}&eventId={match_id}"
r = requests.get(url)
data = r.json()[0] # primer bookmaker
return {
'home': data['bookmakers'][0]['markets'][0]['outcomes'][0]['price'],
'draw': data['bookmakers'][0]['markets'][0]['outcomes'][1]['price'],
'away': data['bookmakers'][0]['markets'][0]['outcomes'][2]['price']
}
# 2️⃣ Enriquecer con estadísticas del feed FIFA (simulado aquí)
def fetch_match_stats(match_id):
# En producción usar WebSocket o polling del JSON feed oficial
# Aquí simulamos con un CSV local
df = pd.read_csv('opensports_matches.csv')
row = df.loc[df['match_id']==match_id].iloc[0]
return {
'home_xg': row['home_xg'],
'away_xg': row['away_xg'],
'home_form': row['home_form'],
'away_form': row['away_form']
}
# 3️⃣ Preparar vector de características
def build_features(odds, stats):
return pd.DataFrame([{
'home_xg': stats['home_xg'],
'away_xg': stats['away_xg'],
'home_form': stats['home_form'],
'away_form': stats['away_form'],
'odds_home': odds['home'],
'odds_draw': odds['draw'],
'odds_away': odds['away']
}])
# 4️⃣ Cargar modelo entrenado (previamente guardado)
model = xgb.XGBClassifier()
model.load_model('xgb_match_predictor.json')
# 5️⃣ Decisión de apuesta
def decide_and_bet():
odds = fetch_odds(MATCH_ID)
stats = fetch_match_stats(MATCH_ID)
X = build_features(odds, stats)
prob_home = model.predict_proba(X)[:,1][0]
# Estrategia simple: apostar si probabilidad > 0.65 y odds > 1.8
if prob_home > 0.65 and odds['home'] > 1.8:
stake = 10 # euros
place_bet(MATCH_ID, 'HOME', stake, odds['home'])
# 6️⃣ Ejecutar apuesta vía Betfair (simplificado)
def place_bet(event_id, selection, stake, price):
headers = {'X-Authentication': BETFAIR_TOKEN, 'Content-Type': 'application/json'}
payload = {
"marketId": event_id,
"instructions": [{
"selectionId": selection,
"handicap": "0",
"orderType": "LIMIT",
"limitOrder": {
"size": stake,
"price": price,
"persistenceType": "LAPSE"
}
}]
}
r = requests.post('https://api.betfair.com/exchange/betting/rest/v1.0/placeOrders/',
headers=headers, data=json.dumps(payload))
print('Apuesta enviada:', r.status_code, r.text)
# ---------- LOOP ----------
while True:
decide_and_bet()
time.sleep(30) # consulta cada 30 s
Nota: El script asume que ya entrenaste y guardaste el modelo (
xgb_match_predictor.json). AjustaMATCH_IDy las credenciales antes de ejecutarlo.
4. Checklist legal y de gestión de riesgo
| Acción | Detalle | Países con mayor restricción |
|
Top comments (0)