Arquitectura del Sistema

Stock Market Risk Analysis -> Z-Score & Merton Model

Autor: Mauricio Martínez Ulloa

Flujo completo: entrada de tickers → modelos → decisión crediticia → reporte


01 · Entrada del usuario
UI / API Layer
🖥️
Frontend (SPA)
ui/index.html
Single-page app servida en GET /. El usuario ingresa los tickers (máx. 20), lanza el análisis y hace polling del estado.
POST /api/analyze GET /api/status/{job_id} GET /api/results/{job_id}
FastAPI App
api/main.py · run_api.py
Instancia FastAPI con CORS. Registra los routers de analyze y download. Sirve ui/index.html y el directorio outputs/ como estático.
uvicorn CORS * StaticFiles /outputs
📋
Schemas Pydantic
api/schemas.py
Contrato I/O de la API. Valida tickers (1–20), limpia strings, define TickerRow con todos los campos de resultado que consume el frontend.
AnalyzeRequest TickerRow ResultsResponse DataWarning
BackgroundTask · job_id UUID

02 · Orquestación
Routing & Job Management
🗂️
Analyze Router
api/routes/analyze.py
Lanza _run_pipeline_task() como BackgroundTask. Serializa summary_dfTickerRow[]. Lee ar.risk_zone directamente del ModelResult para zscore_zone.
POST /analyze GET /results _clean_float()
⚙️
Job Manager
api/services/job_manager.py
Singleton en memoria. Ciclo de vida: queued → running → done | error. Crea outputs/jobs/{uuid}/plots/ y reports/ por job. Almacena el result dict completo al terminar.
queued running done error
🔁
Download Router
api/routes/download.py
Expone el PDF y Markdown generados para descarga directa. Lee el path desde job.result["pdf_path"] y job.result["report_path"].
GET /download/pdf GET /download/md
run_pipeline(tickers, output_dir)

03 · Pipeline principal
main.py · run_pipeline()
STEP 1
📡
Data Fetcher
data/fetcher.py
Descarga via yfinance: balance sheet (hasta 10 años), income statement, cash flow, market data y tasa libre de riesgo (^TNX). Cache en CSV por ticker.
yfinance balance_sheet.csv cache.py force_refresh
STEP 2
🏷️
Sector Classifier
classifiers/sector_classifier.py
Detecta sector e industria de Yahoo Finance. Determina qué versión de Altman aplicar: Z original (manufactureras), Z' (privadas) o Z'' (servicios/no-manufactureras).
Z original 1968 Z' 1983 Z'' 1995
CompanyData → CreditEvaluator

04 · Modelos cuantitativos
models/ · Ejecución por ticker
Altman Z-score
📊
AltmanZScore
models/altman_zscore.py
Análisis discriminante sobre 5 ratios contables (X1–X5). Versión seleccionada por SectorClassifier.

Z'': 6.56·X1 + 3.26·X2 + 6.72·X3 + 1.05·X4
Zonas: Safe >2.60 · Grey 1.10–2.60 · Distress <1.10
Working Capital/Assets RE/Assets EBIT/Assets Equity/Liabilities
Merton (1974)
📐
MertonModel
models/merton.py
Modelo estructural de opciones. V_A = Total Assets, D = Total Liabilities, σ_A = std(log-returns anuales).

DD = [ln(V_A/D) + (r − σ²/2)·T] / (σ·√T)
PD = N(−DD)
^TNX tasa libre riesgo T = 1 año log-normal V_A
ModelResult → CreditEvaluator

05 · Decisión crediticia consolidada
evaluation/ · credit_evaluator.py
⚖️
CreditEvaluator
evaluation/credit_evaluator.py
Consolida los resultados de ambos modelos en una decisión única por ticker. Genera summary_df con todas las columnas para reporte y API.
🔀 Lógica de Consolidación
✓ Aprobar
Altman Safe Zone AND Merton PD < 1%
~ Zona Gris
Alguno en Grey Zone, ninguno en Distress
✕ Rechazar
Altman Distress Zone OR Merton PD > 5%
evaluations + summary_df + plot_paths

06 · Visualización & Reporte
visualization/ · reporting/ · api/services/
📈
Visualization
visualization/*.py
Genera 5 gráficos matplotlib: Z-score por modelo (original / Z''), DD Merton, PD Merton, Mapa de riesgo combinado. Guarda como PNG en outputs/jobs/{id}/plots/.
zscore_original.png zscore_double_prime.png merton_dd.png merton_pd.png risk_heatmap.png
📝
ReportGenerator
reporting/report_generator.py
Genera credit_report.md con secciones: portada, metodología, resultados por empresa, tabla comparativa (6 cols, markdown="1"), visualizaciones, conclusiones y bibliografía.
credit_report.md table-summary CSS span decision colors
📄
PDF Converter
api/services/pdf_converter.py
Pipeline: MD → HTML (markdown + md_in_html) → imágenes embebidas en base64 → CSS profesional → WeasyPrint → credit_report.pdf. Bibliografía con sangría francesa.
WeasyPrint A4 · @page base64 imgs credit_report.pdf
job.set_done(result) → polling frontend

07 · Outputs
outputs/jobs/{uuid}/
🌐
UI Resultados
Tabla interactiva con badges de zona Altman y decisión, gráficos en base64, advertencias por ticker
📄
credit_report.pdf
19 páginas A4: metodología, resultados por empresa, tabla comparativa formateada, 5 gráficos embebidos
📝
credit_report.md
Fuente del reporte en Markdown con HTML inline para colores de decisión y clases CSS
🖼️
plots/ (5 PNGs)
zscore_original · zscore_double_prime · merton_dd · merton_pd · risk_heatmap
💾
data/ cache CSVs
balance_sheet · income_stmt · cash_flow · market_data · companies por ticker
⚠️
DataWarnings
Advertencias por ticker: datos parciales, σ_A con <5 años, Working Capital incompleto
Leyenda de capas
UI / FastAPI / Schemas
Routing / Job Management
Data & Clasificación
Modelo Altman Z-score
Modelo Merton (1974)
Evaluador / Consolidación
Visualización / Reporte / PDF