Saltar a contenido

Referencia de la API

Superficie pública de bayesrisk, organizada por dominio. Cada símbolo se genera automáticamente desde sus docstrings con mkdocstrings; las firmas y campos son los del código publicado (2.0.0).

Estabilidad (SemVer 2.x)

El pipeline de validación de scorecard (F1) —el trío run → Study → BayesRiskConfig y los dominios data, eda, binning, selection, model, scorecard, calibration, performance y stability— es API estable: no rompe hasta una versión 3.0. También lo son el informe (report), el trail de auditoría (audit), porque ya son superficie de integración, y la puerta guiada (guided, bayesrisk.Scorecard), desde que cerraron sus tres puertas. Las superficies que aún crecen (modelado ML, provisiones, survival, forward-looking, stress, validación, gobernanza y tracking) están marcadas como experimentales en su docstring, fuera de la garantía SemVer 2.x.

Esa lista no se escribe a mano en tres sitios: la fija bayesrisk.testing.stability y la verifican los gates del repositorio contra el docstring de cada paquete y contra esta página.

Núcleo liviano e import perezoso

import bayesrisk no arrastra el stack ML. bayesrisk.run se re-exporta de forma perezosa (PEP 562) desde bayesrisk.api, y los backends pesados de cada dominio (pandas, sklearn, statsmodels, optbinning, XGBoost, …) se cargan solo al ejecutar el paso correspondiente, tras sus extras opcionales.

Puerta guiada

bayesrisk.Scorecard construye, corre y cuenta un scorecard de comportamiento con la entrada mínima; es un cliente de run que arma el BayesRiskConfig, lo ejecuta y lee sus artefactos. Estable bajo SemVer 2.x desde que cerraron sus tres puertas (código, config completo y pantalla): su firma, sus resúmenes y sus decisiones (exclude, keep, merge_bins, set_bins) sólo crecen de forma aditiva.

Scorecard

Un scorecard de comportamiento de punta a punta, con la entrada mínima (D-FLU-1).

Parameters:

Name Type Description Default
data str | Path | DataFrame

Ruta a un CSV, Parquet o Excel, o un pandas.DataFrame. Los datos se copian al proyecto —un archivo, tal cual; un DataFrame, como Parquet— bajo <run_dir>/<name>/input/ con su huella en el nombre, y el config referencia esa copia: la inferencia y cada corrida leen exactamente los mismos bytes, y config.yaml + input/ reproducen la corrida por sí solos.

required
target str | _TargetRule

La columna 0/1 (o verdadero/falso) que dice quién es «malo», o una regla {"col": "dias_mora", "op": ">", "value": 90} con los operadores del motor.

required
id str | None

Identificador de cada operación, opcional y recomendado: una columna (llave de unicidad) o el nombre del índice del archivo. Sin él se usa el índice del archivo y se declara.

None
date str | None

El eje temporal: date= particiona por fecha de corte, cohort= por añada; sin eje, partition="random" explícito (D-OBL-5: la estrategia no se siembra). Exactamente uno.

None
cohort str | None

El eje temporal: date= particiona por fecha de corte, cohort= por añada; sin eje, partition="random" explícito (D-OBL-5: la estrategia no se siembra). Exactamente uno.

None
partition str | None

El eje temporal: date= particiona por fecha de corte, cohort= por añada; sin eje, partition="random" explícito (D-OBL-5: la estrategia no se siembra). Exactamente uno.

None
oot_from str | None

La frontera fuera de tiempo, obligatoria con date (fecha ISO) o con cohort (las cohortes reservadas). Si falta, la puerta se detiene antes de correr con el rango del archivo y el valor que usaría.

None
oot_cohorts str | None

La frontera fuera de tiempo, obligatoria con date (fecha ISO) o con cohort (las cohortes reservadas). Si falta, la puerta se detiene antes de correr con el rango del archivo y el valor que usaría.

None
holdout float

Proporción reservada como Holdout dentro de la muestra de desarrollo (0,2 de fábrica).

0.2
name str

Nombre de la versión del proyecto y carpeta raíz: la evidencia queda en <run_dir>/<name>/ (§8-8: "bayesrisk-runs" y "scorecard" de fábrica).

'scorecard'
run_dir str

Nombre de la versión del proyecto y carpeta raíz: la evidencia queda en <run_dir>/<name>/ (§8-8: "bayesrisk-runs" y "scorecard" de fábrica).

'scorecard'
purpose str | None

Con purpose se enciende la gobernanza y la ficha del modelo (D-GOB-8); sin él no hay ficha. owner y review_every (meses) completan la ficha.

None
owner str | None

Con purpose se enciende la gobernanza y la ficha del modelo (D-GOB-8); sin él no hay ficha. owner y review_every (meses) completan la ficha.

None
review_every str | None

Con purpose se enciende la gobernanza y la ficha del modelo (D-GOB-8); sin él no hay ficha. owner y review_every (meses) completan la ficha.

None
track str | Path | None

Ruta o URI de MLflow: enciende el registro de la corrida (D-FLU-9). Apagado sin él.

None
features Sequence[str] | None

Las predictoras y cuáles son categóricas. Si no se dan, se infieren y se declaran.

None
categorical Sequence[str] | None

Las predictoras y cuáles son categóricas. Si no se dan, se infieren y se declaran.

None
max_bins int
6
min_bin_size int
6
monotonic int
6
min_iv int
6
max_correlation int
6
max_vif int
6
stepwise int
6
p_enter int
6
p_exit float
0.05
sign_policy float
0.05
pdo float
0.05
target_score float
0.05
target_odds float
0.05
anchor float
0.05
target_pd float
0.05
deciles float
0.05
psi_thresholds tuple[float, float]

Los campos esenciales de cada etapa (§3.8 de la enmienda), con los valores del preset F1 de fábrica. Cada uno escribe una hoja existente del config; lo que no está aquí se alcanza por sc.config (la puerta completa).

(0.1, 0.25)
validation tuple[float, float]

Los campos esenciales de cada etapa (§3.8 de la enmienda), con los valores del preset F1 de fábrica. Cada uno escribe una hoja existente del config; lo que no está aquí se alcanza por sc.config (la puerta completa).

(0.1, 0.25)
document tuple[float, float]

Los campos esenciales de cada etapa (§3.8 de la enmienda), con los valores del preset F1 de fábrica. Cada uno escribe una hoja existente del config; lo que no está aquí se alcanza por sc.config (la puerta completa).

(0.1, 0.25)
formats tuple[float, float]

Los campos esenciales de cada etapa (§3.8 de la enmienda), con los valores del preset F1 de fábrica. Cada uno escribe una hoja existente del config; lo que no está aquí se alcanza por sc.config (la puerta completa).

(0.1, 0.25)

config property

config

El BayesRiskConfig completo que corre (la puerta completa lo ve todo).

config_hash property

config_hash

La identidad de la corrida completa sobre el config vigente.

study property

study

El Study de la última corrida, o None si aún no corrió.

steps property

steps

Las etapas del pipeline en orden; los valores válidos de run(until=).

project_dir property

project_dir

<run_dir>/<name>: donde queda todo.

results property

results

La tabla de decisión de cada etapa que ya corrió (con sus rótulos en español).

Cada una es un DataFrame con los números intactos que se muestra como la lee una persona —coma decimal, miles, porcentajes—, con la misma regla del resumen de su etapa.

inferences property

inferences

Lo que la puerta infirió y declara al trail en cada corrida.

to_yaml

to_yaml()

El config vigente en YAML, para la puerta completa o la pantalla.

run

run(until=None, *, raise_on_error=False)

Corre el pipeline completo —o hasta until inclusive— y cuenta cada etapa.

until recorta run.steps al prefijo del pipeline: es una corrida parcial con su propio config_hash (D-FLU-3). Ante un fallo de dominio la corrida devuelve el estado y el resumen final lo dice; con raise_on_error=True se levanta :class:ScorecardRunError con el mismo diagnóstico (D-FLU-4). La carpeta del proyecto admite una corrida a la vez: si otra la tiene, se levanta :class:ScorecardRunError antes de mover nada.

resume

resume()

Corrida nueva y completa sobre el config vigente (D-SIM-6, D-FLU-3).

Nada se reutiliza de la corrida anterior: run_id, lineage y evidencia son propios, y la anterior queda como respaldo lateral (.run.old.*) con su informe.

summary

summary(stage=None)

El resumen final (D-FLU-4) o el de una etapa que ya corrió (D-FLU-2).

exclude

exclude(columns, *, reason)

Descarta variables en toda la corrida siguiente, con motivo.

Escribe binning.exclude_columns (D-EXC-1): la variable no se tramifica, no aparece en las tablas y no puede detener la corrida en «Tramos y WoE». La retira de las listas forzadas de selección y modelo —las dos rechazan forzar una variable que el binning ya no publica— (la última decisión sobre una variable gana). Sus tramos fijados con set_bins()/merge_bins() quedan en suspenso, y keep() los reactiva. La corrida siguiente (resume()) emite al trail un evento decision con autor usuario y este motivo.

keep

keep(columns, *, reason)

Fuerza variables a entrar al modelo, con motivo.

Escribe selection.force_include y model.force_include (sólo con la primera, model no vería una variable que selection descartó por IV, correlación o VIF) y las retira de las listas contrarias y de binning.exclude_columns. Una variable forzada que falle una validación dura del motor —signo invertido con la política en fail— sigue fallando: keep no apaga ninguna guarda.

bins

bins(column)

Los tramos de una variable numérica en la última corrida, numerados desde 1.

Es la tabla con la que se decide merge_bins/set_bins: número, rango, filas, malos, tasa de malos y WoE, leídos de la tabla de binning que el motor publicó (sin los tramos Special/Missing, que no tienen corte).

merge_bins

merge_bins(column, bins, *, reason)

Junta dos tramos adyacentes de una variable numérica, con motivo.

Los tramos se numeran como en :meth:bins (desde 1). Escribe la hoja binning.variable_overrides[<column>].user_splits con los cortes vigentes menos el que separaba esos dos tramos, todos fijados (user_splits_fixed): en la corrida siguiente el motor tramifica exactamente así y calcula el WoE de los tramos que resultan.

set_bins

set_bins(column, cuts, *, reason)

Fija los cortes de una variable numérica (los límites entre tramos), con motivo.

Escribe binning.variable_overrides[<column>].user_splits con esos cortes, todos fijados: en la corrida siguiente el motor tramifica exactamente así. Un tramo fijado que viole el tamaño mínimo o la monotonía declarada hace que el motor no tramifique la variable, y el resumen de «Tramos y WoE» lo dice.

export_excel

export_excel()

Un libro Excel por etapa, numerado, en <run_dir>/<name>/excel/ (D-FLU-5, D-SIM-7).

01 Datos y muestras.xlsx … 10 Validación formal.xlsx para las etapas que corrieron —cada uno con el resumen, la tabla de decisión y las tablas completas que el informe publica para ese dominio, con la misma protección de celdas que los exports del informe— más 11 Decisiones.xlsx con las decisiones del registro de auditoría (humanas, de la puerta y del motor). Opcional: nunca es la vía para ver un resultado. Exige el extra excel (openpyxl); sin él se detiene con el comando de instalación.

export

export(destination)

Empaqueta la carpeta del proyecto en un .zip (hallazgo #8 de INTEGRACION-EXTERNA).

Entran el config vigente, el snapshot de datos, la evidencia de la corrida (run/), el informe y el Excel si se exportó; quedan fuera el candado y los respaldos de corridas anteriores. Devuelve la ruta del archivo escrito.

compare

compare(other)

Dos corridas lado a lado: cifras clave, variables finales y decisiones humanas.

StageSummary dataclass

El resumen de una etapa: de 3 a 8 líneas, sus alertas y su tabla de decisión (D-SIM-5).

text

text(*, with_table=True)

El resumen como texto para la consola.

to_dict

to_dict()

El resumen como JSON transportable, con la tabla ya escrita como la lee una persona.

Es lo que consume la pantalla (D-FLU-8: Resultados lee la misma fuente que summary()): las celdas viajan formateadas por :func:_formatear —coma decimal, miles, «—» en las ausencias— para que el panel pinte exactamente lo que el notebook y la consola muestran, sin una segunda regla de formato en el front.

FinalSummary dataclass

El resumen final (D-FLU-4).

Ejecución y validación técnica por separado, cinco cifras, qué revisar, decisiones y archivos.

text

text()

El resumen final como texto para la consola.

to_dict

to_dict()

El resumen final como JSON transportable (los dos estados, cifras, alertas, archivos).

Las etapas no viajan aquí: cada una se serializa con su propio :meth:StageSummary.to_dict.

Ejecución y estado de la corrida

Punto de entrada único (run) y las estructuras stateful que produce: el Study contenedor, su ArtifactStore namespaced, el RunContext (estado + lineage) y el LineageBundle reproducible. check_pipeline responde si un config se puede ejecutar, sin ejecutarlo.

run

run(
    config,
    *,
    artifacts=None,
    run_dir=None,
    preamble=(),
    on_step=None,
)

Ejecuta una corrida completa de extremo a extremo y devuelve el Study.

Superficie pública única de ejecución (CT-4): ensambla el AuditSink y el ModelInventory (assemble_run), corre el Study, y —solo en éxito y solo si governance.publish_to_inventory— publica la ModelCard en el inventario.

Semántica de fallo (D-UI-2, decidida). Study.run() es el primitivo fail-loud: ante un fallo marca status="failed", conserva el lineage y re-levanta. Esta función es el envoltorio de producto: captura el BayesRiskError y devuelve el Study parcial en vez de propagarlo. El fallo no se silencia pero tampoco explota. Por eso, el consumidor por código debe chequear study.run_context.status ("done" vs "failed") antes de leer los resultados.

Dónde quedan los resultados: en study.artifacts, indexado por (dominio, clave)::

study = bayesrisk.run(config)
assert study.run_context.status == "done"
study.artifacts.get("performance", "result")     # métricas de discriminación
study.artifacts.get("model", "coefficients")     # los betas del modelo
study.artifacts.keys()                           # todo lo que dejó la corrida

study.results es el resumen firmable de la corrida, no un duplicado del store: trae metrics —plano, "<dominio>.<metrica>", float finito— y metric_sections por dominio (D-GOB-1…3). Es lo que leen el model card y MLflow. Una métrica que el dominio no pudo evaluar no aparece; ausencia y cero no son lo mismo.

Dónde queda la evidencia en disco: en run_dir, y sólo si se pide (D-GOB-6). Con el default None la corrida no escribe nada, que es el comportamiento histórico: una librería que empieza a dejar archivos en el cwd de quien la importa es una regresión, no una mejora. Con un run_dir se escribe allí el layout de SDD-03 §6::

<run_dir>/audit_trail.jsonl   # si `audit` está activo (su nombre lo fija AuditConfig)
<run_dir>/environment.json    # si `audit` está activo y captura entorno
<run_dir>/model_card.json     # si `governance` está activa
<run_dir>/model_card.md       # idem
<run_dir>/study/              # lo que produce `Study.save`: config, lineage y artefactos

Cada archivo aparece sólo si su sección está activa: audit sin governance deja trail y entorno, y no card. scenario_log.jsonl del layout de SDD-03 §6 no se escribe: hoy no tiene ningún productor, y crear un archivo vacío para cumplir el layout sería teatro.

Si run_dir ya contiene una corrida, no se mezcla con la nueva. El layout se construye en un hermano temporal y sustituye al destino sólo cuando está completo; la corrida previa se aparta a un respaldo lateral (.<nombre>.old.*) que se conserva. Si algo falla antes de ese punto —al ensamblar, durante la corrida o al escribir la evidencia—, la corrida previa queda exactamente donde estaba, y lo que la corrida fallida alcanzó a dejar —su audit-trail con el diagnóstico del fallo, sobre todo— se conserva al lado, en .<nombre>.failed.*, con la ruta anotada en la excepción; si no llegó a haber evidencia, no queda rastro. Un trail_filename absoluto que apunte dentro de run_dir se escribe también en el temporal y ocupa su lugar con la consolidación: nunca toca la corrida previa.

Entrar por la mitad. artifacts= permite traer resultados ya calculados. Las claves son las parejas (dominio, clave) declaradas en Step.requires/Step.provides; hay que apagar en el config la sección que produciría cualquiera de las claves inyectadas. El tipo lo valida el paso consumidor, no esta puerta. Toda corrida que recibe artefactos externos los enumera en lineage.injected_artifacts y declara que no es reconstruible sólo desde config y datos. Esta puerta es de código: la UI/HTTP no deserializa artefactos externos.

Declarar la procedencia y escuchar cada paso. preamble y on_step son los dos ganchos aditivos de :meth:Study.run: pares (step, payload) que se emiten al trail como decision justo después de run_start —la puerta guiada declara así sus inferencias y las decisiones humanas con motivo— y un callback (nombre_del_paso, study) tras cada paso, con el que esa puerta cuenta cada etapa al terminar. Ninguno cambia el cálculo ni el config_hash; sin ellos la corrida es exactamente la de siempre.

Dónde queda el diagnóstico. En study.run_context.error (:class:~bayesrisk.core.lineage.RunError): tipo de la excepción, mensaje del motor y paso que falló, sin que haya que configurar nada. El audit-trail lo repite en el evento run_end, pero sólo si el config declara un sink: los presets lo declaran desde D-GOB-8, pero un config escrito a mano puede traer audit: null, así que no dependa de él; y el lineage no guarda el error nunca (enmienda RUN-ERROR).

check_pipeline

check_pipeline(config, *, artifacts=None)

Responde si config es ejecutable, sin ejecutarlo, y con qué pasos.

Envoltorio de producto de :meth:~bayesrisk.core.study.Study.check_pipeline: donde el primitivo del núcleo re-levanta, esta función captura y devuelve el veredicto, igual que :func:run frente a Study.run (D-UI-2). Sirve para avisar mientras se edita —el usuario sabe que le falta encender una sección antes de apretar Ejecutar— y es la misma respuesta por código y por interfaz (D-PIPE-3).

No ejecuta pasos, no lee el dataset, no monta sinks ni inventario y no deja rastro de corrida: comprobar no es correr.

Captura Exception, no sólo BayesRiskError. Es deliberado y más amplio que :func:run: una comprobación existe para informar, así que tumbar a quien la llama —el formulario la invoca en cada tecleo— sería peor que cualquier fallo que quiera reportar. Un from_config de dominio puede levantar algo que no es de la familia del motor; is_domain_error lo declara en vez de disfrazarlo (D-PIPE-6).

Parameters:

Name Type Description Default
config BayesRiskConfig

Config ya reconstruido. Que reconstruya es precondición, no resultado: la validez del modelo Pydantic y la ejecutabilidad del pipeline son dos preguntas distintas (D-PIPE-1).

required
artifacts Iterable[ArtifactKey] | Mapping[ArtifactKey, Any] | None

Claves de artefactos que estarán disponibles al correr. Si se entrega un mapping, sus valores se ignoran: comprobar sólo necesita las claves. Una clave válida que ningún paso activo consume se publica en PipelineCheck.inert_artifacts en vez de bloquear.

None

Returns:

Type Description
PipelineCheck

executable=True + steps en orden, o executable=False + el diagnóstico del motor.

PipelineCheck dataclass

Veredicto de ejecutabilidad de un config, sin correr nada (D-PIPE-2/D-PIPE-3).

steps trae los pasos en el orden en que correrían —útil por sí solo: es lo que el usuario va a ejecutar—, y queda vacío si el config no es ejecutable, porque en ese caso no hay pipeline que anunciar.

message guarda str(exc) íntegro, con el código de marca si el motor lo trae al frente: esta es superficie de código, donde el código es el dato, igual que en :class:~bayesrisk.core.lineage.RunError. El copy público lo sanea al publicarlo (:func:~bayesrisk.core.markers.strip_declared_codes, D-ERR-4).

is_domain_error distingue el diagnóstico accionable por quien configura de una excepción inesperada, cuyo texto puede ser detalle interno sin valor para quien usa el formulario (mismo criterio que D-ERR-5).

inert_artifacts enumera, en orden canónico, las claves externas que ningún paso activo ni el cierre transversal del lineage consumirá. No vuelven el config inejecutable: son un aviso contra typos o material preparado para una sección todavía apagada.

Cubre dos familias, y el ValidationError no es un añadido cosmético: las secciones de dominio son Any en el schema raíz, así que un valor fuera de rango dentro de ellas no lo caza BayesRiskConfig.model_validate — lo caza la coacción que hace la resolución, y llega aquí como ValidationError de Pydantic. Es el diagnóstico más accionable que produce esta función (nombra el campo y la restricción); clasificarlo como «inesperado» lo habría ocultado justo en el caso más común.

assemble_run

assemble_run(config, *, run_dir=None, workdir=None)

Construye el AuditSink compuesto y el inventario real/no-op de una corrida.

core recibe ambos objetos ya resueltos: no importa audit, governance, tracking ni MLflow. Si governance.publish_to_inventory=True y falta el extra tracking, esta capa falla ruidoso con MissingDependencyError porque la publicación fue una petición explícita.

run_dir es el directorio de la corrida (D-GOB-6): contra él se resuelve el nombre relativo del audit-trail. Sin él, un trail_filename relativo es un error explícito (D-GOB-7). workdir es el hermano temporal donde :func:run construye la corrida antes de consolidarla: todo trail que caiga dentro de run_dir se abre allí (:func:_resolver_trail).

Study

Estado del experimento y orquestador de la corrida (SDD-01 §4/§7).

Un Study recién construido arranca en status="created" y serializa sin valores ficticios (DoD F0). :meth:run lo transiciona a running → done/failed y congela el lineage. El config es inmutable: su identidad se ancla al config_hash.

inert_injected_artifacts property

inert_injected_artifacts

Expone a la API las claves externas que ningún paso activo consume.

preamble property

preamble

Las declaraciones (paso, payload) que :meth:run emitió antes del primer paso.

Copia profunda de lo que se pasó en run(preamble=…), en el mismo orden; vacía si la corrida no declaró nada o todavía no corrió. Vive en run_context —se persiste con save y vuelve con load, para que un informe regenerado desde un Study recargado diga las mismas decisiones que el trail (capa C de FLUJO-GUIADO-SCORECARD)— y es de sólo lectura: mutar lo devuelto no toca el snapshot.

⚠️ El registro durable es el trail; ante una discrepancia, manda el trail. Cada declaración se añade aquí sólo después de que su emit terminó sin error, así que ante un sink que falla esto trae un prefijo de lo emitido, nunca más. Con un sink compuesto (FanOutSink con trail y tracking) que falle en uno de sus subordinados, el trail puede conservar una declaración que aquí no está: se omite, no se inventa. core no sabe cuál de los sinks compuestos es el durable (CT-4: recibe el sink ya resuelto), así que cerrar esa ventana es cosa de quien compone el sink.

set_audit_sink

set_audit_sink(sink)

Inyecta el AuditSink (ya compuesto por api/runner) y lo propaga al ArtifactStore.

Debe llamarse antes de :meth:run. core no compone FanOutSink ni resuelve el inventario (CT-4): toma un sink ya resuelto.

lineage_bundle

lineage_bundle()

Devuelve el :class:LineageBundle congelado en :meth:run; levanta si no se corrió.

run

run(steps=None, *, preamble=(), on_step=None)

Ejecuta el pipeline y devuelve self (encadenable).

El argumento steps tiene prioridad sobre config.run.steps. fail_fast=False no se soporta en v1: se emite un warning ruidoso (no un no-op silencioso) y se procede como True. Una excepción en un paso (con fail_fast=True) deja status="failed" pero conserva el lineage (evidencia de trazabilidad, SR 11-7), escribe el rastro del fallo en run_context.error (:class:~bayesrisk.core.lineage.RunError: tipo, mensaje y paso), sella finished_at, emite run_end y se re-levanta; el Study parcial sigue siendo guardable.

Dos ganchos aditivos, ambos opcionales y sin efecto sobre el cálculo (enmienda FLUJO-GUIADO-SCORECARD, D-FLU-1/D-FLU-3; el motor no cambia de resultado con ellos):

  • preamble: pares (step, payload) que se emiten al trail como eventos decision justo después de run_start y antes del primer paso, en ese orden. Es la vía con que una puerta de entrada declara su procedencia —qué infirió y qué decisión humana con motivo trae el config— sin construir un segundo sink ni tocar el sobre del evento: el payload es del llamador y viaja tal cual (las claves aditivas que la ficha no lee, como autor y motivo, se conservan; D-ERR-6). No emite nada si la resolución del pipeline falla: entonces el trail lleva run_start y el run_end con el diagnóstico.
  • on_step: se llama con (nombre_del_paso, self) después de que cada paso ejecutó y publicó sus métricas, para que quien orquesta pueda contar lo que ya está en el store (el resumen por etapa de la puerta guiada). Una excepción del gancho se propaga como fallo del paso en curso, con su rastro: silenciarla escondería un error del llamador dentro de una corrida que se diría completa.

check_pipeline

check_pipeline(steps=None)

Resuelve y valida el pipeline sin ejecutar nada; devuelve los pasos en orden.

Responde la pregunta «¿este config se puede correr?» antes de correrlo, que es lo que permite avisarlo mientras se edita en vez de al apretar Ejecutar (enmienda VALIDACION-PIPELINE, D-PIPE-3). La capacidad vive aquí, en el núcleo, y no en la capa UI: quien trabaja por código tiene la misma respuesta que quien usa el formulario, que es el requisito de paridad.

Es fail-loud como :meth:run: un config inejecutable levanta el ConfigError del motor con su diagnóstico. El envoltorio de producto que lo captura y devuelve un veredicto inspeccionable es :func:bayesrisk.check_pipeline, igual que :func:bayesrisk.run frente a :meth:run (D-UI-2).

No toca el run_context: no asigna run_id, no cambia status ni sella finished_at. Comprobar no es correr, y una comprobación no debe dejar rastro de corrida en el audit-trail. No lee el dataset ni escribe en disco, y cuesta ≤0,1 ms con los dominios ya importados (la primera llamada del proceso paga sus imports perezosos, ~1-3 s).

Sí tiene un efecto, y no es cosmético: :meth:_resolve_steps coacciona los sub-configs opacos a su clase real, exactamente como haría :meth:run, y esa coacción materializa los defaults que un config cargado de YAML no traía — con lo que el config_hash de este Study puede cambiar. Es convergente (coaccionar dos veces da lo mismo) y deja el config en el estado que tendría al correr, así que una corrida posterior sobre el mismo Study es consistente; pero quien compare hashes alrededor de esta llamada debe saberlo.

Lo que no hace es sembrar los RNG del proceso cuando el Study se construyó con apply_global_seed=False, que es como lo hace :func:bayesrisk.check_pipeline.

run_step

run_step(name)

Ejecuta un paso aislado y devuelve su resultado; no altera run_context.status.

Emite sólo los eventos del paso (no run_start/run_end) y exige sus prerequisitos presentes. En F0 BayesRiskConfig no expone secciones de dominio, así que la resolución levanta ConfigError (la orquestación de dominios llega en T2).

Se resuelve SIN contexto de dominios activos, a propósito (D-FX-1). [name] no es «el pipeline de esta invocación»: es un paso suelto sobre artefactos que ya deben estar en el store. Pasar {name} como conjunto activo convertiría la comprobación CT-1 de este método en vacua para cualquier paso cuyo requires se derive del contexto —run_step ('report') dejaría de exigir sus cards—, y la precedencia que D-FX-1 fija (steps= → config.run.steps → secciones no nulas) describe una corrida, no este atajo.

save

save(path)

Serializa el Study a un directorio de forma atómica (escribe-a-temporal-y-renombra).

Layout: config.yaml + run_metadata.json + lineage.json (si hay lineage) + artifacts/<domain>/<key>.joblib. Al sobrescribir, el directorio previo se aparta a un respaldo lateral antes de colocar el nuevo y se restaura si el swap falla. En el doble-fallo (falla el swap y también la restauración), el estudio previo queda preservado en el respaldo lateral .old.* y path podría quedar transitoriamente sin directorio válido; se prioriza no perder datos. El azar (seed_manager) no se guarda: se reconstruye en :meth:load. Devuelve el Path del directorio final.

load classmethod

load(path, *, trust=False)

Recarga un Study desde un directorio; reconstruye el azar y verifica el config_hash.

trust=False (default) rechaza un Study con artefactos pickle (vector de ejecución de código). Un config_hash que no coincide con el del lineage levanta :class:~bayesrisk.core.exceptions.ReproducibilityError; una divergencia de versiones de librerías sólo advierte. El SeedManager se reconstruye desde config.repro.seed.

Nota: el chequeo de config_hash detecta divergencia accidental entre config.yaml y el lineage, no manipulación maliciosa (el hash de referencia vive en el mismo directorio editable). La integridad fuerte recae en trust=True + control del origen del directorio.

ArtifactStore

Contenedor namespaced (domain, key) → valor con traza de auditoría por escritura.

El Study inyecta el sink de auditoría; si no se pasa, cae a NullAuditSink (nunca None), de modo que emitir es siempre seguro. get devuelve el mismo objeto guardado (identidad, sin copia defensiva).

set

set(domain, key, value, *, overwrite=False)

Escribe value bajo (domain, key) y emite un AuditEvent "artifact".

Si la clave ya existe y overwrite=False, levanta :class:~bayesrisk.core.exceptions.ArtifactExistsError. El payload del evento distingue creación de sobrescritura con el campo overwrite (trazabilidad SR 11-7). Convención del evento "artifact": step lleva el domain del artefacto (no el paso que lo escribió) y payload el (domain, key) completo; SDD-03 lo consume sin adivinar.

get

get(domain, key)

Devuelve el artefacto (domain, key) (el mismo objeto); ausente → error.

has

has(domain, key)

Indica si la clave (domain, key) está presente.

keys

keys()

Lista las claves (domain, key) presentes, en orden de inserción.

RunContext

Bases: BaseModel

Estado de vida de una corrida del Study.

Arranca en "created" (Study recién construido, serializable sin correr); run() lo transiciona created → running → done|failed y le cuelga el :class:LineageBundle congelado. No es frozen (run() muta su estado); extra="forbid" rechaza un campo intruso al recargar run_metadata.json.

LineageBundle

Bases: BaseModel

Bundle de trazabilidad de una corrida (gobernanza en el núcleo, §4 principio 3, SR 11-7).

Se construye al cierre del run (§7 paso 4); git_sha/data_hash/uv_lock_hash son | None por ausencia legítima (repo ausente, datos sin cargar, uv.lock ausente). data_hash es el hash del contenido lógico por bloques (no los bytes del Parquet, decisión D2); su cálculo vive en data/ (SDD-02), aquí sólo se declara el campo. extra="forbid" rechaza un campo intruso al revalidar el bundle desde disco (Study.load).

injected_artifacts enumera las claves que entraron desde fuera de la corrida. Su default vacío mantiene compatibles los bundles escritos antes de la puerta D-ART-7.

Step

Bases: Protocol

Lo que un dominio implementa para ser orquestable (SDD-01 §7).

@runtime_checkable permite isinstance(obj, Step) en el despacho del motor; sólo verifica la presencia de name/requires/provides/execute, no sus tipos ni firmas.

execute

execute(study, rng)

Ejecuta el paso: lee de study.artifacts, calcula y escribe su salida.

Configuración declarativa

BayesRiskConfig es la raíz del experimento (Pydantic v2): agrupa las secciones de reproducibilidad, orquestación y todos los dominios. Se acompaña de utilidades de identidad (config_hash), carga/volcado YAML y migración de esquema.

BayesRiskConfig

Bases: BayesRiskBaseConfig

Configuración completa del estudio: todas las secciones del pipeline en un solo objeto.

Cada sección es opcional: la que se deja vacía no se ejecuta, y BayesRiskConfig() sin argumentos construye un estudio con todas las secciones vacías. El orden de ejecución lo fija el motor, no el orden de los campos; audit, governance y tracking documentan y registran la corrida, pero no son pasos del pipeline.

RunConfig

Bases: BayesRiskBaseConfig

Parámetros de orquestación de la corrida.

ReproConfig

Bases: BayesRiskBaseConfig

Parámetros de reproducibilidad del experimento.

config_hash

config_hash(cfg)

Devuelve el SHA-256 hex (64 chars) del JSON canónico de las secciones computacionales.

Las secciones de dominio que lleguen opacas (un dict, porque el proceso aún no importó esa capa) se coaccionan antes de canonicalizar, de modo que el digest no dependa del orden de los import. Ver :func:_coaccionar_secciones_opacas y D-HASH-1.

Parameters:

Name Type Description Default
cfg BayesRiskConfig

Config ya validado del que derivar la identidad.

required

Returns:

Type Description
str

Digest hexadecimal SHA-256 del config sin las :data:INFRA_SECTIONS ni la ruta data.load.source (la identidad depende del CONTENIDO del dato, vía data_hash, no de su ubicación en disco).

load_config

load_config(path)

Carga un :class:BayesRiskConfig desde un fichero YAML.

Parameters:

Name Type Description Default
path str or PathLike

Ruta del fichero YAML del config.

required

Returns:

Type Description
BayesRiskConfig

Config validado e inmutable.

Raises:

Type Description
ConfigError

Si el YAML no cumple el schema (campo desconocido, tipo/rango erróneo).

loads_config

loads_config(text)

Carga un :class:BayesRiskConfig desde un string YAML.

Parameters:

Name Type Description Default
text str

Contenido YAML del config (un mapeo en la raíz).

required

Returns:

Type Description
BayesRiskConfig

Config validado e inmutable.

Raises:

Type Description
ConfigError

Si el YAML no es un mapeo o no cumple el schema.

dump_config

dump_config(cfg, *, exclude_unset=False)

Serializa un :class:BayesRiskConfig a YAML legible (orden de declaración).

Parameters:

Name Type Description Default
cfg BayesRiskConfig

Config a volcar.

required
exclude_unset bool

Si es True, omite los campos que no fueron provistos explícitamente (toman su default al recargar). Hace el volcado determinista frente al estado de imports para las secciones de capa diferida (report/audit/governance/validation): un dict de entrada sin, p. ej., report.document produce el MISMO YAML se haya importado o no la capa que coacciona a ReportConfig (que materializaría document por default_factory). El default False conserva el volcado completo (lineage auditable de una corrida).

False

Returns:

Type Description
str

YAML con las claves en orden de declaración y las tildes sin escapar.

migrate

migrate(raw)

Aplica el version-gate y la cadena de migradores a un config crudo.

Parameters:

Name Type Description Default
raw dict[str, Any]

Config recién deserializado del YAML, antes de validar. Un dict sin schema_version asume la versión base del paquete.

required

Returns:

Type Description
dict[str, Any]

El config listo para BayesRiskConfig.model_validate (migrado si hacía falta).

Raises:

Type Description
ConfigError

Si schema_version no es una cadena SemVer válida.

ConfigVersionError

Si schema_version es mayor que la del paquete (config "del futuro").

MigrationNotFoundError

Si falta un migrador para completar algún salto de versión necesario.

migration

migration(from_version, to_version)

Registra un migrador puro dict -> dict para el salto from_version -> to_version.

Valida en import time la linealidad de la cadena: el destino avanza estrictamente sobre el origen y no existe ya otro migrador con el mismo origen (evita ciclos, pasos que no progresan y bifurcaciones que colgarían o desviarían :func:migrate).

Parameters:

Name Type Description Default
from_version str

Versiones SemVer de origen y destino del migrador.

required
to_version str

Versiones SemVer de origen y destino del migrador.

required

Returns:

Type Description
Callable[[Migrator], Migrator]

Decorador que registra la función en :data:_MIGRATORS y la devuelve intacta.

Raises:

Type Description
ConfigError

Si el destino no avanza sobre el origen, o si ya hay un migrador con ese origen.

Datos

Carga, validación de esquema, definición del target, particionado y hashing lógico del dataset (data_hash) que alimenta el lineage.

DataConfig

Bases: BayesRiskBaseConfig

Carga el dataset, valida su esquema, define el target y arma las particiones.

columnas_que_produce

columnas_que_produce()

Columnas que este paso añade al frame, y que las secciones de abajo pueden nombrar.

Las cuatro se escriben sin condición —DataStep.execute llama a TargetDefinition.apply y a Partitioner.split siempre (data/step.py:77-80)—, o sea que no hay rama que consultar: si esta sección corre, están.

🔴 Existen aquí porque el preflight compara contra el ARCHIVO y las secciones de abajo consumen la SALIDA de este paso. Medido: survival.input.event_col = "target" llega a done —el indicador de evento es el flag de malo, que es lo natural— y sin esta declaración el preflight lo acusaría de columna faltante. stability.temporal_column ya sufría lo mismo con tres valores alcanzables (D-RAM-6).

El import es perezoso por el ciclo: data/target.py y data/partition.py importan este módulo. Las constantes se toman de ellos y no se redeclaran: una constante duplicada que se mueva por un lado deja el preflight mintiendo por el otro, y este repo ya pagó una triplicada.

DataLoader

Carga el dataset crudo a pandas.DataFrame con copias defensivas.

from_config classmethod

from_config(cfg)

Construye un cargador desde DataConfig.load / LoadingConfig.

load

load(source=None, *, audit=None)

Carga source como DataFrame y devuelve una copia defensiva.

Parameters:

Name Type Description Default
source (str, Path, DataFrame or None)

Ruta CSV/Parquet/Excel (.xlsx) o DataFrame en memoria. Si es None, usa self.config.source; si ambos faltan, levanta DataValidationError. Excel solo se admite con backend='pandas'.

None
audit AuditSink or None

Reservado para la orquestación de DataStep; la carga no emite decisiones todavía.

None

Returns:

Type Description
DataFrame

Dataset cargado. Siempre es una copia nueva respecto de la fuente interna.

SchemaValidator

Valida columnas, tipos y reglas simples mediante pandera.

index_col se interpreta como el nombre del índice pandas ya existente: el validador no ejecuta set_index ni consume una columna ordinaria con ese nombre. Si el identificador vive como columna, debe declararse como ColumnSpec o en unique_keys; si vive en el índice, index_col exige que el índice tenga ese nombre y sea único.

from_config classmethod

from_config(cfg)

Construye un validador desde DataConfig.schema_ / SchemaConfig.

build_schema

build_schema()

Traduce SchemaConfig al contrato imperativo de pandera.

Returns:

Type Description
DataFrameSchema

Esquema listo para validar un DataFrame con backend pandas. El mapeo de tipos lógico→pandera es explícito: int→int64, float→float64, str→str, bool→bool, category→category y datetime→datetime64[ns].

validate

validate(df, *, audit=None)

Valida df y devuelve el DataFrame resultante de pandera.

Parameters:

Name Type Description Default
df DataFrame

Dataset a validar. No se muta in-place; si coerce=True pandera devuelve una copia con los tipos coaccionados.

required
audit AuditSink or None

Reservado para la orquestación de DataStep; la validación de esquema no emite decisiones todavía.

None

Returns:

Type Description
DataFrame

DataFrame validado, posiblemente coaccionado según ColumnSpec.coerce.

Raises:

Type Description
DataValidationError

Si pandera detecta incumplimientos. El mensaje agrega todos los fallos de failure_cases explicados en español: qué columna falta, qué tipo se esperaba o qué regla se incumplió. Es copy público, así que no transporta los literales de pandera (column_in_dataframe, not_nullable, in_range) ni el vocabulario de su volcado — los lee un usuario, no quien desarrolla la librería.

TargetDefinition

Deriva la etiqueta binaria desde reglas declarativas con precedencia explícita.

from_config classmethod

from_config(cfg)

Construye una definición desde DataConfig.target / TargetConfig.

apply

apply(df, *, audit=None)

Etiqueta df en una copia defensiva y devuelve el contenedor auditable.

Parameters:

Name Type Description Default
df DataFrame

Dataset validado sobre el que se evalúan las reglas de target. No se muta in-place.

required
audit AuditSink or None

Sumidero opcional para emitir eventos decision por exclusiones y ambigüedades.

None

Returns:

Type Description
LabeledFrame

Copia de df con target y label_status agregados, más resumen de clases.

Raises:

Type Description
ConfigError

Si una regla está vacía, referencia columnas inexistentes, usa un operador fuera de la allowlist o compara valores incompatibles con el dtype de la columna.

DataValidationError

Si la ventana declara fechas no datetime, si las columnas de salida colisionan con el input, o si el resultado queda sin buenos o sin malos.

Partitioner

Asigna particiones Dev/HO/OOT de forma estable por observación.

from_config classmethod

from_config(cfg)

Construye un particionador desde PartitionConfig.

split

split(lf, *, root_seed, rng, audit=None)

Particiona un LabeledFrame sin mutar el frame de entrada.

Parameters:

Name Type Description Default
lf LabeledFrame

Resultado de TargetDefinition.apply con columnas target y label_status.

required
root_seed int

Semilla raíz cruda: ancla la identidad estable por observación.

required
rng Generator

Generador derivado por core; reservado para sorteos auxiliares deterministas.

required
audit AuditSink or None

Sumidero opcional para emitir decisiones de estrategia y resumen.

None

Returns:

Type Description
PartitionResult

Copia del frame con partition categórico y ttd booleano.

Raises:

Type Description
ConfigError

Si la estrategia no existe en el factory local o su config es inconsistente.

DataValidationError

Si faltan columnas, hay particiones vacías o se viola el piso de malos.

suggest

suggest(lf)

Sugiere una PartitionConfig editable según señales temporales simples.

DataStep

Bases: AuditableMixin

Orquesta la secuencia canónica de datos y publica artefactos domain='data'.

from_config classmethod

from_config(cfg)

Construye DataStep desde BayesRiskConfig.data.

execute

execute(study, rng)

Ejecuta load → schema → special → target → partition → hash → artefactos.

metrics

metrics(study)

Publica el resumen métrico del dominio al namespace canónico (D-GOB-4).

Proyección directa de la card: los tres son escalares que DataCardSection ya declara, así que aquí no hay reducción que decidir. Sin metric_sections: data no tiene hoy payload estructurado CT-2, y fabricar uno para llenar el hueco sería inventar (D-GOB-5).

Análisis exploratorio (EDA)

Perfiles por variable, calidad de datos, tasa de incumplimiento en el tiempo y su estabilidad temporal, antes de modelar. Cómo se lee cada pieza —y qué hace el motor cuando el archivo no trae fecha— está en la guía Análisis exploratorio.

Eje, indicador, causas y marcas

En los resultados —JSON, tablas, model card— cada uno viaja como su identificador; en la pantalla, en el informe y en las guías se lee como su palabra. Son el mismo dato, y cada correspondencia tiene una sola fuente en bayesrisk.eda.

Identificador Palabra Qué es Fuente
period por fecha de observación Eje efectivo de la tasa (axis de la card) bayesrisk.eda.default_rate.AXIS_LABELS
cohort por cohorte Ídem; puede ser el efectivo aunque el config diga period (axis_inferred) ídem
cv variación relativa Indicador de estabilidad temporal bayesrisk.eda.stability.STABILITY_INDICATOR_LABELS
max_relative_drift peor desvío Ídem ídem
trend_slope tendencia Ídem ídem
eje_cohorte eje de cohorte, sin orden cronológico Causa de no evaluar la señal (stability_not_evaluable_reason) bayesrisk.eda.stability.NOT_EVALUABLE_REASON_LABELS
pocos_periodos_evaluables menos de dos períodos con observaciones suficientes Ídem ídem
tasa_media_cero sin incumplimientos en los períodos evaluables Ídem; sólo con un indicador relativo ídem
sin_eje_temporal el archivo no trae un eje temporal que ordenar Ídem; la tasa no se pudo agrupar, así que no hay serie que mirar ídem
tasa_no_calculable la tasa por período no se pudo calcular Ídem; el cálculo de la tasa falló, así que no hay serie que mirar ídem
no_calculable no se pudo calcular Ídem; la señal falló por sí sola y la tasa se conserva entera ídem
sin_eje_temporal el archivo no trae columna de fecha ni cohorte declarada Causa de no evaluar la tasa (default_rate_not_evaluable_reason): sin columna de fecha y sin cohorte declarada no hay eje, la tabla por período sale vacía y la corrida sigue bayesrisk.eda.default_rate.DEFAULT_RATE_NOT_EVALUABLE_REASON_LABELS
no_calculable no se pudo calcular Ídem, cuando el cálculo falló: la tabla sale vacía, la tasa global se conserva si hubo población y la causa del motor viaja en failed_analyses ídem
near_constant casi constante Marca de calidad por columna bayesrisk.eda.quality.QUALITY_FLAG_LABELS
near_unique casi única Ídem ídem
high_cardinality alta cardinalidad Ídem ídem

La regla que gobierna la causa es una sola: hay causa si y sólo si el indicador configurado no es finito; entonces stability_value viaja como null y stability_flagged es false. Cuando el archivo no trae columna de fecha y la partición es por cohorte, el eje se infiere a esa cohorte y la decisión eje_eda_inferido queda en el trail de la corrida.

EdaStep nunca detiene la corrida: la tasa por período, la señal temporal, los perfiles y la calidad fallan por separado, cada uno publica su versión vacía y el paso publica siempre sus seis artefactos. La card trae failed_analyses —sub-análisis (default_rate, stability, univariate, quality, figures) → causa del motor—, vacío en toda corrida sana; cada falla deja una decisión analisis_exploratorio_parcial en el trail, y en el canal de métricas lo que no se calculó se omite en vez de publicarse como cero. Una excepción que no sea EdaError también degrada, pero su causa lleva el tipo: «error inesperado del motor (<Tipo>): …». Las piezas —DefaultRateAnalyzer, UnivariateProfiler, DataQualityProfiler— usadas por código siguen levantando su EdaError de siempre. Lo que se dice de cada uno y la frase que lo redacta viven en bayesrisk.eda.card (FAILED_ANALYSIS_LABELS, failed_analysis_sentence).

EdaConfig

Bases: BayesRiskBaseConfig

Describe la cartera antes de modelar: tasa de incumplimiento, perfiles y calidad de datos.

UnivariateProfiler

Calcula perfiles descriptivos de features candidatas frente al target.

from_config classmethod

from_config(cfg)

Construye un profiler desde UnivariateConfig.

profile

profile(frame, *, target_col, columns, audit=None)

Calcula perfiles univariados sobre filas con target elegible.

Parameters:

Name Type Description Default
frame DataFrame

Dataset etiquetado por data o equivalente standalone.

required
target_col str

Columna binaria nullable: 1 malo, 0 bueno, <NA> no elegible.

required
columns tuple[str, ...]

Columnas candidatas a perfilar. Una tupla vacía produce resultado vacío.

required
audit AuditSink or None

Reservado para compatibilidad con la orquestación; este profiler puro no emite eventos auditables y no aplica muestreo.

None

Returns:

Type Description
UnivariateResult

Diccionario columna-tabla y, si se pidió, IV descriptivo pre-binning.

Raises:

Type Description
EdaError

Si faltan columnas requeridas, el frame está vacío o el índice no es único.

DataQualityProfiler

Calcula missing, cardinalidad y flags descriptivos por columna.

from_config classmethod

from_config(cfg)

Construye un profiler desde QualityConfig.

profile

profile(frame, *, audit=None)

Calcula el diagnóstico de calidad sin mutar el DataFrame de entrada.

Parameters:

Name Type Description Default
frame DataFrame

Dataset validado por data o equivalente standalone. Se diagnostican todas sus columnas.

required
audit AuditSink or None

Reservado para compatibilidad con la orquestación; este profiler puro no emite eventos auditables.

None

Returns:

Type Description
QualityResult

Tabla con una fila por columna y flags descriptivos de calidad.

Raises:

Type Description
EdaError

Si el frame está vacío o el índice no identifica observaciones de forma única.

DefaultRateAnalyzer

Calcula la tasa de default sobre la población elegible del target.

from_config classmethod

from_config(cfg)

Construye un analizador desde DefaultRateConfig.

compute

compute(frame, *, target_col, audit=None)

Calcula la tasa de default por período/cohorte sin mutar el input.

Parameters:

Name Type Description Default
frame DataFrame

Dataset etiquetado por data o equivalente standalone.

required
target_col str

Columna binaria nullable: 1 malo, 0 bueno, <NA> no elegible.

required
audit AuditSink or None

Reservado para compatibilidad con la orquestación; este analizador puro no emite eventos auditables.

None

Returns:

Type Description
DefaultRateResult

Tabla agregada ordenada y tasa global ponderada por elegibles.

Raises:

Type Description
EdaError

Si faltan columnas requeridas, el eje temporal es ambiguo/no datetime o no hay filas que describir.

TemporalStabilityAnalyzer

Bases: AuditableMixin

Evalúa la estabilidad temporal descriptiva de la tasa de default cruda.

from_config classmethod

from_config(cfg)

Construye un analizador desde TemporalStabilityConfig.

assess

assess(default_rate, *, audit=None)

Calcula CV, drift relativo extremo y pendiente OLS de la tasa de default.

Parameters:

Name Type Description Default
default_rate DefaultRateResult

Resultado de DefaultRateAnalyzer.compute con axis='period' y la tabla by_period ordenable temporalmente.

required
audit AuditSink or None

Sumidero opcional para registrar la decisión auditable de redesarrollo o no evaluabilidad.

None

Returns:

Type Description
StabilityResult

Indicadores descriptivos, métrica configurada, umbral y bandera de señal.

Raises:

Type Description
EdaError

Si by_period no contiene las columnas mínimas del contrato de B5.2.

Notes

Con una tasa que no se pudo agrupar —sin columna de fecha ni cohorte declarada, D-SC-17— la señal sale no evaluable con la causa sin_eje_temporal, que se mira antes que el eje: la tabla llega vacía y «menos de dos períodos» describiría el síntoma en vez de la causa.

Con axis="cohort" la señal temporal no se evalúa y no es un error (D-SC-2, SDD-27 §8): las cohortes no tienen un orden cronológico que el motor pueda inferir, así que el resultado sale con los tres indicadores NaN, flagged=False y la causa eje_cohorte, y el trail registra la decisión no_evaluable —el mismo tratamiento que «menos de dos períodos»—. Hasta la capa 3 del scorecard completo este caso levantaba EdaError y con él moría la corrida entera de eda, tasa por cohorte incluida.

La regla que gobierna la causa es una sola, y se prueba en los dos sentidos: hay causa si y sólo si el indicador configurado no es finito. «Tasa media cero» (§0-13) sólo aplica a los indicadores relativos —cv y max_relative_drift—; con trend_slope el indicador vale cero, es evaluable y no hay causa.

no_calculable

no_calculable()

La señal cuyo PROPIO cálculo falló (D-SC-19): no evaluable, sin decisión en el trail.

La decisión la registra el paso, que es quien atrapó la falla y conoce su causa; aquí sólo se construye el resultado con la forma de siempre —tres indicadores NaN, sin señal—.

EdaStep

Bases: AuditableMixin

Orquesta EDA y publica artefactos domain='eda' sin mutar data.

from_config classmethod

from_config(cfg)

Construye EdaStep desde BayesRiskConfig.eda.

execute

execute(study, rng)

Ejecuta default_rate → stability → univariate → quality → figures.

EdaStep sólo lee el dominio data y sólo escribe el dominio eda. Para particiones, lee ("data", "splits") de forma condicional cuando analysis_partition no es "todas"; esa clave no entra en requires por decisión de frontera documentada en el módulo.

🔴 Nunca levanta (D-SC-19). El análisis exploratorio es descriptivo y ninguna etapa del modelo lo necesita, así que un error aquí cuesta un sub-análisis, no la corrida: la preparación, la tasa por período, la estabilidad, los perfiles y la calidad fallan por separado, cada uno publica su versión vacía y su causa va a failed_analyses de la card, al trail y —como alerta— a las superficies. El paso publica siempre sus seis artefactos. Se atrapa cualquier excepción, pero una que no sea EdaError —un defecto del motor— se publica con su tipo, para que no quede escondida. Las piezas (DefaultRateAnalyzer, los perfiladores), usadas sueltas, siguen levantando.

metrics

metrics(study)

Publica el resumen métrico del dominio al namespace canónico (D-GOB-4, respuesta 6).

Proyección directa de la card: la tasa de incumplimiento observada, cuántos períodos o cohortes la componen y si la señal temporal quedó marcada. stability_flagged viaja como 1.0/0.0 porque el canal sólo admite float finito (D-GOB-2) y un bool lo rechaza como contrato roto; NaN en la tasa —sin elegibles— se omite, no se rellena.

Binning y WoE

Discretización supervisada con Weight of Evidence (WoE), monotonía controlada e IV (motor OptBinning tras el extra scoring).

BinningConfig

Bases: BayesRiskBaseConfig

Agrupa cada variable en tramos WoE y mide su poder predictivo con el IV.

requisitos_incumplidos_por_perfil

requisitos_incumplidos_por_perfil(perfil)

Invariantes que exigen mirar los DATOS, no sólo los nombres (D-PERF-3/4).

La invariante la declara aquí el dominio que la impone, igual que las de D-INV-1: es binning quien sabe que una columna de texto con casi un valor por fila no es un predictor.

El caso real que la motiva, medido con un CSV de cartera corriente: una columna id_operacion con un valor por fila entra por el comodín, OptBinning manda todas sus categorías al bin «otros», se queda sin ninguna y mata la corrida con un mensaje suyo, en inglés, que no nombra la columna. El paquete C ya dejó la salida —declararla en la llave de unicidad—; lo que faltaba era señalarla antes de pagar la corrida.

WoEBinner

Bases: TransformerMixin, BaseEstimator, BayesRiskTransformer

Wrapper sklearn-like sobre optbinning.BinningProcess para scorecard.

from_config classmethod

from_config(cfg)

Construye WoEBinner desde BinningConfig excluyendo el discriminador type.

fit

fit(X, y, *, special=None, sample_weight=None, audit=None)

Ajusta bins supervisados WoE/IV sin mutar X, y ni special.

Si el corte de categorías raras deja un solo nivel por debajo y ese grupo unitario queda sin una de las dos clases, la columna se reajusta una vez con el menor corte que deja dos niveles debajo (D-RAR-1). El intento y la reagrupación van a audit como dos decisiones —la primera antes de reajustar, la segunda sólo si el reajuste resuelve—, y el corte efectivo queda en rare_category_regroupings_.

Si un bin Missing o Special con observaciones queda sin una de las dos clases y su WoE es el empírico, se le asigna el del tramo regular de mayor tasa de malos observada de la misma variable —el de menor WoE; ante un empate, la primera fila—, con IV 0 en su fila (D-FAL-1). Cada asignación va a audit y a assigned_bins_, y la transformación usa ese mismo WoE.

Raises:

Type Description
BinningFitError

Si el target no es binario con ambas clases, si todas las variables son no binneables, si OptBinning no alcanza un estado aceptable, si alguna tabla publica WoE infinito o si un bin conserva una clase en cero —también tras el único reintento de D-RAR-1, con un mensaje que dice qué se intentó y qué salidas hay—.

transform

transform(X)

Transforma variables crudas a columnas WoE usando bins fiteados previamente.

transform_bins

transform_bins(X)

Publica la etiqueta congelada de cada bin sin recalcular cortes ni WoE.

fit_transform

fit_transform(X, y, **kwargs)

Ajusta el binner y devuelve el woe_frame para el mismo X.

BinningResult

Bases: BaseModel

Contenedor agregado de las salidas principales de binning.

BinningStep

Bases: AuditableMixin

Orquesta binning supervisado WoE/IV y publica artefactos domain='binning'.

from_config classmethod

from_config(cfg)

Construye BinningStep desde BayesRiskConfig.binning.

execute

execute(study, rng)

Ejecuta fit en Desarrollo y transform determinista sin consumir rng.

rng se recibe por el protocolo homogéneo de Step; binning v1 no introduce muestreo ni azar propio. La reproducibilidad depende de la matriz fija de datos/config/OptBinning.

metrics

metrics(study)

Publica el resumen métrico del dominio al namespace canónico (D-GOB-4).

Los dos conteos que describen qué pudo binnearse. El IV por variable NO entra: es un mapa por variable, no un escalar del modelo, y aplanarlo publicaría una clave por columna en cada model card. Sin metric_sections (D-GOB-5).

Selección de variables

Filtrado pre-modelo por IV, correlación, VIF y estabilidad.

Motivos y bandas de IV

Cada variable candidata sale con un motivo (decisions[].reason) y con la banda diagnóstica de su IV (decisions[].iv_band). Igual que con las bandas de estabilidad, el identificador es el dato y la palabra es lo que se lee en pantalla y en el informe; las fuentes únicas son bayesrisk.selection.results.REASON_LABELS y bayesrisk.binning.results.IV_BAND_LABELS.

Motivo Palabra
included inclusión
business_include inclusión forzada de negocio
business_exclude exclusión de negocio
low_iv IV insuficiente
high_iv IV excesivo (posible fuga)
low_auc AUC insuficiente
low_ks KS insuficiente
low_gini Gini insuficiente
high_correlation correlación excesiva
high_vif VIF excesivo
cluster_representative_lost no ser representante de su clúster
constant_or_nonfinite ser constante o no finita
missing_binning_artifact faltar su artefacto de binning
forced_conflict conflicto entre reglas forzadas
high_stability inestabilidad temporal
Banda de IV Palabra
none sin poder
weak débil
medium medio
strong fuerte
suspicious sospechoso

SelectionConfig

Bases: BayesRiskBaseConfig

Filtra las variables WoE candidatas por IV, correlación, VIF y estabilidad PSI/CSI.

FeatureSelector

Bases: TransformerMixin, BaseEstimator, BayesRiskTransformer

Selector sklearn-like de columnas WoE para scorecard.

from_config classmethod

from_config(cfg)

Construye FeatureSelector desde SelectionConfig y sus sub-configs.

fit

fit(
    woe_frame,
    *,
    target_col,
    partition_col,
    binning_summary,
    woe_column_map,
    audit=None,
)

Ajusta filtros de selección sobre Desarrollo sin mutar artefactos de entrada.

transform

transform(woe_frame)

Filtra el frame WoE a columnas estructurales y variables seleccionadas.

fit_transform

fit_transform(woe_frame, **kwargs)

Ajusta la selección y devuelve el frame WoE filtrado para el mismo input.

SelectionResult

Bases: BaseModel

Contenedor agregado de las salidas principales de selection.

SelectionStep

Bases: AuditableMixin

Orquesta selección pre-modelo y publica artefactos domain='selection'.

from_config classmethod

from_config(cfg)

Construye SelectionStep desde BayesRiskConfig.selection.

execute

execute(study, rng)

Ejecuta fit en Desarrollo y transform determinista sin consumir rng.

rng se recibe por el protocolo homogéneo de Step; selection v1 no introduce muestreo ni azar propio. La reproducibilidad depende de datos, config y versiones instaladas.

metrics

metrics(study)

Publica el resumen métrico del dominio al namespace canónico (D-GOB-4).

max_abs_correlation_after_selection es opcional en la card —sin pares que comparar no hay máximo— y se publica None para que el núcleo lo OMITA en vez de rellenarlo con 0.0, que leería como «cero correlación» cuando lo cierto es «no se pudo evaluar». Sin metric_sections (D-GOB-5).

Modelo (regresión logística PD)

Regresión logística sobre variables WoE con stepwise, política de signos e inferencia (statsmodels).

ModelConfig

Bases: BayesRiskBaseConfig

Ajusta la regresión logística de PD sobre las variables WoE seleccionadas.

LogisticPDModel

Bases: ClassifierMixin, BaseEstimator, BayesRiskClassifier

Modelo logístico PD sobre columnas WoE seleccionadas.

from_config classmethod

from_config(cfg)

Construye LogisticPDModel desde ModelConfig y sus sub-configs.

fit

fit(
    X,
    y,
    *,
    feature_names,
    woe_columns,
    iv_by_feature,
    audit=None,
    sample_weight=None,
)

Ajusta la logística PD y el stepwise usando sólo filas de Desarrollo.

decision_function

decision_function(X)

Devuelve el predictor lineal preservando índice y orden de entrada.

predict_pd

predict_pd(X)

Devuelve PD cruda P(target=1) preservando el índice original.

predict_proba

predict_proba(X)

Devuelve probabilidades [P(good), P(bad)] con el orden de entrada.

predict

predict(X)

Clasifica con umbral fijo 0.5; la calibración formal vive en SDD-10.

ModelResult

Bases: BaseModel

Contenedor agregado de artefactos publicados por la capa model.

ModelStep

Bases: AuditableMixin

Orquesta ajuste logístico PD y publica artefactos domain='model'.

from_config classmethod

from_config(cfg)

Construye ModelStep desde BayesRiskConfig.model.

execute

execute(study, rng)

Ejecuta fit en Desarrollo y predicción PD determinista sin consumir rng.

rng se recibe por el protocolo homogéneo de Step; model v1 no introduce muestreo ni azar propio. La reproducibilidad depende de datos, config y versiones instaladas.

metrics

metrics(study)

Publica el resumen métrico del dominio al namespace canónico (D-GOB-4).

Sólo el tamaño del modelo final. Los estadísticos de ajuste viven en ModelFitStatistics y son un DTO, no escalares del namespace: su lugar es metric_sections cuando SDD-08 declare qué va dentro.

metric_sections

metric_sections(study)

Publica el payload estructurado CT-2 de la card, sin aplanar (D-GOB-3).

Scorecard

Traducción de coeficientes a puntajes enteros (escala PDO / target odds), con overrides y redondeo controlado.

ScorecardConfig

Bases: BayesRiskBaseConfig

Traduce el log-odds del modelo a puntos de scorecard.

direccion_del_score_declarada

direccion_del_score_declarada()

Declara con qué orientación esta sección construye el puntaje (D-DIR-5).

Es el protocolo METODO_CONVENCION_SCORE del preflight, por convención de nombre y no por herencia, igual que requisitos_incumplidos. Existe para que el núcleo no tenga que leer config.scorecard.score_direction: con la sección opaca —el estado por defecto— ese atributo sería una clave de dict, y el núcleo pasaría a conocer el vocabulario de un dominio, que es justo lo que D-INV-1 rechazó.

Quien la construye es quien la declara: scorecard es la única sección que fabrica el puntaje (scaler.py:536-553 decide el signo de cada punto con este valor). performance y stability sólo lo miden, y por eso preguntan en vez de declarar.

PointsScaler

Bases: BayesRiskTransformer

Escala componentes log-odds de una logística WoE a puntos de scorecard.

from_config classmethod

from_config(cfg)

Construye PointsScaler desde ScorecardConfig excluyendo type.

fit

fit(
    *,
    coefficients,
    final_features,
    final_woe_columns,
    binning_tables,
    woe_column_map,
    audit=None,
    assigned_bins=None,
    bin_edges=None,
)

Deriva puntos por bin desde coeficientes y tablas WoE sin mutar entradas.

assigned_bins nombra, por variable, los bins auxiliares cuyo WoE asignó el binning (D-FAL-1). Comparten los puntos de su tramo de referencia —la primera fila con su mismo WoE, la que usa la búsqueda de puntos—: heredan su ajuste manual y no admiten uno propio.

bin_edges son los bordes efectivos que publica binning (D-CPY-3): con ellos, un ajuste manual de puntos casa con la etiqueta del motor o con el rótulo legible que muestran las tablas. Un ajuste que no casa con ninguno se declara en el trail (point_override_sin_casar); antes se ignoraba en silencio.

transform

transform(woe_frame)

Publica columnas de puntos y score total desde un frame WoE ya validado.

Scorecard

Bases: PointsScaler, TransformerMixin, BaseEstimator

Transformer sklearn-like que publica puntos por variable y score total.

fit_from_artifacts

fit_from_artifacts(
    *,
    model_result=None,
    binning_result=None,
    coefficients=None,
    final_features=None,
    final_woe_columns=None,
    binning_tables=None,
    woe_column_map=None,
    audit=None,
)

Ajusta el scorecard desde DTOs de model/binning o artefactos explícitos.

ScorecardResult

Bases: BaseModel

Contenedor agregado de artefactos publicados por la capa scorecard.

ScorecardStep

Bases: AuditableMixin

Orquesta el escalamiento log-odds a puntos y publica domain='scorecard'.

from_config classmethod

from_config(cfg)

Construye ScorecardStep desde BayesRiskConfig.scorecard.

emit

emit(event)

Permite pasar el step como AuditSink a PointsScaler.

execute

execute(study, rng)

Ejecuta scorecard determinista sin consumir rng y publica cuatro artefactos.

metrics

metrics(study)

Publica el resumen métrico del dominio al namespace canónico (D-GOB-4).

Sólo el tamaño de la tarjeta. pdo, target_score, factor y offset son PARÁMETROS de escalamiento elegidos por la institución, no resultados medidos: publicarlos como «métricas del modelo» es justamente el error que D-GOB-4 evita.

metric_sections

metric_sections(study)

Publica el payload estructurado CT-2 de la card, sin aplanar (D-GOB-3).

Calibración

Ajuste de la PD cruda a un ancla de negocio (through-the-cycle), con tope de offset auditable.

CalibrationConfig

Bases: BayesRiskBaseConfig

Ajusta la PD cruda del modelo a una tasa central de anclaje aprobada.

PDCalibrator

Bases: BayesRiskTransformer

Calibra PD cruda de una logística a una tasa central.

from_config classmethod

from_config(cfg)

Construye PDCalibrator desde CalibrationConfig excluyendo type.

fit

fit(raw_pd_frame, *, audit=None)

Ajusta parámetros de calibración usando sólo filas de Desarrollo.

transform

transform(raw_pd_frame)

Aplica la calibración fiteada y publica las ocho columnas canónicas.

fit_transform

fit_transform(raw_pd_frame, *, audit=None)

Ajusta el calibrador y devuelve el frame calibrado para la misma entrada.

CalibrationResult

Bases: BaseModel

Contenedor agregado de artefactos publicados por la capa calibration.

CalibrationStep

Bases: AuditableMixin

Orquesta la calibración de PD cruda y publica domain='calibration'.

from_config classmethod

from_config(cfg)

Construye CalibrationStep desde BayesRiskConfig.calibration.

emit

emit(event)

Permite pasar el step como AuditSink si un motor futuro lo requiere.

execute

execute(study, rng)

Ejecuta calibration determinista sin consumir rng y publica cuatro artefactos.

metrics

metrics(study)

Publica el resumen métrico del dominio al namespace canónico (D-GOB-4).

El ancla objetivo y las dos tasas que permiten juzgar si la calibración la alcanzó. Sin las tres juntas, calibrated_mean_pd_dev no dice nada por sí sola.

metric_sections

metric_sections(study)

Publica el payload estructurado CT-2 de la card, sin aplanar (D-GOB-3).

Desempeño

Métricas de discriminación (AUC/KS/Gini) y desempeño por decil, por partición.

PerformanceConfig

Bases: BayesRiskBaseConfig

Mide el desempeño del modelo ya ajustado: AUC, Gini, KS y tablas de gains por partición.

requisitos_incumplidos

requisitos_incumplidos(columnas)

Invariantes que el evaluador exige y que sólo se descubrían corriendo (D-INV-1).

No dependen del dataset —columnas va sin usar—, pero el protocolo la recibe igual porque el comprobador no sabe de antemano qué necesita cada dominio.

requisitos_incumplidos_por_contexto

requisitos_incumplidos_por_contexto(contexto)

Avisa si esta sección mide el puntaje al revés de como se construyó (D-DIR-5).

🔴 Es el defecto más caro que este repo ha medido, y no fallaba: publicaba. Con la tarjeta construida en un sentido y el desempeño midiendo en el otro, la corrida llega a done y el informe publica Gini -0,424 —un modelo con la discriminación invertida— con el validador, check_pipeline, check_dataset y la corrida los cuatro en verde y cero avisos.

Se avisa aunque hoy el valor sea inerte. Medido: la orientación sólo entra al cálculo con evaluation_source='score'; con la fuente por defecto no cambia ningún número. Callar en ese caso dejaría la contradicción escrita, publicada en la ficha del informe y lista para volverse mortal en cuanto alguien cambie la fuente con dos clicks — que es exactamente el camino por el que se llegó al Gini invertido.

PerformanceEvaluator

Bases: AuditableMixin, BaseBayesRiskEstimator

Calcula métricas discriminantes y deciles/gains para score o PD calibrada.

from_config classmethod

from_config(cfg)

Construye el evaluador desde PerformanceConfig excluyendo metadatos de schema.

evaluate

evaluate(
    frame,
    *,
    score_column,
    pd_column,
    target_column,
    partition_column,
)

Evalúa AUC/Gini/KS y tabla de deciles por partición.

Parameters:

Name Type Description Default
frame DataFrame

Frame analítico post-modelo con score, PD calibrada, target y partición.

required
score_column str

Columna del score operacional.

required
pd_column str

Columna de PD calibrada post-modelo.

required
target_column str

Columna target binaria, con 1 como default.

required
partition_column str

Columna que identifica desarrollo, holdout y oot.

required

Returns:

Type Description
PerformanceResult

DTO agregado con performance_table, discriminant_metrics, records y card.

PerformanceResult

Bases: BaseModel

Contenedor agregado de artefactos publicados por la capa performance.

PerformanceStep

Bases: AuditableMixin

Orquesta desempeño post-modelo y publica domain='performance'.

from_config classmethod

from_config(cfg)

Construye PerformanceStep desde BayesRiskConfig.performance.

emit

emit(event)

Permite pasar el step como AuditSink si un motor futuro lo requiere.

execute

execute(study, rng)

Ejecuta performance determinista sin consumir rng y publica cuatro artefactos.

metrics

metrics(study)

Publica el resumen métrico del dominio al namespace canónico (D-GOB-4).

🔴 Aquí hay REDUCCIÓN, no proyección: AUC, Gini y KS no son campos escalares de PerformanceCardSection —el único escalar declarado es n_deciles—, sino que viven en max_metrics_by_partition, un dict por partición. Se publica una clave por partición y métrica, auc_<partición>, porque colapsar las particiones a un número exigiría elegir cuál manda y esa elección es institucional, no del motor.

Una partición not_evaluable —cartera corta, sin ambas clases— trae None y el núcleo la OMITE. Es el caso real de una cartera pequeña, y publicar 0.0 ahí diría «AUC de 0.0», que es peor que no decir nada.

metric_sections

metric_sections(study)

Publica el payload estructurado CT-2 de la card, sin aplanar (D-GOB-3).

Estabilidad

PSI/CSI y estabilidad temporal del puntaje y de las características.

Bandas de estabilidad

Cada comparación se clasifica en una banda, y la banda fija de forma única la acción auditada. En los resultados —JSON, psi_table, stability_metrics, model card— la banda viaja como su identificador; en la pantalla, en el informe y en las guías se lee como su palabra. Son el mismo dato: la fuente única de la correspondencia es bayesrisk.stability.results.BAND_LABELS.

Identificador Palabra Acción auditada
stable Estable none
review Revisar vigilar
redevelop Redesarrollar redesarrollar
not_evaluable No evaluable none

El resumen de cada comparación publica juntos el peor PSI entre score y PD, la identidad de la magnitud ganadora (score_psi → «score», pd_psi → «PD calibrada», en bayesrisk.stability.results.PSI_METRIC_LABELS) y la banda de esa misma magnitud.

StabilityConfig

Bases: BayesRiskBaseConfig

Mide la estabilidad del score y de la PD calibrada con PSI y CSI.

requisitos_incumplidos

requisitos_incumplidos(columnas)

Invariantes que esta sección impone y que la corrida rechazaría (D-INV-1).

No son validaciones de forma —de eso se encarga _check_invariantes— sino exigencias sobre la combinación de campos y sobre el dataset, que hasta ahora sólo se descubrían pagando la corrida entera: el caso de origen de la enmienda moría en el paso 8 de 10 con el preflight y check_pipeline en verde.

requisitos_incumplidos_por_contexto

requisitos_incumplidos_por_contexto(contexto)

Avisa si esta sección describe el puntaje al revés de como se construyó (D-DIR-5).

⚠️ Aquí la consecuencia no es un número invertido: es un documento que se contradice. Medido, el motor de estabilidad no lee este campo en ningún cálculo —PSI y CSI comparan distribuciones binadas y son invariantes al signo—; el valor viaja del config a la ficha y de ahí al informe. Con la respuesta contraria a la de la tarjeta, el mismo documento afirma dos orientaciones distintas del mismo puntaje, y el lector no tiene cómo saber cuál rige.

requisitos_de_recalculo_declarados

requisitos_de_recalculo_declarados()

Qué artefactos leerá quien recalcule el PSI con esta sección (D-VAL-16; CT-1).

Lo consume el resolver del núcleo por convención de nombre (core.steps.METODO_REQUISITOS_RECALCULO) para armar el contexto con que validation declara su requires cuando apaga consume_stability: el recálculo reutiliza el ensamblador del paso de estabilidad, y lo que ese ensamblador lee lo deciden estos campos, que el paso de validación no puede mirar al construirse (D-INV-1, D-REQ-2).

Es la misma lista que compute_stability lee de verdad, con la exigencia conservadora que la enmienda declara como límite de CT-1: data.frame siempre que haya eje temporal —el ensamblador lo abre sólo si el score no trae la columna, y eso se sabe en ejecución—, y binning.bin_frame sólo con CSI por bins WoE. La ficha del scorecard no va aquí: se lee si está y no se exige (optional_requires del paso que recalcula).

StabilityEvaluator

Bases: AuditableMixin, BaseBayesRiskEstimator

Calcula PSI del score/PD, CSI por característica y estabilidad temporal post-modelo.

from_config classmethod

from_config(cfg)

Construye el evaluador desde StabilityConfig excluyendo metadatos de schema.

evaluate

evaluate(
    frame,
    *,
    score_column,
    pd_column,
    partition_column,
    feature_point_columns,
)

Evalúa PSI del score/PD, CSI por característica y estabilidad temporal por partición.

Parameters:

Name Type Description Default
frame DataFrame

Frame analítico post-modelo con score, PD calibrada, partición, columnas <feature>__points y, si aplica, la columna de período/cohorte.

required
score_column str

Columna del score operacional.

required
pd_column str

Columna de PD calibrada post-modelo, estrictamente en (0, 1).

required
partition_column str

Columna que identifica desarrollo, holdout y oot.

required
feature_point_columns Sequence[str]

Columnas <feature>__points cuya distribución de puntos alimenta el CSI.

required

Returns:

Type Description
StabilityResult

DTO agregado con psi_table, stability_metrics, records y card.

StabilityResult

Bases: BaseModel

Contenedor agregado de artefactos publicados por la capa stability.

StabilityStep

Bases: AuditableMixin

Orquesta estabilidad post-modelo y publica domain='stability'.

from_config classmethod

from_config(cfg)

Construye StabilityStep desde BayesRiskConfig.stability.

emit

emit(event)

Permite pasar el step como AuditSink si un motor futuro lo requiere.

execute

execute(study, rng)

Ejecuta stability determinista sin consumir rng y publica cuatro artefactos.

El cálculo entero —ensamblar el frame y correr el evaluador— vive en :func:compute_stability, que es también lo que llama validation cuando recalcula el PSI (D-VAL-16): un solo camino, sin duplicar la alineación.

metrics

metrics(study)

Publica el resumen métrico del dominio al namespace canónico (D-GOB-4).

worst_psi es una REDUCCIÓN de max_psi_by_comparison (un dict por comparación): el peor caso es lo que gobierna la conclusión de estabilidad, y es la única forma de publicar un escalar sin elegir por la institución qué comparación importa. Sin ninguna comparación evaluable no hay peor caso, y la clave se omite en vez de valer 0.0 —que leería como «estabilidad perfecta», la lectura exactamente opuesta a la verdadera—.

metric_sections

metric_sections(study)

Publica el payload estructurado CT-2 de la card, sin aplanar (D-GOB-3).

Validación

Backtesting y pruebas regulatorias de discriminación, calibración y estabilidad (familias de tests). Cómo se lee el resultado —y qué hace un validador con él— está en la guía Validación formal.

Estado técnico y veredictos

En los resultados —JSON, tablas tidy, model card— cada estado viaja como su identificador; en la pantalla y en el informe se lee como su palabra. Son el mismo dato, y su correspondencia tiene una sola fuente: bayesrisk.validation.results.

Identificador Palabra Dónde aparece
pass Pasa Estado técnico agregado de la corrida
warn Revisar Ídem
fail Falla Ídem
not_evaluable No evaluable Ídem: ninguna prueba dejó un veredicto de pasa o falla y la estabilidad no dejó una decisión. La falta de potencia es una causa posible, no la única: también sale con sólo el puntaje de Brier, con sólo discriminación o con las pruebas de pasa o falla apagadas
pass Pasa Veredicto de una fila de calibración o de backtesting
fail Falla Ídem
not_evaluable Sin veredicto Ídem: sin potencia estadística, o una fila que no es una prueba de pasa/falla (el puntaje de Brier)
partition_below_min / group_below_min / degenerate_group / non_finite_statistic la muestra quedó bajo el mínimo de operaciones / un grupo de PD quedó bajo el mínimo de operaciones / un grupo de PD quedó sin variabilidad / el estadístico no fue finito con PD extremas Por qué un Hosmer-Lemeshow quedó sin veredicto (not_evaluable_reason); la card las enumera en metric_sections.validation.not_evaluable_partitions
green / amber / red Verde / Ámbar / Rojo Semáforo de un grado de rating
stability_artifact / recomputed Reusado de la etapa de estabilidad / Recalculado en esta etapa De dónde salió cada fila de la tabla de estabilidad (source); la card lo repite en metric_sections.validation.stability_source y, si se recalculó, dice con qué receta en stability_recompute (declared, la sección de estabilidad; minimal, sin eje temporal ni bins)

El estado técnico es evidencia del motor, no el veredicto sobre el modelo: aprobar, aprobar con observaciones o rechazar es una decisión de quien valida, y el informe lo declara explícitamente.

Familias y sus tablas

Identificador Palabra Tabla que publica
discrimination Discriminación Una fila por partición: población, AUC, Gini, KS, origen y estado
calibration Calibración Hosmer-Lemeshow y puntaje de Brier por partición, y el contraste por grado
stability Estabilidad El PSI de cada magnitud y comparación, con su banda
backtesting Backtesting Un contraste realizado-vs-estimado por parámetro y segmento

Los grados sin potencia estadística no entran en la tabla de calibración ni en el conteo de pruebas: viajan aparte, en card.metric_sections.validation.not_evaluable_grades, con sus conteos y el mínimo técnico que los dejó fuera. Un Hosmer-Lemeshow sin veredicto sí está en la tabla —con statistic nulo y su causa— pero tampoco cuenta: n_tests y n_failed cuentan sólo las decisiones evaluables de las cuatro familias.

ValidationConfig

Bases: BayesRiskBaseConfig

Valida el modelo con calibración y backtesting, y lo resume en un semáforo.

columnas_inactivas

columnas_inactivas()

La subsección entera de cada familia que no corre (D-RAM-1 + D-SUB-1).

🔴 Es la primera declaración del repo que nombra SUBMODELOS y no columnas sueltas, y hace falta porque la condición vive un nivel arriba de los campos que apaga: quien decide si la calibración lee grade_col no es binomial_by_grade sino, antes que él, families. Medido en evaluator.py::validate: cada familia entra por if "<familia>" in self.families, así que una familia deseleccionada no abre ninguna columna aunque sus flags queden encendidos — y quedan, porque deseleccionar una familia no los apaga.

El preflight poda el campo y su subárbol cuando el padre lo declara inactivo (dataset_check.py::_declaraciones, D-SUB-1), que es exactamente lo que hace falta aquí.

Las cuatro familias se llaman igual que sus cuatro sub-configs, y eso no es casualidad sino el contrato que un gate fija: una familia nueva sin su sub-config —o al revés— haría que este método suprimiera de más o de menos, en silencio.

requisitos_incumplidos

requisitos_incumplidos(columnas)

Invariantes que el evaluador exige y que sólo se descubrían corriendo (D-INV-1).

families vacío es el caso caro: el campo no tiene min_length, _check_validation sólo mira la coherencia backtesting↔enabled, y validation corre penúltimo en el F1 — así que un if de una línea tumbaba la corrida con todo el cómputo ya pagado.

ValidationEvaluator

Orquesta las familias de validación activas y consolida un :class:ValidationResult (§4).

from_config classmethod

from_config(cfg)

Construye ValidationEvaluator desde BayesRiskConfig.validation.

validate

validate(
    *,
    calibrated_pd=None,
    performance_metrics=None,
    stability_metrics=None,
    stability_source="stability_artifact",
    stability_recompute=None,
    ifrs9_detail=None,
    realised=None,
    model_ref="validation",
)

Ejecuta las familias activas en la secuencia canónica §7 y publica el resultado tidy.

calibrated_pd es el frame analítico común (§6): partition/target/ pd_calibrated/grade (nombres por config.calibration). Los artefactos consumidos (performance_metrics/stability_metrics) y los insumos de backtesting (ifrs9_detail/realised) se pasan tal cual; el evaluador copia todo en profundidad. stability_metrics llega siempre como un stability_metrics de SDD-11: el que publicó el paso de estabilidad (stability_source="stability_artifact") o el que el paso de validación recalculó con compute_stability ("recomputed", con la receta en stability_recompute; D-VAL-16). El evaluador no recalcula: sólo proyecta y publica la procedencia en la tabla y en la card. model_ref identifica el modelo validado en la card. Levanta un :class:~bayesrisk.validation.exceptions.ValidationConfigError si no hay familias activas o si una brecha crítica gatilla con fail_on_falta_dato=True.

ValidationResult

Bases: BaseModel

Contenedor agregado de los artefactos publicados por la capa validation (§4/§6).

ValidationStep

Bases: AuditableMixin

Orquesta la validación avanzada y publica domain='validation'.

from_config classmethod

from_config(cfg)

Construye ValidationStep desde BayesRiskConfig.validation (firma histórica).

Sin contexto, la ruta de recálculo declara los requires de la receta mínima y :meth:execute exige lo efectivo antes de calcular (D-REQ-4): un run_step('validation') con sección declarada que necesite data.frame o binning.bin_frame y no los tenga falla al entrar a execute con la clave exacta, no a mitad de cálculo.

from_config_with_context classmethod

from_config_with_context(cfg, *, contexto)

Fábrica contextual del resolver (D-FX-2): declara el requires de ESTA invocación.

Tercer implementador del hook. Con consume_stability=False lee contexto.requisitos_de_recalculo['stability'] y distingue tres estados (D-VAL-16): clave ausente → la sección no está declarada y el recálculo usará la receta mínima, así que se declaran sus dos claves y nada más; None → la sección está declarada pero no se pudo coaccionar, y como execute va a releerla el paso se detiene aquí, en el preflight, con ConfigError (check_pipeline lo acusa antes de ejecutar ningún paso); tupla → lo declarado. Es una precisión sobre D-REQ-4, no una excepción: degradar al default es correcto cuando el paso conserva el contrato que declararía solo; aquí va a leer esa sección, y un config inválido no puede pasar la comprobación previa.

emit

emit(event)

Permite pasar el step como AuditSink si un motor futuro lo requiere.

execute

execute(study, rng)

Ejecuta la validación determinista sin consumir rng y publica seis artefactos.

Backends ML

Modelos GBDT (XGBoost, LightGBM, CatBoost), random forest y SVM como extras selectivos, con monotonía y comparación challenger frente al scorecard.

MLConfig

Bases: BayesRiskBaseConfig

Entrena un challenger de machine learning que reta al scorecard campeón.

Compite sobre los mismos datos que el campeón.

contrato_de_variables_declarado

contrato_de_variables_declarado()

Publica de dónde salen las variables del challenger en ESTA corrida (D-REQ-3).

Lo consume el resolver del núcleo por convención de nombre (core.steps.METODO_CONTRATO_VARIABLES) para armar el contexto con que tuning y explain calculan su requires. Los dos pasos ajustan el mismo modelo que esta sección describe, así que leen artefactos distintos según lo que aquí se decida: con feature_source='selection_woe' el WoE lo publica selection, no binning.

🔴 Existe para que el núcleo no tenga que conocer estos dos campos. Podría leer config.ml.feature_source en dos líneas, y sería el acoplamiento que D-INV-1 rechazó: con la sección opaca —el estado por DEFECTO— eso es una clave de dict y el núcleo pasaría a depender del vocabulario de este dominio. Aquí el núcleo transporta un mapa de str cuyas claves no interpreta; quien las lee es quien las necesita.

⚠️ Son dos campos y no uno: hasta D-REQ-3, tuning declaraba binning.tables/binning.result, que sólo consume con monotonic.mode 'from_binning': con 'off' exigía dos artefactos que nunca lee.

🔴 data_raw NO se publica, y salió al implementar. Es una fuente diferida: el motor la rechaza siempre con FALTA-DATO-ML-1, nombrando la carencia y las dos salidas. Publicarla hacía que el paso declarase ('data','frame') como prerequisito duro, y entonces el DAG cortaba antes con «necesita 'frame', que produce 'data'» — un mensaje cierto y mucho peor, sobre un config que el motor iba a rechazar de todos modos. Omitirla no es declarar de menos: un paso con data_raw no llega a correr nunca, así que sus requisitos son irrelevantes y lo único que importa es cuál de los dos errores se lee.

MLResult

Bases: BaseModel

Contenedor agregado de los artefactos publicados por la capa ml (SDD-12 §4/§6).

term_structure

term_structure()

Retorna None: el challenger ML no publica estructura temporal (CT-2, SDD-12 §9).

A diferencia de IFRS 9/forward, ml produce una PD escalar por observación, no una curva multi-período; alimenta a report/governance por card + metric_sections.

comparison_frame

comparison_frame()

Materializa el tidy de :class:MLComparisonRecord (SDD-12 §6).

Preserva el orden de los registros (el MLStep los produce en el orden de config de particiones y métricas). Importa pandas de forma perezosa para no romper el import liviano de bayesrisk.ml.

MLStep

Bases: AuditableMixin

Orquesta el challenger ML y publica domain='ml' (SDD-12 §4/§7).

from_config classmethod

from_config(cfg)

Construye MLStep desde BayesRiskConfig.ml.

emit

emit(event)

Permite pasar el step como AuditSink si un motor futuro lo requiere.

execute

execute(study, rng)

Entrena, predice, compara, (opcional) calibra, audita y publica siete artefactos (§7).

Tuning de hiperparámetros

Optimización del espacio de búsqueda (Optuna) con muestreadores/pruners deterministas.

TuningConfig

Bases: BayesRiskBaseConfig

Busca con Optuna los hiperparámetros del challenger definido en ml.

resolve_search_space

resolve_search_space(ml_config)

Resuelve el espacio de búsqueda efectivo contra el backend de ml (SDD-13 §5).

tuning hereda el backend de ml (no lo duplica): un ml ausente impide tunear (:class:~bayesrisk.tuning.exceptions.TuningConfigError). Con search_space vacío devuelve default_search_space(ml.backend); si el usuario declaró claves, cada una debe ser un hiperparámetro del params-model del backend y su kind debe casar con el tipo del campo (:class:~bayesrisk.tuning.exceptions.TuningSearchSpaceError).

TuningResult

Bases: BaseModel

Contenedor agregado de los artefactos publicados por la capa tuning (SDD-13 §4/§6).

term_structure

term_structure()

Retorna None: el tuning no publica estructura temporal (CT-2, SDD-13 §9).

A diferencia de IFRS 9/forward, tuning produce hiperparámetros escalares y una curva de optimización, no una curva multi-período; alimenta a report/governance por card + metric_sections.

trials_frame

trials_frame()

Materializa el tidy de :class:TuningTrialRecord (SDD-13 §6).

Columnas number, param_<hiperparámetro> (unión estable en orden de aparición), value y state, en el orden de ejecución de los trials. Importa pandas de forma perezosa para no romper el import liviano de bayesrisk.tuning.

TuningStep

Bases: AuditableMixin

Orquesta la búsqueda de hiperparámetros y publica domain='tuning' (SDD-13 §4/§7).

from_config classmethod

from_config(cfg)

Construye TuningStep desde BayesRiskConfig.tuning (firma histórica).

from_config_with_context classmethod

from_config_with_context(cfg, *, contexto)

Fábrica contextual del resolver (D-FX-2): declara el requires de ESTA invocación.

Segundo implementador del hook, y la razón de que su contexto dejara de ser un frozenset[str]: saber que selection corre no basta —lo que decide qué artefactos lee este paso es qué eligió ml, no qué secciones existen— (D-REQ-2).

emit

emit(event)

Permite pasar el step como AuditSink si un motor futuro lo requiere.

execute

execute(study, rng)

Busca θ* con Optuna, valida invariantes, audita y publica siete artefactos (§7).

Explicabilidad

Explicaciones globales/locales (SHAP opcional) y reason codes para scorecard y modelos ML.

ExplainConfig

Bases: BayesRiskBaseConfig

Explica cada decisión con el aporte del scorecard, valores SHAP y reason codes.

ExplainResult

Bases: BaseModel

Contenedor agregado de los artefactos publicados por explain (SDD-14 §4/§6).

term_structure

term_structure()

Retorna None: la explicación no publica estructura temporal (CT-2, SDD-14 §9).

A diferencia de IFRS 9/forward, explain atribuye una predicción escalar por observación, no una curva multi-período; alimenta a report/governance por card + metric_sections.

global_frame

global_frame()

Materializa el tidy de :class:ShapGlobalRecord (SDD-14 §6).

Preserva el orden de los registros (el step los produce descendente por mean_abs_contribution con desempate lexicográfico). Importa pandas de forma perezosa para no romper el import liviano de bayesrisk.explain.

reason_codes_frame

reason_codes_frame()

Explota los reason codes a un tidy (observación · factor) (SDD-14 §6).

Recorre reason_codes (la vista top-N de shap_local) preservando el orden de las observaciones y, dentro de cada una, el orden por rank. Importa pandas de forma perezosa.

ExplainStep

Bases: AuditableMixin

Orquesta la explicabilidad unificada y publica domain='explain' (SDD-14 §4/§7).

from_config classmethod

from_config(cfg)

Construye ExplainStep desde BayesRiskConfig.explain (histórica, standalone).

from_config_with_context classmethod

from_config_with_context(cfg, *, contexto)

Fábrica contextual del resolver (D-FX-2): declara el requires de ESTA invocación.

emit

emit(event)

Permite pasar el step como AuditSink si un motor futuro lo requiere.

execute

execute(study, rng)

Explica ML (SHAP) y/o scorecard (analítico), audita y publica siete artefactos (§7).

Survival

Modelos de tiempo-a-evento: Kaplan-Meier, hazard discreto y Cox/AFT (algunos tras extra).

SurvivalConfig

Bases: BayesRiskBaseConfig

Modela el tiempo hasta el incumplimiento y obtiene de ahí la PD lifetime.

requisitos_incumplidos

requisitos_incumplidos(columnas)

Lo que esta sección se exige a sí misma y detiene la corrida al final (D-INV-1).

🔴 El caso es caro y era invisible: con los dos campos de la grilla en su default, el motor cae a los tiempos observados, emite DATO-INSTITUCIONAL-SUR-1 y —como fail_on_falta_dato viene en True— aborta en step.py:637-643, después de cargar el archivo, ajustar el modelo y calcular la term-structure. Medido con corridas reales: los cuatro métodos abortan, porque el fallback lo resuelve el paso y no cada motor.

Va en esta clase y no en las sub-secciones porque la condición necesita fail_on_falta_dato y method, que viven aquí. Es el mismo criterio por el que el gate del motor está en _card_from_model y no dentro de un motor.

⚠️ fail_on_falta_dato es parte de la condición, no un detalle: con él apagado la corrida llega a done y registra el aviso, así que avisar ahí sería un falso positivo —y el mensaje, que dice que la corrida se detendrá, sería literalmente falso—.

SUR-2 queda fuera con su razón medida: depende del CONTENIDO (todos censurados), no del config, y este protocolo sólo recibe nombres de columna.

SurvivalStep

Bases: AuditableMixin

Orquesta modelos survival y publica domain='survival'.

from_config classmethod

from_config(cfg)

Construye SurvivalStep desde BayesRiskConfig.survival.

emit

emit(event)

Permite pasar el step como AuditSink a los modelos survival.

execute

execute(study, rng)

Ejecuta survival determinista sin consumir rng y publica siete artefactos.

Cadenas de Markov

Estimación de matrices de transición y estructura temporal de PD por estados.

MarkovConfig

Bases: BayesRiskBaseConfig

Estima matrices de transición y la curva de PD lifetime desde un panel de migraciones.

MarkovStep

Bases: AuditableMixin

Orquesta matrices Markov y publica domain='markov'.

from_config classmethod

from_config(cfg)

Construye MarkovStep desde BayesRiskConfig.markov.

emit

emit(event)

Permite pasar el step como AuditSink sin exponer el sink interno.

execute

execute(study, rng)

Ejecuta Markov determinista sin consumir rng y publica siete artefactos.

Forward-looking

Proyección macroeconómica, modelos satélite y escenarios ponderados para PD point-in-time.

ForwardConfig

Bases: BayesRiskBaseConfig

Proyecta la PD con variables macroeconómicas y convierte entre PD PIT y PD TTC.

ForwardResult

Bases: BaseModel

Contenedor agregado de artefactos publicados por la capa forward.

term_structure

term_structure()

Retorna la term-structure forward-looking tidy o None si no existe.

Cumple CT-2: SDD-16 puede consumir esta salida sin que forward importe ni instancie el motor ECL. pandas se importa perezosamente aquí para mantener liviano import bayesrisk.forward.results.

ForwardStep

Bases: AuditableMixin

Orquesta forward-looking y publica domain='forward'.

from_config classmethod

from_config(cfg)

Construye ForwardStep desde BayesRiskConfig.forward.

emit

emit(event)

Permite pasar el step como AuditSink sin exponer el sink interno.

execute

execute(study, rng)

Ejecuta el flujo forward determinista y publica las diez claves del dominio.

Stress testing

Escenarios de shock, barridos de sensibilidad y reverse stress sobre las métricas de provisión.

StressConfig

Bases: BayesRiskBaseConfig

Aplica escenarios de stress, sensibilidad y reverse stress sobre la cartera.

StressResult

Bases: BaseModel

Contenedor agregado de artefactos publicados por la capa stress.

term_structure

term_structure()

Retorna la term-structure estresada tidy o None si no fue publicada.

Cumple CT-2: SDD-16/17 y reportes pueden consumir esta salida cuando existe. pandas se importa perezosamente aquí para mantener liviano import bayesrisk.stress.results.

scenarios

scenarios()

Retorna una copia de la tabla pública de escenarios/shocks aplicados.

tidy

tidy()

Retorna una copia de la tabla de impactos de stress.

StressStep

Bases: AuditableMixin

Orquesta stress testing severo y publica domain='stress'.

from_config classmethod

from_config(cfg)

Construye StressStep desde BayesRiskConfig.stress.

emit

emit(event)

Permite pasar el step como AuditSink sin exponer el sink interno.

execute

execute(study, rng)

Ejecuta el stress determinista y publica las nueve claves del dominio.

Provisiones

Dos marcos de provisión —IFRS 9/ECL y método interno (exposición por la tasa de pérdida del grupo, descompuesta en PD · LGD o provista directamente; jurisdiccionalmente neutro)— más una capa fina de orquestación que compara dos metodologías y aplica la regla declarada. El motor CMF (Chile) documentado más abajo es el caso de referencia de cómo se aterriza una norma local sobre esa base; su alcance y su fecha de verificación están en Aterrizar una norma local.

Sobre la regla del máximo

La regla del máximo del Capítulo B-1 (Circular N° 2.346 / 06.03.2024) es entre el método estándar de la CMF y el método interno del banco, y se aplica "para cada institución en Chile que consolida con el banco". No es un máximo entre la provisión CMF y el ECL de IFRS 9: el Compendio (Cap. A-2, num. 5) excluye el modelo de deterioro de NIIF 9 sobre las colocaciones y los créditos contingentes, porque esos criterios los define la propia CMF en B-1 a B-3. El comparativo CMF↔IFRS 9 que expone esta capa es un comparativo entre marcos contables (útil, por ejemplo, para reportar a una matriz extranjera), no una exigencia de la CMF.

ProvisioningConfig

Bases: BayesRiskBaseConfig

Compara dos fuentes de provisión configurables y aplica la regla declarada.

La regla del máximo del Cap. B-1 (Circular N° 2.346) es entre el método estándar de la CMF y el método interno del banco, por institución; comparar contra IFRS 9 es un contraste entre marcos contables, no la exigencia local.

sources property

sources

Par ordenado de dominios comparados (source_a, source_b).

consume_source_a property

consume_source_a

Consumo efectivo de la fuente A (el flag deprecado de su dominio manda si se informó).

consume_source_b property

consume_source_b

Consumo efectivo de la fuente B (el flag deprecado de su dominio manda si se informó).

portfolio_col_for

portfolio_col_for(source)

Columna de cartera declarada para el detail de la fuente indicada.

ProvisioningOrchestrator

Compara dos fuentes de provisión y aplica la regla declarada por celda (SDD-17 §6/§7).

from_config classmethod

from_config(cfg)

Construye el orquestador desde BayesRiskConfig.provisioning (revalida si aplica).

compare

compare(*, result_a, result_b, as_of_date, audit=None)

Aplica la regla (max / use_internal) por celda, determinista.

result_a y result_b son los resultados publicados por cfg.source_a y cfg.source_b respectivamente (posicionales por ranura, no por motor).

ProvisionOrchestrationResult

Bases: BaseModel

Contenedor agregado del comparativo de dos fuentes de provisión (SDD-17 §4/§6).

term_structure

term_structure()

Retorna la curva ECL de IFRS 9 (CT-2) o None si IFRS 9 no es fuente (SDD-17 §4).

Delega en la curva larga que IfrsProvisionResult.term_structure() publicó y que el orchestrator guardó en ifrs9_term_structure; la expone como copia defensiva. No fabrica una term-structure de la provisión reportada (que es escalar por celda): si IFRS 9 no participa retorna None — ni el CMF ni el método interno publican curva (D-CORE-7).

ProvisioningStep

Bases: AuditableMixin

Orquesta dos fuentes de provisión bajo la regla declarada (domain='provisioning').

from_config classmethod

from_config(cfg)

Construye ProvisioningStep desde BayesRiskConfig.provisioning.

emit

emit(event)

Permite pasar el step como AuditSink al orquestador (SDD-17 §9).

execute

execute(study, rng)

Aplica la regla a las dos fuentes sin usar rng y publica cuatro artefactos.

Motor CMF

CmfProvisioningConfig

Bases: BayesRiskBaseConfig

Calcula la provisión regulatoria CMF (Cap. B-1 y B-3) con el bundle de matrices versionado.

El bundle activo se elige en matrices.active_version.

Motor experimental: fuera de la garantía SemVer 2.x.

CmfProvisioningEngine

Calcula provisiones CMF B-1/B-3 con garantías verificadas o fail-fast.

from_config classmethod
from_config(cfg)

Construye el motor y carga las matrices CMF activas por config.

calculate
calculate(frame, *, pd_frame=None, as_of_date, audit=None)

Calcula detalle, resumen y card CMF preservando orden e índice del input.

CmfProvisionResult

Bases: BaseModel

Contenedor agregado de artefactos publicados por provisioning.cmf.

term_structure
term_structure()

Retorna None en CMF B-1 agregado, cumpliendo CT-2/D-CORE-7.

El modelo estándar CMF B-1 publica provisión agregada y por operación, no una curva lifetime ni una estructura multi-período. SDD-17 usa summary/card para comparar el método estándar con la fuente configurada; no fabrica una curva para CMF.

Motor IFRS 9 / ECL

IfrsProvisioningConfig

Bases: BayesRiskBaseConfig

Calcula las provisiones contables IFRS 9: staging y pérdida esperada (ECL).

Motor experimental: fuera de la garantía SemVer 2.x.

requisitos_incumplidos
requisitos_incumplidos(columnas)

Lo que esta sección se exige a sí misma y la corrida rechazará (D-INV-1).

🔴 El caso es el config DE FÁBRICA, y por eso importa tanto. Medido: los tres defaults —curva de survival, modo «ya viene a condiciones actuales» y escenarios de forward— construyen sin un solo error y revientan al calcular, porque las dos columnas que esas dos elecciones exigen —la marca de curva ajustada al momento y el peso de escenario— las publica únicamente forward: cero apariciones en survival/ y en markov/. Quien entra por el trabajo «Provisiones IFRS 9» recibe ese esqueleto; el preset F4 no lo sufre porque fija los tres a mano, o sea que el árbol ya sabía que los defaults no corren.

Va aquí y no en cada sub-sección porque la condición cruza dos de ellas: scenarios.source no puede juzgarse sin mirar pd.term_structure_source, que vive en su hermana. Es el mismo criterio con que la invariante de survival vive en la clase que ve method y el flag.

⚠️ No es un model_validator, y es deliberado. Las tres combinaciones son alcanzables y legítimas para quien inyecta su propia curva por código con esas columnas puestas; cerrarlas al construir mataría ese uso. Aquí se avisa (D-PRE-5, D-INV-3) y el motor sigue siendo la autoridad sobre sí mismo.

columnas no se usa: la exigencia es entre campos del config, no sobre el dataset.

IfrsProvisioningEngine

Motor económico IFRS 9 que orquesta la secuencia canónica de la ECL (SDD-16 §7).

from_config classmethod
from_config(cfg)

Construye el motor desde IfrsProvisioningConfig (molde hermano from_config).

calculate
calculate(
    frame,
    *,
    term_structure,
    calibrated_pd=None,
    as_of_date,
    audit=None,
)

Calcula la ECL IFRS 9 por operación y ensambla el :class:IfrsProvisionResult.

Parameters:

Name Type Description Default
frame DataFrame

DataFrame económico (exposición/drawn/límite, dpd, EIR, rating, LGD/recovery, flags). No se muta (copia defensiva).

required
term_structure DataFrame

Term-structure tidy lifetime PD del proveedor configurado (survival/markov/forward), con al menos row_id/period/time_value/pd_marginal. No se muta.

required
calibrated_pd DataFrame | None

PD 12m anclada por SDD-10 (columna pd_calibrated); obligatoria sólo cuando pd.base_pd_source='calibration'.

None
as_of_date str

Fecha de cálculo/cierre contable de la provisión (texto no vacío).

required
audit AuditSink | None

Sink de auditoría opcional (el step orquestador registra las decisiones de §9).

None

Returns:

Type Description
IfrsProvisionResult

Contenedor con staging/detail/ecl_term_structure/summary, los registros por operación y la card CT-2.

Raises:

Type Description
IfrsTermStructureError

Si la term-structure incumple el contrato tidy o sus invariantes.

IfrsConfigError

Si el modo PIT, la fuente de PD base o la fuente de escenarios exige insumos ausentes.

IfrsInputError

Si faltan columnas raíz del frame o los identificadores no son únicos/alineables.

MissingDependencyError

Si falta numpy o pandas.

IfrsProvisionResult

Bases: BaseModel

Contenedor agregado de artefactos publicados por provisioning.ifrs9 (SDD-16 §4).

term_structure
term_structure()

Retorna la term-structure de ECL en forma larga CT-2; nunca es None en IFRS 9.

Apila ecl_term_structure (ancho por componente) en la forma larga [row_id, scenario, period, time_value, component, value] que consumen SDD-17 y los reportes. Los componentes se preservan en orden canónico dentro de cada (row_id, scenario, period) y -0.0 se normaliza a 0.0.

Gobernanza

Model card (SR 11-7), inventario de modelos y registro de escenarios/overlays. Es la superficie de trazabilidad que run ensambla y (opcionalmente) publica al inventario.

GovernanceConfig

Bases: BayesRiskBaseConfig

Documenta el modelo para su gobierno: model card, inventario y diario de overlays.

Cambiar el propósito, los metadatos de inventario o la política de publicación no altera los resultados de la corrida ni su config_hash; el cambio queda registrado en el model card y en el audit-trail.

ModelCard

Bases: BaseModel

Ficha auditable del modelo, serializable a JSON canónico y markdown.

to_json

to_json()

Serializa el model card a JSON canónico para diff/auditoría.

to_markdown

to_markdown()

Renderiza una versión markdown estable del model card.

ModelCardBuilder

Ensambla un :class:ModelCard desde un Study finalizado y su trail.

build

build(study, *, trail_path=None)

Construye el model card desde lineage, resultados, artefactos y audit-trail.

ModelInventory

Bases: Protocol

Protocol SR 11-7 que SDD-04 implementa sobre MLflow Registry.

register debe ser idempotente por la ancla (model_name, nikodym.config_hash). Si el backend no soporta Registry, la implementación levanta RegistryUnavailableError.

register

register(entry)

Registra una entrada y devuelve el identificador de versión.

get_active

get_active(model_name)

Devuelve la versión activa del modelo, si existe.

list_versions

list_versions(model_name)

Lista las versiones conocidas del modelo.

NullInventory

Inventario no-operativo para publish_to_inventory=False.

register

register(entry)

No registra nada y devuelve cadena vacía por no-op consciente.

get_active

get_active(model_name)

Sin backend, no hay versión activa.

list_versions

list_versions(model_name)

Sin backend, no hay versiones.

InventoryEntry

Bases: BaseModel

Entrada completa que una implementación de inventario debe registrar.

publish_inventory

publish_inventory(entry, *, inventory=None)

Publica una entrada usando el inventario inyectado o NullInventory.

La resolución publish_to_inventory=True + extra tracking vive fuera de este módulo (B3.1c, assemble_run). Aquí solo se aplica el no-op explícito cuando el llamador entrega inventory=None.

ScenarioLog

Diario append-only de escenarios y overlays en JSONL canónico.

log_scenario

log_scenario(rec)

Añade un escenario al JSONL append-only.

log_overlay

log_overlay(rec)

Añade un overlay al JSONL, rechazando justificación vacía si fue manipulada.

read

read()

Lee y revalida todo el scenario_log en orden de escritura.

Auditoría, lineage y reproducibilidad

Audit sink JSONL, captura del entorno y hashing determinista de datos/archivos, más la relectura del trail para reconstruir la corrida.

AuditConfig

Bases: BayesRiskBaseConfig

Controla el audit-trail de la corrida y el snapshot del entorno de ejecución.

JsonlAuditSink

Sink que persiste el audit-trail a un archivo JSONL append-only.

emit

emit(event)

Serializa event como una línea JSON canónica y la añade al trail.

close

close()

Cierra el archivo de forma idempotente.

EnvironmentSnapshot

Bases: BaseModel

Registro serializable del entorno que acompaña a una corrida.

capture_environment

capture_environment(
    *,
    packages=None,
    uv_lock_path=None,
    now=None,
    version_provider=None,
    python_version_provider=None,
    platform_provider=None,
)

Captura versiones, plataforma, Python y hash de uv.lock.

Los proveedores son inyectables para que los tests fijen golden values exactos sin depender del entorno real del desarrollador.

hash_dataframe

hash_dataframe(df, *, algo='sha256')

Delegación perezosa al data_hash canónico de SDD-02.

hash_file

hash_file(path, *, algo='sha256')

Calcula el hash hexadecimal de un fichero leído por bloques.

read_trail

read_trail(path)

Lee todo el trail JSONL y devuelve una lista de AuditEvent revalidados.

iter_trail

iter_trail(path)

Itera eventos del trail, descartando líneas finales corruptas por crash.

Tracking (MLflow)

Registro opcional de corridas y modelos en un backend externo (MLflow), tras el extra correspondiente.

TrackingConfig

Bases: BayesRiskBaseConfig

Registra la corrida en MLflow y publica el modelo en el Model Registry.

Cambiar la URI, el experimento o la política de logging no altera los resultados de la corrida ni su config_hash, así que apuntar a otro destino no duplica versiones en el inventario.

TrackingRecorder

Frontera MLflow: traduce un Study ejecutado a un run auditable.

start_run

start_run(study, *, run_name=None)

Abre un run MLflow y devuelve un handle con sus identificadores.

ensure_run

ensure_run(*, run_name=None)

Abre un run si aún no existe; lo usa TrackingSink con eventos de core.

end_run

end_run(*, status='FINISHED')

Cierra el run activo si existe; doble cierre es no-op.

log_config

log_config(config)

Loguea params computacionales y tags de identidad del config.

log_metrics

log_metrics(results, *, step=None)

Loguea métricas finitas como metrics y el resto como results.json.

log_lineage

log_lineage(bundle)

Loguea lineage como tags de búsqueda y artefacto JSON.

log_study_dir

log_study_dir(path)

Adjunta el directorio serializado del Study bajo study/.

log_artifact_file

log_artifact_file(path, *, artifact_path=None)

Adjunta un fichero de artefacto al run activo.

register_model

register_model(model_uri, *, name=None, tags=None)

Registra un modelo vía el atajo MLflow de bajo nivel.

Con un Registry no respaldado por DB devuelve None + warning; el contrato regulatorio ruidoso vive en MLflowInventory.register.

snapshot_study

snapshot_study(study)

Guarda temporalmente el Study y adjunta su directorio si la config lo permite.

TrackingSink

Implementa AuditSink enrutando eventos del Study hacia TrackingRecorder.

emit

emit(event)

Procesa un evento de auditoría sin levantar hacia core por defecto.

MLflowInventory

Inventario SR 11-7 respaldado por MLflow Model Registry.

register

register(entry)

Registra entry idempotentemente por (model_name, config_hash).

get_active

get_active(model_name)

Devuelve la versión apuntada por el alias champion, si existe.

list_versions

list_versions(model_name)

Lista versiones rehidratadas desde tags del Registry.

list_models

list_models()

Lista modelos registrados con conteo y última versión.

get_version

get_version(name, version)

Lee una versión exacta; ausente levanta ModelNotFoundError.

latest_version

latest_version(name, *, alias=None)

Devuelve versión por alias o la última numérica; None si no existe.

Reportería

Reporte auditable del scorecard: ensamblado del bundle, render HTML/PDF y narración opcional (regla o IA).

ReportConfig

Bases: BayesRiskBaseConfig

Genera el informe auditable de la corrida y elige sus formatos de salida en formats.

ReportBuilder

Ensambla el documento lógico desde cards/results; no renderiza.

from_config classmethod

from_config(cfg)

Construye ReportBuilder desde BayesRiskConfig.report.

collect

collect(study)

Recolecta cards, tablas, figuras, parámetros y lineage en un snapshot defensivo.

build_sections

build_sections(bundle)

Construye el documento: capítulos, subsecciones de dominio y anexos.

El orden y los títulos salen de :data:~bayesrisk.report.document.CHAPTER_SPECS; la numeración (1-6 para capítulos, A/B/C para anexos) se deriva aquí, de modo que omitir un dominio no deja huecos en el índice.

Un capítulo con requires_domain informado es condicional: se omite entero si ese dominio no publicó card. La numeración se reajusta sola, porque se deriva de los capítulos efectivamente emitidos y no de la posición en CHAPTER_SPECS.

build_manifest

build_manifest(bundle, *, path)

Ensambla metadatos pre-render; el renderer completa el sha256 real.

HtmlReportRenderer

Render HTML standalone determinístico con Jinja2.

from_config classmethod

from_config(cfg)

Construye HtmlReportRenderer desde BayesRiskConfig.report.

render

render(bundle, *, ai_blocks=())

Renderiza HTML standalone byte-determinístico desde el bundle lógico.

build_manifest

build_manifest(html)

Construye el manifiesto HTML canónico sin escribir archivos.

write

write(html, *, output_dir)

Escribe el HTML en disco y devuelve un manifiesto reproducible.

PdfReportRenderer

Render opcional a PDF vía WeasyPrint sobre el HTML básico primario.

from_config classmethod

from_config(cfg)

Construye PdfReportRenderer desde BayesRiskConfig.report.

render

render(bundle, *, output_dir)

Renderiza y escribe el HTML básico y, si procede, un PDF opcional en disco.

El HTML determinístico es el artefacto primario: se escribe siempre y su manifest es el valor de retorno (igual que hoy con la ruta HTML). Con pdf.enabled se genera además un PDF con WeasyPrint (import perezoso) que se escribe como efecto secundario en {basename}.pdf y NO se refleja en el manifest. Si WeasyPrint no está disponible degrada a HTML (fail_if_unavailable=False) o re-lanza la dependencia ausente (True).

write_pdf_from_html

write_pdf_from_html(html, *, output_dir)

Escribe el PDF desde un HTML ya renderizado; devuelve su Path o None al degradar.

Recibe el HTML primario (que puede incluir la narrativa IA) y produce el PDF con WeasyPrint (import perezoso), sin re-renderizar el HTML. Degrada con gracia según pdf.fail_if_unavailable: en ausencia de WeasyPrint re-lanza la dependencia (True) o emite RuntimeWarning y devuelve None (False). En éxito escribe {basename}.pdf y devuelve el Path real en disco.

El warning propaga el diagnóstico de :func:~bayesrisk.report.pdf.render_pdf, que distingue "falta el paquete" de "el paquete está pero no encuentra sus nativas". Un texto genérico ("WeasyPrint no está disponible") describía mal el segundo caso —el más común en macOS y Windows, donde pip install bayesrisk[pdf] sí instaló WeasyPrint— y dejaba al usuario reinstalando un paquete que ya tenía.

ReportResult

Bases: _ReportBaseModel

Contenedor agregado publicado como salida final de la capa report.

md_path class-attribute instance-attribute

md_path = None

Ruta del .qmd (Quarto/Markdown): la fuente editable del informe, no un artefacto terminal. El analista escribe su contexto y sus conclusiones encima y compila su documento.

data_exports class-attribute instance-attribute

data_exports = Field(default_factory=dict)

{nombre de archivo: ruta real} de los adjuntos de datos (tablas por observación completas, ver :mod:bayesrisk.report.exports). Vacío si no se pidió csv ni xlsx.

ReportStep

Bases: AuditableMixin

Orquesta el reporte canónico F1 y publica domain='report'.

from_config classmethod

from_config(cfg)

Construye ReportStep desde BayesRiskConfig.report (firma histórica).

from_config_with_context classmethod

from_config_with_context(cfg, *, contexto)

Fábrica contextual del resolver (D-FX-2): recibe el contexto de ESTA invocación.

Study._resolve_step la prefiere sobre :meth:from_config cuando existe. Es la extensión genérica del resolver, no un caso especial de report: cualquier dominio cuyo contrato dependa de la invocación puede exponerla, y el que no la exponga no cambia.

⚠️ report sólo usa dominios_activos, que es lo que el contexto ya traía cuando era un frozenset a secas (D-REQ-2). Lo que cambió es la forma: el DTO permitió que otro paso necesitara más sin obligar a éste a enterarse.

emit

emit(event)

Permite pasar el step como AuditSink si un motor futuro lo requiere.

execute

execute(study, rng)

Ejecuta report determinístico sin consumir rng y publica tres artefactos.

Datasets y presets (helpers)

Utilidades para el quickstart y la UI: materialización determinista de datasets sintéticos, ingesta de uploads y el config F1 curado (standard_preset).

materialize

materialize(dataset_id, *, workdir)

Materializa un dataset a parquet determinista bajo workdir y lo cachea.

Deja además su perfil de columnas al lado (D-PERF-1), igual que :func:ingest_upload con un archivo subido: los datasets del catálogo no tienen por qué ser los únicos sobre los que el preflight no puede avisar de una columna identificador. Aquí también sale gratis —el generador ya devuelve el DataFrame—, y en la rama de caché lo repone :func:_asegurar_perfil.

Parameters:

Name Type Description Default
dataset_id str

Identificador del dataset. Un id uploaded_<token> resuelve el parquet ya materializado por :func:ingest_upload; en otro caso es la clave del registro sintético. Uno desconocido (o un upload no encontrado) levanta UiDatasetError.

required
workdir Path

Directorio de trabajo local; el parquet vive en workdir/datasets/<id>.parquet.

required

Returns:

Type Description
Path

Ruta del parquet materializado (o el cacheado si ya existía).

Raises:

Type Description
UiDatasetError

Si el dataset_id es desconocido, un upload no está materializado, o la ruta escaparía del workdir (path traversal).

list_datasets

list_datasets()

Devuelve el catálogo estable de datasets sintéticos.

Returns:

Type Description
list of dict

Un descriptor por dataset con id/name/description/columns/ index_columns/n_rows. Cada entrada de las dos listas trae name/dtype/ role y, desde D-COL-7, values con sus valores ofrecibles. El orden es estable (orden de inserción del registro), de modo que el listado no cambia entre corridas.

``index_columns`` va **aparte** desde D-PRO-1: el índice no es una columna, y publicarlo dentro
de ``columns`` hacía que la interfaz lo ofreciera donde el motor no puede leerlo. Un campo con
``column_role: "index"`` ofrece esta lista; uno con ``"input"``, la otra.
No depende del ``workdir``: estos datasets son sintéticos deterministas, así que sus valores
son una propiedad del catálogo y no de una materialización concreta.

ingest_upload

ingest_upload(
    content, filename, *, workdir, max_bytes=None
)

Ingesta un dataset propio subido y lo materializa a parquet canónico bajo workdir.

Valida tamaño/formato, lee el archivo con pandas según su extensión (.csv/.xlsx/ .parquet) y lo materializa en workdir/datasets/uploaded_<token>.parquet (token = sha256 del contenido: determinista ⇒ el mismo archivo reusa su parquet cacheado). Devuelve el dataset_id más un preview de columnas. Es domain-agnostic: no importa bayesrisk.data; el cableado de data.load.source ocurre luego en :func:bayesrisk.ui.routes.run_pipeline, dejando intacta la byte-identidad del config canónico (SDD-23 §9, §11).

Parameters:

Name Type Description Default
content bytes

Bytes crudos del archivo subido.

required
filename str

Nombre original; su sufijo (.csv/.xlsx/.parquet) determina el lector pandas.

required
workdir Path

Directorio de trabajo local; el parquet vive en workdir/datasets/uploaded_<token>.

required

Returns:

Type Description
dict

{dataset_id, name, n_rows, columns} con columns = lista de {name, dtype}.

Raises:

Type Description
UiDatasetError

Si el archivo está vacío, supera max_bytes, su formato no está admitido, no se puede leer con pandas o no contiene filas/columnas de datos.

standard_preset

standard_preset()

Devuelve el descriptor del preset estándar F1 (config curado + dataset recomendado).

Returns:

Type Description
dict

{id, name, description, config, dataset_id}: un config F1 completo y JSON-able (copia defensiva, no el literal compartido) alineado a las columnas del dataset sintético consumo_comportamiento. El config valida con BayesRiskConfig.model_validate y corre end-to-end produciendo un scorecard; dataset_id es el dataset recomendado para materializar y ejecutar la corrida (SDD-23 §3.2/§5).

Extras opcionales

Introspección de extras instalados e imports perezosos con error accionable cuando falta una dependencia opcional.

has_extra

has_extra(extra, *modules)

Devuelve True si todos los modules del extra están importables (sin levantar).

require_extra

require_extra(extra, *modules)

Importa y devuelve los módulos de un extra; si falta uno, levanta MissingDependencyError.

Parameters:

Name Type Description Default
extra str

Nombre del extra (clave de [project.optional-dependencies]), usado en el mensaje de instalación.

required
*modules str

Nombres de módulos importables a resolver (p. ej. "xgboost").

()

Returns:

Type Description
tuple of module

Los módulos importados, en el mismo orden.

Raises:

Type Description
MissingDependencyError

Si alguno de los módulos no se puede importar.

Examples:

>>> xgb, = require_extra("xgboost", "xgboost")