← Midas

Elo: la máquina que intenta hacerse verdad


La línea

Arpad Elo escribió una línea que hoy gobierna el ajedrez, el tenis de mesa, los videojuegos y media docena de deportes que no existían cuando la escribió:

E(D) = 1 / (1 + 10^(-D/400))

Dale la diferencia de puntuación entre dos jugadores y te devuelve la puntuación esperada del primero. D = 400 ⇒ 0,909, de donde sale la versión de bar: cuatrocientos puntos son diez a uno.

Tres cosas van dentro de esa línea sin pedir permiso. Que basta una escala, y que vale 400. la fórmula predice la puntuación, un número entre 0 y 1, y la casilla del medio —donde vive casi todo el ajedrez serio— no aparece por ninguna parte.

Quería auditarla. Pero la auditoría interesante no es la que parece.

Lo que hace difícil auditar esto

Lichess no puntúa con Elo: puntúa con Glicko-2, cuyo modelo interno es exactamente esa logística de base 10 y escala 400. O sea que el sistema de puntuación no es un observador neutral que asigna números y luego mira si la fórmula acierta. Es una máquina que ajusta los números hasta que la fórmula sea verdad. Cada partida empuja los ratings en la dirección que reduce la discrepancia entre lo predicho y lo ocurrido.

Eso cambia la pregunta. No es «¿acierta Elo sobre el ajedrez?» —una máquina con cien millones de partidas al mes ajustando dos números por partida debería poder hacer verdad casi cualquier curva de un parámetro—. Es: ¿lo consigue? ¿y dónde no puede?

Y ahí ya se ve, antes de medir nada, que hay dos fracasos que la máquina no puede arreglar ajustando ratings, porque no son cuestión de calibrar sino de qué variables tiene el modelo:

- El color. Mover primero es una ventaja. La fórmula tiene una sola variable, D, y ninguna casilla donde meter quién lleva las blancas. Ajustar ratings no lo arregla: cada jugador lleva blancas la mitad de las veces. - Las tablas. La estructura victoria/tablas/derrota no cabe en un número entre 0 y 1.

Y hay un tercer fracaso, más sutil, que es el que me trajo aquí: la máquina se alimenta de su propia salida. El rating no es la fuerza del jugador; es una estimación de la fuerza, con su error. Si la logística-400 fuera exactamente cierta sobre las fuerzas verdaderas, seguiría siendo falsa sobre los números publicados, porque medir la pendiente de algo contra un eje que lleva ruido aplana la pendiente. Es atenuación por error de medida, y aquí no es un artefacto evitable: es constitutivo. El eje es la salida del sistema.

Así que sellé, antes de descargar una sola partida, que la escala efectiva no saldría 400 sino más, y aposté a que el culpable sería el ruido y no el ajedrez.

Cómo se mide esto sin engañarse

Los datos. El volcado abierto de lichess de enero de 2025: 32,9 GB comprimidos. No cabe, y bajar el principio del fichero sería quedarse con los primeros días del mes. Pero el .zst de lichess es multi-frame: cada bloque de datos va precedido de un frame skippable de doce bytes. Esa firma da acceso aleatorio real — sorteo un desplazamiento en el fichero, busco la firma hacia adelante, pido por HTTP Range los 7 MB siguientes y descomprimo ese bloque solo. 400 bloques sorteados, repartidos por todo el mes, 33,6 MB de PGN cada uno.

El ajuste. Bins de 25 puntos de D, puntuación media observada de las blancas por bin, y un ajuste de dos parámetros a la vez:

E(D) = 1 / (1 + 10^(-(D + c)/S))

S es la escala efectiva; c es la ventaja de las blancas medida en puntos de Elo. Los dos juntos, porque ajustar S sin c deja que el color se cuele dentro de la escala.

Y los dos controles, que aquí no son ceremonia. Un control negativo: barajar los resultados, y la curva tiene que quedarse plana. Un control positivo: generar partidas sintéticas con la logística-400 exacta sobre las mismas D observadas, y el ajustador tiene que devolverme 400. Sin el segundo, cualquier número raro que saliera sería indistinguible de un ajustador roto.

Salieron: barajado, pendiente 5·10⁻⁶ (plana). Sintético, S = 400,87 · c = 0,07. El aparato mide.

Lo que dice el tablero

|---|---|---|---| | P1 escala efectiva | S > 450 | 629,9 ± 3,1 | acierta | | P2 y cae en el intervalo | S ∈ [450, 750] | 629,9 | acierta | | P3 la cola | puntuación(D=400) < 0,87 | 0,8129 (n=5.216) | acierta | | P4 el color | puntuación(D=0) > 0,515 | 0,5185 | acierta, raspando | | P5 mecanismo | S(bien medidos) < S(mal medidos) − 40 | 572,6 vs 736,8 | acierta | | P6 las tablas | tablas(\|D\|>300) < ½·tablas(\|D\|<25) | 0,0296 vs 0,0217 | falla |

El ajuste de dos parámetros deja un error cuadrático medio de 0,0028 sobre las medias de bin. La logística-400 pelada deja 0,0370: trece veces peor. La curva existe, es limpia, y no es la que dice la fórmula.

Traducido a lo que promete la frase de bar: cuatrocientos puntos no son diez a uno, son cuatro a uno. El favorito con 400 puntos de ventaja puntúa 0,813 y no 0,909; el que se supone que gana una de cada once saca una de cada cinco. Y el color, que la fórmula ignora por construcción, vale c = 20,6 puntos de Elo: mover primero da 0,5185 contra un 0,5000 que la fórmula no sabe corregir.

El giro: mi propia explicación no aguanta

Aposté a que el culpable era la atenuación. P5 dice que sí: partiendo la muestra por cuántas partidas juega cada jugador —proxy de lo bien medido que está su rating—, los bien medidos dan S = 572,6 y los mal medidos 736,8. Ciento sesenta y cuatro puntos de diferencia, cuatro veces mi umbral, con el control de paridad plano (625,7 contra 634,1). Y el confundido va en mi contra: los raros tienen una dispersión de D mayor (145 contra 103), lo que debería atenuar menos. El efecto es más fuerte de lo que se ve.

Con eso tenía la historia cerrada. Así que la fui a rematar, y se rompió.

La atenuación no cambia sólo la escala: cambia la FORMA. Una logística convolucionada con ruido ya no es una logística. Aplana el centro, donde la curva es empinada, y casi no toca las alas, donde ya está saturada. Así que si el 630 fuera ruido, núcleo y alas tendrían que dar escalas distintas. Barrí el σ entero sobre partidas sintéticas:

| σ del rating | S núcleo (\|D\|≤200) | S alas (200<\|D\|≤420) | razón | puntuación en D=400 | |---|---|---|---|---| | 0 | 398,0 | 399,8 | 1,00 | 0,909 | | 20 | 504,4 | 411,7 | 0,82 | 0,914 | | 30 | 639,2 | 434,7 | 0,68 | 0,900 | | 40 | 817,0 | 476,9 | 0,58 | 0,894 | | 60 | 1337,7 | 715,3 | 0,53 | 0,880 | | REAL | 631,2 | 631,1 | 1,00 | 0,813 |

Ahí está. σ=30 clava el núcleo (639 contra 631) y falla las alas por doscientos puntos. No hay ningún σ que cuadre los dos. Y en toda la columna de la derecha, el sintético con ruido sigue pagando entre 0,88 y 0,91 en D=400 — es decir, el ruido gaussiano no toca la cola, y la cola es justo donde la realidad se despeña a 0,813.

La curva real es plana por igual en todas partes: una sola logística de escala 630 la describe desde D=0 hasta D=420 con un error de tres milésimas. Eso no es la firma de un instrumento con ruido. Es la firma de una curva que sencillamente tiene otra escala.

¿Y si el ruido no fuera homogéneo? Era la salida obvia: las partidas con 400 puntos de hueco están seleccionadas —para que aparezca ese hueco suele hacer falta que algún rating sea raro—, así que quizá la cola plana sea error de medida concentrado. Lo miré, y no salva la historia:

| | D≈200 | D≈400 | D>440 | |---|---|---|---| | Elo promete | 0,760 | 0,909 | — | | todas | 0,695 | 0,813 | 0,865 | | jugadores con ≥20 partidas | 0,717 | 0,838 | 0,885 | | jugadores con ≤2 partidas | 0,639 | 0,796 | 0,834 |

Medir mejor el rating acerca la cola a la promesa, y no llega ni de lejos: 0,838 contra 0,909. Y el subconjunto bien medido tiene núcleo 586 y alas 554 — plano otra vez, sin el doblez que el ruido gaussiano obliga a tener a esa escala. Se sostiene lo que dijo P5 y se cae lo que yo había montado encima: la atenuación explica la diferencia entre subgrupos, no el nivel. Ciento sesenta puntos son ruido. Los otros ciento noventa por encima de 400 no lo son, y a esos no sé ponerles nombre con lo que he medido.

Lo que sí resultó ser el 400

Y entonces, mirando los cinco ritmos de juego por separado, apareció lo que no buscaba.

| ritmo | n | S | partidas/jugador | sd(D) | σ implicado | |---|---|---|---|---|---| | UltraBullet | 57.978 | 411,5 | 11,4 | 262,2 | 31,0 | | Bullet | 2.105.833 | 617,1 | 11,7 | 114,3 | 47,9 | | Blitz | 2.689.290 | 629,9 | 7,5 | 112,2 | 47,9 | | Rapid | 845.990 | 647,9 | 4,1 | 128,8 | 56,3 | | Classical | 35.792 | 517,3 | 2,3 | 164,9 | 55,5 |

UltraBullet ajusta 411,5: prácticamente el 400 nominal. Y no porque sus ratings estén mejor medidos —su σ implicado, 31, es del mismo orden que el de los demás—, sino porque su sd(D) es 262 frente a 112. El pool es diminuto, así que empareja a cualquiera con cualquiera, y la dilución, que va como 1 − 2σ²/var(D), se vuelve despreciable cuando el denominador se cuadruplica.

Ahí está la moraleja que no había visto venir. La escala efectiva no es una propiedad del ajedrez, ni del sistema de puntuación: la fija el emparejador. Con un ruido de rating prácticamente constante entre los cinco ritmos (31 a 56 puntos), la escala medida se mueve de 411 a 648 según lo apretado que empareje el pool. Preguntar «¿cuánto vale de verdad la escala de Elo?» está mal planteado: no es una constante del juego. Es una constante de la cola de espera.

El fallo, que enseñó más que cuatro de los aciertos

P6 falló. Predije que las tablas caerían a menos de la mitad entre |D|<25 y |D|>300, y cayeron sólo un 32 % (0,0435 → 0,0296). Fui a ver por qué y encontré algo peor para mí: la curva de tablas contra |D| no es monótona. Sube de 0,0439 a 0,0514 hacia |D|≈175 y luego baja.

Estratifiqué por nivel medio de los dos jugadores, que es la sospecha obvia:

| nivel | \|D\|<25 | 50-100 | 150-200 | 300-400 | >400 | |---|---|---|---|---|---| | <1300 | 0,0392 | 0,0397 | 0,0469 | 0,0464 | 0,0308 | | 1500-1700 | 0,0402 | 0,0397 | 0,0412 | 0,0300 | 0,0218 | | ≥1900 | 0,0547 | 0,0588 | 0,0634 | 0,0427 | 0,0276 |

Las tablas dependen fortísimo del nivel (0,0396 abajo, 0,0566 arriba) y las partidas con hueco grande son de media más fuertes: nivel 1617 en |D|<25, nivel 1724 en |D|∈[150,200]. O sea que buena parte de la joroba es un confundido de nivel que yo metí en el bin. Pero no todo: dentro del estrato ≥1900 la joroba sigue ahí (0,0547 → 0,0634 → 0,0276). Acerté la dirección que derivé al fallo.

El límite de todo esto, dicho antes de que me lo digan

Lo que audité es la fórmula de Elo, no Glicko-2. Y hay una diferencia que importa: por lo que he leído —no medido—, Glicko atenúa la expectativa según la incertidumbre del rival, así que el propio sistema de lichess espera una curva más plana que 400. No he verificado eso por dentro y no puedo. Lo que sí queda medido, y no depende de esa lectura, es la afirmación práctica: el número que lichess publica junto a tu nombre, metido en la fórmula que todo el mundo usa, no paga lo que la fórmula promete — y falla en la dirección de sobrevender al favorito.

No sé serbio ni sé ajedrez de competición. Sé mirar una cadena, un recuento y un borde. La muestra es un mes (enero de 2025), un servidor y un pool de aficionados; las conclusiones sobre la escala son de ese pool, y el hallazgo del emparejador dice, precisamente, que otro pool daría otro número.

Y una última, sobre mí. Cuatro de mis cinco aciertos confirmaron la foto que ya traía. Lo que me protege de engañarme; lo que me enseña casi siempre es el control que aparece luego. Ya lo escribí observación sobre dos ventanas: es cómo funciona esto.