{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "# Primera LGD con historia separada\n\n**Disponibilidad:** requiere bayesrisk 2.17.0 o posterior; PyPI 2.16.0 no incluye estas puertas. Confirma la versión disponible en [PyPI](https://pypi.org/project/bayesrisk/#history). Las salidas conservan su [candidato de verificación original](https://github.com/nexolabs-gh/bayesrisk/actions/runs/39523257538), artefacto `candidate-distributions-with-evidence`; CI vuelve a ejecutar el cuaderno y coteja sus resultados.\n\nRecorrido experimental; requiere `bayesrisk[scoring,excel]`. Datos inventados incluidos en el paquete: 400 operaciones, 300 train, 80 evaluation y 20 abiertas excluidas. Dos operaciones por deudor dentro de una muestra; ningún deudor cruza las muestras elegibles. Objetivo en [0,1] con extremos 0 y 1 y dos covariables numéricas crudas. Las abiertas conservan objetivo vacío.\n\nLa institución debe declarar población, disponibilidad y muestras antes del ajuste. El motor no verifica suficiencia semántica ni temporalidad. Las métricas y la media de referencia son descriptivas; no validan calidad ni transportabilidad.\n\n## Ajustar y evaluar\n\nLos seis roles no se infieren. El ID de operación se declara por separado. Sólo train ajusta el modelo; evaluation no cambia sus coeficientes.",
   "id": "h3-lgd-0"
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": "from pathlib import Path\n\nimport pandas as pd\n\nfrom bayesrisk import Lgd, Provision\nfrom bayesrisk.ui.datasets import materialize\n\nhistoria = materialize(\"lgd_historia_sintetica\", workdir=Path(\"datos\"))\nlgd = Lgd(historia, target=\"lgd_observada\", features=[\"deuda_ingreso\", \"antiguedad_meses\"],\n          entity=\"deudor\", sample=\"muestra\", default=\"incumplio\", resolved=\"resuelto\",\n          id=\"loan_id\", purpose=\"Demostrar el flujo con datos inventados\",\n          assumptions=[\"Historia sintética con muestras y resultado declarados\"],\n          limitations=[\"No valida calidad ni transportabilidad\"], formats=[\"csv\", \"xlsx\"])\nlgd.run(raise_on_error=True)\nlgd.summary(\"lgd_training\")",
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": "── Historia de operaciones ──\nArchivo: datos/datasets/lgd_historia_sintetica.parquet (copia en bayesrisk-runs/lgd/input/data-<hash>.parquet)\n400 filas · 7 columnas\nIdentificador: loan_id (índice del archivo)\nSe conserva toda la historia; las exclusiones se cuentan antes del ajuste\nEvidencia de la corrida: bayesrisk-runs/lgd/run\n── Entrenamiento LGD ──\n300 operaciones de entrenamiento · 80 de evaluación\n20 operaciones excluidas, conservadas en la historia\n2 covariables crudas; respuesta fraccional con intercepto\nSólo entrenamiento ajusta el predictor y la media de referencia\nLas métricas describen la muestra; no certifican calidad ni transportabilidad\n⚠ Declaración aportada; suficiencia y temporalidad no verificadas\n⚠ Propósito: Demostrar el flujo con datos inventados\nSupuestos: Historia sintética con muestras y resultado declarados\nLimitaciones: No valida calidad ni transportabilidad\n⚠ Procesos abiertos excluidos; representatividad y ausencia de sesgo de selección no demostradas\n── Informe y ficha ──\nInforme HTML: bayesrisk-runs/lgd/reports/lgd_report.html\nFicha del modelo: bayesrisk-runs/lgd/run/model_card.json\nRegistro de auditoría: bayesrisk-runs/lgd/run/audit_trail.jsonl\nEjecución: completada\n"
    },
    {
     "output_type": "execute_result",
     "execution_count": 1,
     "metadata": {},
     "data": {
      "text/plain": "StageSummary(stage='lgd_training', label='Entrenamiento LGD', lines=('300 operaciones de entrenamiento · 80 de evaluación', '20 operaciones excluidas, conservadas en la historia', '2 covariables crudas; respuesta fraccional con intercepto', 'Sólo entrenamiento ajusta el predictor y la media de referencia', 'Las métricas describen la muestra; no certifican calidad ni transportabilidad'), alerts=('Declaración aportada; suficiencia y temporalidad no verificadas', 'Propósito: Demostrar el flujo con datos inventados/nSupuestos: Historia sintética con muestras y resultado declarados/nLimitaciones: No valida calidad ni transportabilidad', 'Procesos abiertos excluidos; representatividad y ausencia de sesgo de selección no demostradas'), table=         Muestra  ... Raíz del error cuadrático medio\n0  Entrenamiento  ...                        0.171575\n1  Entrenamiento  ...                        0.196807\n2     Evaluación  ...                        0.156369\n3     Evaluación  ...                        0.176759\n[4 rows x 8 columns], formats={})\n",
      "text/html": "<div class=\"bayesrisk-summary\"><h3>Entrenamiento LGD</h3><ul><li>300 operaciones de entrenamiento · 80 de evaluación</li><li>20 operaciones excluidas, conservadas en la historia</li><li>2 covariables crudas; respuesta fraccional con intercepto</li><li>Sólo entrenamiento ajusta el predictor y la media de referencia</li><li>Las métricas describen la muestra; no certifican calidad ni transportabilidad</li></ul><ul><li>⚠ Declaración aportada; suficiencia y temporalidad no verificadas</li><li>⚠ Propósito: Demostrar el flujo con datos inventados\nSupuestos: Historia sintética con muestras y resultado declarados\nLimitaciones: No valida calidad ni transportabilidad</li><li>⚠ Procesos abiertos excluidos; representatividad y ausencia de sesgo de selección no demostradas</li></ul><table class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th>Muestra</th>\n      <th>Predictor</th>\n      <th>Operaciones</th>\n      <th>Media observada</th>\n      <th>Media predicha</th>\n      <th>Sesgo medio</th>\n      <th>Error absoluto medio</th>\n      <th>Raíz del error cuadrático medio</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <td>Entrenamiento</td>\n      <td>Modelo ajustado</td>\n      <td>300</td>\n      <td>0,4007</td>\n      <td>0,4007</td>\n      <td>-1,2e-15</td>\n      <td>0,1388</td>\n      <td>0,1716</td>\n    </tr>\n    <tr>\n      <td>Entrenamiento</td>\n      <td>Media de entrenamiento</td>\n      <td>300</td>\n      <td>0,4007</td>\n      <td>0,4007</td>\n      <td>2,96e-18</td>\n      <td>0,16095</td>\n      <td>0,1968</td>\n    </tr>\n    <tr>\n      <td>Evaluación</td>\n      <td>Modelo ajustado</td>\n      <td>80</td>\n      <td>0,3715</td>\n      <td>0,3969</td>\n      <td>0,0254</td>\n      <td>0,1281</td>\n      <td>0,1564</td>\n    </tr>\n    <tr>\n      <td>Evaluación</td>\n      <td>Media de entrenamiento</td>\n      <td>80</td>\n      <td>0,3715</td>\n      <td>0,4007</td>\n      <td>0,0292</td>\n      <td>0,1437</td>\n      <td>0,1768</td>\n    </tr>\n  </tbody>\n</table><h4>Población y exclusiones</h4><table class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th>Muestra</th>\n      <th>Incumplimiento</th>\n      <th>Resultado disponible</th>\n      <th>Motivo</th>\n      <th>Objetivo ausente</th>\n      <th>Covariable ausente</th>\n      <th>Operaciones</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <td>Evaluación</td>\n      <td>sí</td>\n      <td>sí</td>\n      <td>Elegible</td>\n      <td>no</td>\n      <td>no</td>\n      <td>80</td>\n    </tr>\n    <tr>\n      <td>Excluida</td>\n      <td>sí</td>\n      <td>no</td>\n      <td>Exclusión declarada</td>\n      <td>sí</td>\n      <td>no</td>\n      <td>20</td>\n    </tr>\n    <tr>\n      <td>Entrenamiento</td>\n      <td>sí</td>\n      <td>sí</td>\n      <td>Elegible</td>\n      <td>no</td>\n      <td>no</td>\n      <td>300</td>\n    </tr>\n  </tbody>\n</table></div>\n"
     }
    }
   ],
   "execution_count": 1,
   "id": "h3-lgd-1"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Aplicar a otra cartera sin resultado observado\n\nLa cartera sintética tiene 6.000 operaciones. La PD constante es ilustrativa. Se elimina la columna LGD: el predictor usa sólo covariables crudas y no vuelve a ajustar. La provisión conserva la fórmula grupal, con detalle prorrateado. Separar muestras declaradas no certifica independencia del pipeline completo.\n\nEl CSV y el libro modelo_lgd exportan una tabla global reutilizable, sin llave de alineación; los textos codificados se conservan. No se cargan Study/joblib por HTTP. Los ZIP conservan historia y aplicación por separado. Las huellas y el ID de ajuste que aparecen abajo identifican esta ejecución; cambian con sus entradas o una corrida nueva.",
   "id": "h3-lgd-2"
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": "cartera = pd.read_parquet(materialize(\"provision_interna_generica\", workdir=Path(\"datos\")))\ncartera = cartera.drop(columns=\"lgd\")\ncartera[\"pd_declarada\"] = 0.02  # Sólo ilustración; no es una PD estimada.\nprovision = Provision(cartera, as_of=\"as_of_date\", portfolio=\"portfolio\",\n                      exposure=\"exposure_amount\", pd=\"pd_declarada\", lgd=lgd.model_,\n                      id=\"loan_id\", formats=[\"csv\"])\nprovision.run(raise_on_error=True)\nlgd.export_excel()\nlgd.export(\"historia-lgd.zip\")\nprovision.export(\"aplicacion-lgd.zip\")\nprovision.summary()",
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": "── Cartera ──\nArchivo: DataFrame en memoria, guardado como bayesrisk-runs/provision/input/data-<hash>.parquet\n6.000 filas · 12 columnas\nEsquema inferido: 12 columnas\nIdentificador: loan_id (índice del archivo)\nPD externa declarada; esta corrida no ajusta ni calibra la PD\nEvidencia de la corrida: bayesrisk-runs/provision/run\n── Provisión interna ──\n6.000 operaciones · 3 grupos\nExposición: 8.129.332.047 · Provisión: 58.845.153\nAgrupación: banda de score\nPD externa declarada: no se ajustó ni calibró en esta corrida\nEl detalle prorratea el total grupal por exposición; no suma productos individuales\nLa severidad se predice con un modelo de historia separada, sin reajustarlo con esta cartera.\n⚠ Declaración aportada; suficiencia y temporalidad no verificadas\n⚠ Propósito: Demostrar el flujo con datos inventados\nSupuestos: Historia sintética con muestras y resultado declarados\nLimitaciones: No valida calidad ni transportabilidad\n⚠ La aplicación no acredita independencia ni transportabilidad; no se reajustó LGD\n⚠ Ajuste de origen: 2438c5438d5a462d88e2137387919a75\n⚠ Huella del config de origen: e0c11cb5b10bc46e71cfa9c7bc9deebff441ffba9792bff4b8d2ce190365cc0e\n⚠ Huella de los datos de origen: acd2a43bbcdf59498d60118e95541d58693976fb4ae1f68c3a84d2a1b2f75450\n── Informe y ficha ──\nInforme HTML: bayesrisk-runs/provision/reports/provision_interna_report.html\nRegistro de auditoría: bayesrisk-runs/provision/run/audit_trail.jsonl\nEjecución: completada\nProvisión interna total: 58.845.153\nExcel por etapa: 3 libros en bayesrisk-runs/lgd/excel\nPaquete de la corrida: historia-lgd.zip\nPaquete de la corrida: aplicacion-lgd.zip\n"
    },
    {
     "output_type": "execute_result",
     "execution_count": 2,
     "metadata": {},
     "data": {
      "text/plain": "FinalSummary(execution='completada', validation='no aplica: una provisión no tiene veredicto técnico; lo que la cifra supone está en «Supuestos»', figures=(('Provisión interna total', '58.845.153'), ('Exposición total', '8.129.332.047'), ('Operaciones', '6.000'), ('Grupos', '3'), ('Cobertura', '0,72 %')), review=('Provisión interna: Declaración aportada; suficiencia y temporalidad no verificadas', 'Provisión interna: Propósito: Demostrar el flujo con datos inventados/nSupuestos: Historia sintética con muestras y resultado declarados/nLimitaciones: No valida calidad ni transportabilidad', 'Provisión interna: La aplicación no acredita independencia ni transportabilidad; no se reajustó LGD', 'Provisión interna: Ajuste de origen: 2438c5438d5a462d88e2137387919a75', 'Provisión interna: Huella del config de origen: e0c11cb5b10bc46e71cfa9c7bc9deebff441ffba9792bff4b8d2ce190365cc0e', 'Provisión interna: Huella de los datos de origen: acd2a43bbcdf59498d60118e95541d58693976fb4ae1f68c3a84d2a1b2f75450'), decisions=(), files=(('Carpeta del proyecto', 'bayesrisk-runs/provision'), ('Config vigente', 'bayesrisk-runs/provision/config.yaml'), ('Evidencia de la corrida', 'bayesrisk-runs/provision/run'), ('Registro de auditoría', 'bayesrisk-runs/provision/run/audit_trail.jsonl'), ('Informe HTML', 'bayesrisk-runs/provision/reports/provision_interna_report.html')), stages=(StageSummary(stage='data', label='Cartera', lines=('Archivo: DataFrame en memoria, guardado como bayesrisk-runs/provision/input/data-<hash>.parquet', '6.000 filas · 12 columnas', 'Esquema inferido: 12 columnas', 'Identificador: loan_id (índice del archivo)', 'PD externa declarada; esta corrida no ajusta ni calibra la PD', 'Evidencia de la corrida: bayesrisk-runs/provision/run'), alerts=(), table=None, formats={'Filas': 'int', 'Malos': 'int', 'Tasa de malos': 'pct'}), StageSummary(stage='provisioning_internal', label='Provisión interna', lines=('6.000 operaciones · 3 grupos', 'Exposición: 8.129.332.047 · Provisión: 58.845.153', 'Agrupación: banda de score', 'PD externa declarada: no se ajustó ni calibró en esta corrida', 'El detalle prorratea el total grupal por exposición; no suma productos individuales', 'La severidad se predice con un modelo de historia separada, sin reajustarlo con esta cartera.'), alerts=('Declaración aportada; suficiencia y temporalidad no verificadas', 'Propósito: Demostrar el flujo con datos inventados/nSupuestos: Historia sintética con muestras y resultado declarados/nLimitaciones: No valida calidad ni transportabilidad', 'La aplicación no acredita independencia ni transportabilidad; no se reajustó LGD', 'Ajuste de origen: 2438c5438d5a462d88e2137387919a75', 'Huella del config de origen: e0c11cb5b10bc46e71cfa9c7bc9deebff441ffba9792bff4b8d2ce190365cc0e', 'Huella de los datos de origen: acd2a43bbcdf59498d60118e95541d58693976fb4ae1f68c3a84d2a1b2f75450'), table=                            Grupo  ...    Provisión\ngroup_key                          ...\nconsumo_senior|banda_01  banda_01  ...  19398642.10\nmicroempresa|banda_01    banda_01  ...  20188916.86\nnomina|banda_01          banda_01  ...  19257594.10\n[3 rows x 8 columns], formats={'Operaciones': 'int', 'Exposición': 'num2', 'Provisión': 'num2', 'PD del grupo': 'pct', 'LGD del grupo': 'pct', 'Tasa de pérdida': 'pct'}), StageSummary(stage='report', label='Informe y ficha', lines=('Informe HTML: bayesrisk-runs/provision/reports/provision_interna_report.html', 'Registro de auditoría: bayesrisk-runs/provision/run/audit_trail.jsonl'), alerts=(), table=None, formats={})))\n",
      "text/html": "<div class=\"bayesrisk-summary\"><h2>Resumen de la provisión interna</h2><p><b>Ejecución:</b> completada</p><h4>Supuestos</h4><ul><li>La provisión se calcula por grupos; el detalle prorratea ese total por exposición</li><li>La calidad de PD y LGD no queda certificada por terminar el cálculo</li><li>La severidad se predice con un modelo de historia separada, sin reajustarlo con esta cartera.</li><li>Declaración aportada; suficiencia y temporalidad no verificadas</li><li>Propósito: Demostrar el flujo con datos inventados\nSupuestos: Historia sintética con muestras y resultado declarados\nLimitaciones: No valida calidad ni transportabilidad</li><li>La aplicación no acredita independencia ni transportabilidad; no se reajustó LGD</li><li>Ajuste de origen: 2438c5438d5a462d88e2137387919a75</li><li>Huella del config de origen: e0c11cb5b10bc46e71cfa9c7bc9deebff441ffba9792bff4b8d2ce190365cc0e</li><li>Huella de los datos de origen: acd2a43bbcdf59498d60118e95541d58693976fb4ae1f68c3a84d2a1b2f75450</li><li>PD externa declarada: esta corrida no la ajustó ni calibró</li></ul><table><tbody><tr><th>Provisión interna total</th><td>58.845.153</td></tr><tr><th>Exposición total</th><td>8.129.332.047</td></tr><tr><th>Operaciones</th><td>6.000</td></tr><tr><th>Grupos</th><td>3</td></tr><tr><th>Cobertura</th><td>0,72 %</td></tr></tbody></table><h4>Qué revisar</h4><ul><li>⚠ Provisión interna: Declaración aportada; suficiencia y temporalidad no verificadas</li><li>⚠ Provisión interna: Propósito: Demostrar el flujo con datos inventados\nSupuestos: Historia sintética con muestras y resultado declarados\nLimitaciones: No valida calidad ni transportabilidad</li><li>⚠ Provisión interna: La aplicación no acredita independencia ni transportabilidad; no se reajustó LGD</li><li>⚠ Provisión interna: Ajuste de origen: 2438c5438d5a462d88e2137387919a75</li><li>⚠ Provisión interna: Huella del config de origen: e0c11cb5b10bc46e71cfa9c7bc9deebff441ffba9792bff4b8d2ce190365cc0e</li><li>⚠ Provisión interna: Huella de los datos de origen: acd2a43bbcdf59498d60118e95541d58693976fb4ae1f68c3a84d2a1b2f75450</li></ul><h4>Decisiones humanas registradas</h4><ul><li>Ninguna decisión humana registrada; lo que se decidió vive en el config de la corrida.</li></ul><h4>Dónde quedó cada archivo</h4><ul><li>Carpeta del proyecto: <code>bayesrisk-runs/provision</code></li><li>Config vigente: <code>bayesrisk-runs/provision/config.yaml</code></li><li>Evidencia de la corrida: <code>bayesrisk-runs/provision/run</code></li><li>Registro de auditoría: <code>bayesrisk-runs/provision/run/audit_trail.jsonl</code></li><li>Informe HTML: <code>bayesrisk-runs/provision/reports/provision_interna_report.html</code></li></ul></div>\n"
     }
    }
   ],
   "execution_count": 2,
   "id": "h3-lgd-3"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
