# E8 · «Precio frente a referencia v2, por reglas y sin modelos» · DEFINICIONES PREVIAS (pre-registro) Ejecutor: Opus 5.5 · 26-oct-2026. Encargo E8 de `asesor/BENCHMARK_MUNDIAL.md` (§4 H4 y §5.3). Antecedente: A1 (`mediciones/precios/`, sellado 2456b5678d629bbd2fa15fb0abb01d54). **Escrito y sellado antes de calcular ninguna razón pagado/referencia sobre los datos reales.** Lo visto antes de sellar: recuentos de cobertura por reglas (`salidas/01_cobertura_explora.json`), objetos de contratos (para escribir las reglas), los documentos de los acuerdos marco de papel y sus precios (la referencia), las referencias de Eurostat y del geoportal, y, de pasada, tres importes de basados de la DGRCC al listar los AM (grupo de referencia, no población). **Cero modelos de lenguaje**: todo es reglas y aritmética; el cotejo lo hago yo leyendo el objeto. Reglas de la casa que se aplican: universo `NOT es_copia` (definición de la web); importe comparable sin IVA; fuera acuerdos marco y SDA (topes, no compras); fuera Canarias, Ceuta y Melilla (otros impuestos); **solo órganos, nunca empresas ni personas**; vocabulario sin «fraude», «sobrecoste» ni «sospechoso»; «por encima de la referencia» describe un precio, no un juicio. ## 1. Construcción, unidad, universo - Construcción `unified_20261025` (publicada el 25-oct) y satélites `.vinculos`, `.identidad`; solo lectura. - Unidad = fila `unidad = 'adjudicacion'` (contrato o lote), `anio_ref` 2015-2026, todas las fuentes. - Mercado = reglas v1 de A1 (`precios/scripts/reglas.py`, CPV o texto del objeto con exclusiones) para carburantes, electricidad y papel. Base: `scripts/c1_base.py` → `priv/e8_base.parquet` (candidatas con copias marcadas). - Universo de cada mercado (en este orden; el primer motivo que se cumple es el estado): `copia` (`copia_de` no nulo, `correccion_imp_adj = 'copia_otra_fuente'` o `cuenta = FALSE` en vínculos) · `sin_importe` (`imp_adj_eur_comparable` nulo o ≤ 0) · `acuerdo_marco` (`rol_am` 'acuerdo' o 'sda') · `fuera_territorio` (provincia INE 35, 38, 51, 52 o NUTS ES70, ES63, ES64; provincia por `comun_a1.provincia_ine`) · `fuera_periodo`. - **Mes de referencia**: el de la primera fecha no nula entre adjudicación, formalización y publicación si cae entre 1-1-2015 y 31-10-2026; si no, julio de `anio_ref`. **Ventana**: carburantes 2015-01 → 2026-10; electricidad 2015-01 → 2026-06 (último semestre de Eurostat 2026-S1); papel 2020-05 → 2027-03 (vigencia de los AM con precio, §2.3). ## 2. Referencias (descargadas con manifiesto en `PRECIOS_REFERENCIA/`; licencias en `licencias/`) ### 2.1 Carburantes (`scripts/r1_ref_carburantes.py` → `salidas/ref_carb_mensual.csv`) - **Geoportal del MITECO**, servicio REST histórico (precio por estación y día): **un lunes por semana**, 5-1-2015 → 19-10-2026 (616 días) más el día del sondeo (15-1-2015). Por día y provincia, media de las estaciones con precio de gasóleo A, gasóleo B y gasolina 95 E5; provincia-día con < 5 estaciones → media nacional (Península y Baleares) del día. **Referencia mensual = media de los días muestreados del mes**; provincia desconocida → nacional. - **Gasóleo C**: no está en el geoportal → Weekly Oil Bulletin (Comisión Europea, datos que remite el MITECO), España, «heating oil» con impuestos, media de las semanas del mes; nacional. - Todo ÷ 1,21 (IVA) → € por litro sin IVA. - Aviso que se dice siempre: entre abril y diciembre de 2022 la bonificación de 20 céntimos se descontaba en el ticket y no en el precio del geoportal (sensibilidad §6). ### 2.2 Electricidad (`scripts/r2_ref_electricidad.py` → `salidas/ref_electricidad_eurostat.csv`) - **Eurostat `nrg_pc_205`**: precio medio de la electricidad a consumidores no domésticos en España, semestral, **€/kWh sin IVA ni impuestos recuperables** (`X_VAT`: incluye energía, redes, cargos e impuesto eléctrico), por banda de consumo anual (IA < 20 MWh … IG ≥ 150.000 MWh). Semestre = el del mes de referencia. Por qué no OMIE: OMIE es solo el término de energía del mercado diario (≈ la mitad del precio final) y e·sios exige clave; A1 no tuvo referencia. ### 2.3 Papel (`salidas/ref_papel_am.csv`, transcrito a mano de los documentos de la PLACSP, ver §8) - **Acuerdos marco de la DGRCC (Ministerio de Hacienda) 20/2019, 20/2021, 20/2023 y 20/2025** «suministro de papel de equipos de impresión, fotocopiadoras y multicopiadoras». Unidad del AM = **caja de 5 paquetes de 500 hojas** (PCAP, cláusula 6.2). - Referencia = **mediana de los precios ofertados por las empresas adjudicatarias** (€/caja sin impuestos, Península y Baleares, A4), por lote (1 fibra virgen, 2 reciclado) y gramaje (80 g; 75 g solo en lote 1), en su **vigencia**: 20/2019 2020-05-01 → 2022-03-31 (primer basado: 28-5-2020; duración máxima 2 años); 20/2021 solo lote 2 (el lote 1 quedó desierto) 2022-04-01 → 2024-03-31 (entrada en vigor y prórroga en la resolución de prórroga); 20/2023 2024-04-01 → 2026-03-31 (ídem); 20/2025 2026-04-01 → 2027-03-31 (PCAP cláusula 4). **Hueco declarado**: fibra virgen entre abril de 2022 y marzo de 2024 no tiene referencia; antes de mayo de 2020, tampoco (los documentos del AM 20/2017 no traen precios). - Es el precio que consiguió la central de compras del Estado, fijado al licitar el AM: **no es un índice de mercado**. ## 3. Cantidad, unidad y producto por reglas (`scripts/reglas_e8.py`; pruebas `pruebas/test_reglas_e8.py`, 59 comprobaciones) Sobre el objeto normalizado (minúsculas, sin acentos; el guion bajo separa palabras). Números: millares con punto o espacio, decimal con coma; coma de millares inglesa solo con varios grupos o si el valor leído con coma decimal es < 10 (regla de A1: «1,500 l» → 1.500). Estados tras el universo, en este orden. Paridad medida antes de sellar: las dos implementaciones de las reglas dan lo mismo en las 154.045 filas candidatas (0 diferencias) y pasan las mismas 59 pruebas. ### 3.1 Carburantes (v3 = v2 de A1 + las dos correcciones de su informe) - `excluido_v2` (limpiador, aditivo, hidrolimpiadora, congelador) → fuera. - Cantidad: primera cantidad en litros del objeto que no sea capacidad (`reglas_v2.cantidad_principal` de A1, sin cambios). Sin cantidad → `sin_cantidad`. - Producto (`producto_carb`): AdBlue/urea, dos letras distintas (B, C o «A» estricta) o gasóleo + gasolina → `mixto`; letra B o C explícita → esa (manda sobre «calefacción»: «gasóleo B de calefacción» → B); gasolina → 95 (98 aparte, sin referencia); sin letra B/C: contexto de calefacción (colegio, caldera, pabellón…) → C; agrícola/bonificado → B; letra A o contexto de automoción → A; si no, `sin_producto`. Producto fuera de {A, B, C, 95} → `sin_producto_comparable`. - Núcleo: litros ≥ 200 y una sola cantidad distinta en el objeto. ### 3.2 Electricidad (`energia_elec`) - Lote de gas natural (o gas sin electricidad) → `lote_gas`; certificados, baterías, autoconsumo, fotovoltaica, recarga, generador → `no_suministro`. - Cantidad: número + kWh/MWh/GWh que **no** sea umbral (en los 45 caracteres anteriores: superior, inferior, mayor, menor, igual, hasta, más de, menos de, >, <, límite, capacidad, máximo, mínimo, entre…); varias cantidades distintas → `varias_cantidades`; ninguna → `sin_cantidad`. «Al año / anual / kWh/año» detrás → cantidad anual. - Energía del contrato = anual × duración/12 (o la cantidad, si no es anual); duración = `duracion_meses` y, si falta, **12 meses** (marcado; sensibilidad §6). Consumo anual (para la banda) = anual, o total × 12/duración. - Núcleo: energía del contrato ≥ 1.000 kWh. ### 3.3 Papel A4 (`papel`) — unidad: **caja equivalente = 2.500 hojas** - Fuera, por este orden: otro artículo o papel especial (sobres, tóner, carpetas, cartulina, impreso, estucado, offset, de color, membrete, laboratorio…) → `excluido_articulo`; A3/A5/otro formato o medidas (65×90…) → `formato_no_a4`; gramaje distinto de 75 u 80 g o mezcla → `gramaje_especial`; virgen y reciclado a la vez → `fibra_mixta`; un número seguido de una palabra que no es unidad de papel («3 percheros») → `otros_articulos`; «N + M» → `suma`. - Cantidad: «N cajas/caixes» × hojas por caja (2.500, o lo que diga: «de 4 paquetes», «de 2.500 folios», «5x500»); «N paquetes/resmas» × hojas por paquete (500, o «de 100/200/250 hojas»); «N unidades de paquetes/cajas»; si no hay nada de eso, «N folios/hojas» con N ≥ 1.000; si no, «N unidades» con un único envase descrito («paquete de 500 hojas») → N envases; «N unidades» sin envase → `unidad_ambigua`; nada → `sin_cantidad`. El tamaño del envase no cuenta como cantidad. Varias cantidades que no coinciden en hojas → `varias_cantidades`. Números de ≥ 7 cifras sin puntos = códigos (no cantidad). - Fibra: reciclado → lote 2; fibra virgen → lote 1; sin fibra escrita → **lote 1** (sensibilidad: lote 2). Gramaje: 75 u 80 escritos; si no, 80. Formato: A4 escrito o, si no hay otro formato, A4 supuesto (sensibilidad: solo A4 escrito). - **Grupo de referencia** (no es población): basados de los AM de papel de la DGRCC (objeto con «acuerdo marco/AM 20/2019, 20/2021, 20/2023, 20/2025» u órgano DGRCC), con cualquier `rol_am`. Se calculan igual y sirven para validar la referencia. - Núcleo: ≥ 2 cajas equivalentes (5.000 hojas). ## 4. Razón, validez, «por encima» - `razón = (importe sin IVA ÷ cantidad) ÷ referencia` (litros; kWh; cajas equivalentes). - Sin referencia para el producto, la banda o el mes → `sin_referencia`. Fuera del núcleo → `fuera_nucleo`. - **Válido** = núcleo y razón en [0,5; 2] (carburantes y electricidad) o [0,5; 2,5] (papel, porque el precio al por menor de un pedido pequeño puede doblar el del AM). Fuera → `dudoso` (nunca entra en nada). - **«Pagado por encima de la referencia» = razón > 1,15** (margen del 15 %: dispersión entre estaciones y provincias, transporte, pedidos pequeños). Sensibilidad 1,10 y 1,25. ## 5. Resultados que se publicarían (solo si el mercado PASA, §7) — por mercado y por órgano, nunca por empresa ni contrato - Por mercado (y por año, producto/fibra, tipo de órgano, menor sí/no): n válidos, **mediana de la razón con IC 95 % (bootstrap de contratos, 10.000 réplicas, semilla 20261026; 2.000 en los cortes)**, P10-P90, % dentro de ±15 %, % por encima (> 1,15) con IC de Wilson; cobertura (válidos ÷ universo, en contratos y en importe). - Por órgano (`organo_clave` de la identidad 20261025; carburantes órgano × producto, papel órgano; electricidad ninguno): solo con **N ≥ 10** válidos; K = contratos por encima; p0 = tasa por encima del resto del mercado (mismo producto en carburantes) dejando fuera al órgano; prueba binomial de cola superior; **Holm con α = 0,05** sobre las unidades evaluables del mercado. Hecho «por encima con más frecuencia que el resto» si se rechaza. Se publica N, K, mediana con IC (2.000) y el hecho. Órganos con NIF de persona física: fuera. - Texto: «En *N* contratos de *mercado* con cantidad en el objeto, *K* pagaron por unidad más de un 15 % por encima de *referencia* del mes». Lo que no dice: que el precio sea indebido (pedidos pequeños, transporte, urgencia, calidad, un presupuesto máximo en vez de un precio). ## 6. Sensibilidades (se informan; no cambian el veredicto) Márgenes 1,10 y 1,25; solo menores / sin menores; por `rol_am` (basado o no). Carburantes: sin abril-diciembre de 2022. Papel: sin fibra → lote 2; validez [0,5; 2]; solo A4 escrito. Electricidad: solo con duración publicada. ## 7. Validaciones y veredicto POR MERCADO (umbrales fijados ahora) 1. **Cobertura**: ≥ 300 contratos válidos (criterio E8 del benchmark). 2. **Cotejo a mano**: 50 contratos válidos por mercado (todos si hay menos), orden md5('e8-cotejo-' ‖ mercado ‖ source ‖ '|' ‖ id_canonical), como mucho 2 por órgano. Por contrato compruebo, leyendo el objeto y el importe tal como están en la fuente (la fila publicada; para los de la PLACSP, además, la ficha original cuando se pueda descargar): cantidad (±1 %), unidad y conversión, producto / fibra / gramaje / banda, y que el contrato es una compra de ese bien (no un presupuesto máximo de un AM ni una mezcla). **Pasa con ≥ 45/50 (90 %) y ≥ 27 de los 30 primeros**. Con menos de 50, ≥ 90 %. 3. **Segunda implementación** (`scripts/impl2_reglas.py` + `scripts/impl2_calculo.py`: Python puro, sin DuckDB ni `reglas_e8`/`reglas_v2`; reglas reescritas aparte a partir de este texto; referencias recalculadas desde los ficheros crudos): diferencias en estado, válido, razón (1e-6 relativo) o «por encima» ≤ 0,5 % del universo del mercado **y** ≤ 1 % de los válidos; unidades órgano: N, K y hecho iguales en ≥ 99,5 %. Banco sintético (`pruebas/banco_e8.py`): plantados detectados por las dos, caso de cero válidos sin error. 4. **Referencia**: carburantes — media nacional mensual del geoportal frente al WOB (gasóleo A ↔ diésel, 95 ↔ euro-super) dentro de ±3 % en ≥ 95 % de los meses; papel — los basados de la DGRCC (grupo de referencia) con mediana de la razón en [0,90; 1,05] y ≥ 80 % en [0,85; 1,10]; electricidad — no hay contraste independiente (se dice). 5. **Sentido del dato**: carburantes — mediana de la razón en [0,85; 1,15] y gasóleo C ≥ 75 % dentro de ±15 % (no regresión de A1); electricidad — mediana en [0,6; 1,5]; papel — sin umbral de mediana (se espera > 1: lo valida el punto 4). **Veredicto por mercado**: **PASA** (publicable como descriptivo por mercado y órgano) si se cumplen 1-5; **NO PASA** si falla alguno, diciendo cuál. No es un indicador de riesgo: ninguna etiqueta externa dice si pagar por encima señala algo (A1: 0 lotes de cártel de carburantes). En el registro: «pasa» o «no pasa» como dato descriptivo, con «lo que no dice». ## 8. Ficheros sellados y fuentes - Este texto (md5 en `DEFINICIONES_PREVIAS_E8.md5`, copia de solo lectura `.sellado.md`); código y referencias en `SELLO_CODIGO_E8.md5`: `scripts/reglas_e8.py`, `c1_base.py`, `c2_calculo.py`, `r1_ref_carburantes.py`, `r2_ref_electricidad.py`, `impl2_reglas.py`, `impl2_calculo.py`, `c4_cotejo_muestra.py`, `pruebas/test_reglas_e8.py`, `pruebas/banco_e8.py`, `salidas/ref_papel_am.csv`, `salidas/ref_electricidad_eurostat.csv`. - La referencia de carburantes se termina de construir cuando acabe la descarga del geoportal (el código ya está sellado; el CSV se sella aparte con su md5 en `ESTADO.md` antes de correr el cálculo). - Documentos de los AM (PLACSP; sha256 en el manifiesto): informes de valoración de ofertas (20/2019, 20/2023), actas de propuesta de adjudicación (20/2019, 20/2021, 20/2025), resoluciones de prórroga (20/2021, 20/2023), informe de la unidad proponente (20/2025), PPT/PCAP (unidad de pedido, vigencia, precios máximos). Las ofertas de empresas no adjudicatarias y los nombres de empresa no salen de `priv/`.