QAO // QUANT AGENTIC ORCHESTRATION
PROMPTS · MÓDULO 06/12

Prompt engineering y salida estructurada para finanzas

System prompts por rol, few-shot, chain-of-thought con criterio y grounding anti-alucinación numérica.

LECTURA ~32 MIN NIVEL INTERMEDIO-AVANZADO EDICIÓN JUL 2026

Objetivos de aprendizaje

Al completar este módulo, el lector será capaz de:


El módulo 5 construyó la capa de recuperación: el contexto que alimenta los prompts. Este módulo aborda la segunda mitad del problema: cómo se instruye al modelo para que transforme ese contexto en salidas fiables, auditables y consumibles por sistemas de front office. Cierra el Bloque II (comprensión de información) y prepara el Bloque III (riesgo y carteras). Dos principios lo vertebran, ambos con respaldo empírico directo: el LLM nunca calcula —toda aritmética se delega en herramientas deterministas— y toda cifra citada se verifica por exact-match contra su fuente, no por el juicio de otro LLM (Financial Wisdom TV) .

6.1 Técnicas por tipo de tarea

La lección central de la evidencia 2023–2026 es que no existe "el mejor prompt": existe una correspondencia técnica × tarea, y elegir mal no solo encarece —en algunos casos degrada activamente la precisión (Day Trading) .

6.1.1 System prompts por rol: analista sell-side y risk manager

El role prompting (asignar un rol experto en el mensaje de sistema) tiene buen soporte en finanzas. La guía oficial de OpenAI recomienda estructurar el mensaje de desarrollador en cuatro secciones —Identidad, Instrucciones, Ejemplos y Contexto— con el contexto al final del prompt y delimitado con etiquetas XML (towardsai.net) . En sentimiento financiero, el formato de role-playing supera a los prompts planos (arXiv.org) , y en arquitecturas multi-agente de decisión el patrón se formaliza en bloques [ROLE], [GOAL], [RULES], [FORMAT], con separación Estratega → Crítico → Moderador que mejora la detección de huecos probatorios e inconsistencias numéricas frente a un agente único (Learnsignal) .

Plantilla 1 — system prompt de analista sell-side (producción):

# Identidad
Eres un analista sell-side senior de renta variable (sector tecnología) con 15 años
de experiencia. Escribes para inversores institucionales.

# Instrucciones
- Toda cifra que cites debe proceder EXCLUSIVAMENTE del bloque <filing_excerpt>.
- Si un dato no está en el contexto, responde "NO_DISPONIBLE" en ese campo.
- No calcules ratios mentalmente: para cualquier cálculo, invoca la herramienta
  `calculator`. La aritmética en texto está prohibida.
- Distingue siempre entre hechos (del filing) e inferencias (tu juicio); etiqueta
  cada párrafo como [HECHO] o [INFERENCIA].
- Horizonte del análisis: 12 meses. Indica siempre la fecha "as-of" de los datos y
  el period_end de cada cifra. No uses información posterior a {as_of}.

# Formato de salida
Devuelve ÚNICAMENTE un objeto JSON conforme al schema InvestmentThesis (adjunto).

# Contexto
<filing_excerpt source="10-K AAPL FY2025" as_of="2025-11-01" page="31">
...
</filing_excerpt>

Plantilla 2 — system prompt de risk manager:

# Identidad
Eres un risk manager de un fondo multi-estrategia. Tu prioridad es la preservación
de capital y el cumplimiento normativo; ante la duda, sé conservador.

# Instrucciones
- Evalúa cada propuesta con el esquema: evidencia → regla/política → conclusión.
- Verifica la coherencia aritmética (P5 ≤ P50 ≤ P95, rangos y totales) antes de
  aprobar; las comprobaciones mecánicas las ejecuta el código, no tú.
- Rechaza cualquier recomendación sin cuantificación de incertidumbre o sin citas.
- Nunca modifiques límites de riesgo; solo los evalúas contra la política adjunta.

Tres detalles no son decorativos. La instrucción negativa ("si no está en el contexto → NO_DISPONIBLE") es la defensa primaria contra la alucinación: sin ella, el modelo rellena huecos con conocimiento de entrenamiento potencialmente obsoleto (IDEAS/RePEc) . La fecha as_of es una defensa point-in-time: los modelos estándar exhiben look-ahead bias, con decaimiento de alpha superior a 15 puntos porcentuales fuera de muestra, porque memorizan resultados en lugar de predecir (metricgate.com) . Y la prohibición de aritmética en texto anticipa la evidencia de la sección 6.2.

EXPANDE

En palabras llanas: el system prompt es una carta de encargo

Piensa en el system prompt como en la carta de encargo que un fondo firma con una consultora externa. No dice «hazme un análisis bonito»: fija quién eres (analista senior, público institucional), qué fuentes puedes usar (solo el <filing_excerpt> adjunto), qué hacer cuando falta un dato («NO_DISPONIBLE», nunca rellenar de memoria) y quién hace los números (la herramienta calculator, no tú).

Cada cláusula de las plantillas 1 y 2 responde a un modo de fallo medido en la sección 6.2: la instrucción negativa cierra la puerta al conocimiento de entrenamiento obsoleto; la fecha as_of convierte el encargo en point-in-time; la etiqueta [HECHO]/[INFERENCIA] separa lo auditable de lo opinable. Una línea de system prompt que no mitiga ningún fallo concreto es decoración — y la decoración cuesta tokens y atención del modelo. Por eso el ejercicio 1 pide justificar cada línea citando el fallo que mitiga, o eliminarla.

Few-shot: tres ejemplos bastan

El few-shot prompting (incluir ejemplos entrada-salida en el prompt) es la técnica con evidencia más robusta para clasificación de sentimiento financiero. El estudio seminal de Lopez-Lira y Tang (2023) mostró que los scores de sentimiento de titulares predicen retornos diarios, y que la predictibilidad es una capacidad emergente de los modelos grandes (GPT-3.5/4 sí; GPT-1/2 y BERT no), con Sharpe 3,8 para GPT-4 en long-short 2021–2022 sin costes (arXiv.org) . Sobre la dosis: en LLMs ligeros (Qwen3-8B, Llama3-8B) el salto de 0-shot a 3-shot eleva la precisión media de 0,67 a 0,74, pero de 3-shot a 5-shot la mejora deja de ser sustancial (arXiv.org) . La palanca adicional no son más ejemplos sino descripciones verbosas de las categorías y una clase "Other" de escape (metricgate.com) .

Plantilla 3 — clasificador de sentimiento 3-shot (formato AD-FCoT, con causalidad explícita y sin look-ahead):

Eres un analista financiero. Lee la noticia y razona paso a paso sobre su impacto
en la acción; después emite Positive/Negative/Neutral.

<ejemplo>
Noticia: "ACME retira del mercado su producto estrella por defectos de seguridad."
Razonamiento: La retirada implica costes directos, riesgo de litigios y pérdida de
ingresos del producto principal → impacto negativo en próximos trimestres.
Sentimiento: Negative
</ejemplo>
<ejemplo>
Noticia: "ACME supera expectativas de beneficio y eleva la guía anual."
Razonamiento: Beat de EPS + guía al alza señalan momentum operativo;
históricamente el mercado reacciona con re-rating positivo.
Sentimiento: Positive
</ejemplo>
<ejemplo>
Noticia: "ACME anuncia que cambiará el auditor del ejercicio 2027."
Razonamiento: Cambio rutinario de auditor sin implicación directa en resultados.
Sentimiento: Neutral
</ejemplo>

Noticia objetivo: {titular}
Razonamiento:

Chain-of-thought: dónde ayuda y dónde destruye precisión

El chain-of-thought (CoT; inducir al modelo a verbalizar pasos intermedios) es el estándar para razonamiento multi-paso, y en finanzas su valor es real pero acotado: en un benchmark multimodal de filings, añadir CoT elevó la precisión de cálculo del 60,0% al 76,9% y redujo la alucinación de ~15% a ~5% (🦜️🔗 LangChain) ; en FinQA/TAT-QA (preguntas numéricas sobre informes anuales), la descomposición lleva a GPT-3.5-turbo de 28,4 a 51,4–55,1 puntos (metricgate.com) . Advertencia metodológica: la cadena verbalizada no es necesariamente fiel al cómputo interno del modelo; no es explicabilidad (ryanoconnellfinance.com) .

La contra-evidencia es el hallazgo más contraintuitivo del área. En tareas donde "pensar" perjudica incluso a humanos, el CoT degrada al modelo: en aprendizaje estadístico implícito se observa una caída absoluta de 36,3 puntos porcentuales, y en clasificación con excepciones a reglas generalizables el CoT aumentó hasta un 331% las iteraciones necesarias, porque sesga al modelo hacia la regla general y le hace ignorar los tokens contextuales con la respuesta correcta (Day Trading) . En clasificación con ground truth humano, activar CoT no mejoró a ningún modelo y degradó ligeramente a algunos; Chain-of-Verification redujo la precisión 1–2 puntos al retractar clasificaciones correctas (metricgate.com) . En el dominio legal —análogo estructural al financiero— el CoT ayuda al entailment contractual (+8,5 pp) pero perjudica la identificación de holdings (−16,0 pp) y la clasificación multi-etiqueta (−3,8 pp) (arXiv.org) . El CoT explícito también degrada el seguimiento de instrucciones (A.L. Capital Advisory) .

Self-consistency muestrea \(k\) cadenas y toma la respuesta mayoritaria:

\[\hat{y} = \arg\max_{y} \sum_{i=1}^{k} \mathbb{1}\,[y_i = y]\]

Combinada con generación de programas elevó GSM8K del 72,0% al 80,4% con \(k=40\) (Financial Wisdom TV) . Su límite documentado: si el prompt o el contexto inducen el mismo sesgo, las muestras coinciden en el error (majority hallucination); la técnica presupone que el modelo tiene acceso a la información necesaria (arXiv.org) . En la práctica financiera se usa con \(k=5\)\(11\) sobre extracciones de una misma métrica, enviando las respuestas minoritarias a cola de auditoría.

Least-to-most descompone el problema en subproblemas resueltos secuencialmente reutilizando respuestas previas; resolvió el benchmark SCAN con ≥99% de precisión frente al 16% del CoT (arxiv.org) . Advertencia 2025–2026: la descomposición asistida por LLM puede omitir subtareas o introducir pasos irrelevantes; la mitigación es híbrida —el humano fija el esqueleto (ingresos → márgenes → flujo de caja → deuda → valoración) y el LLM rellena las subpreguntas (arXiv.org) .

Tabla 6.1 — Técnicas de prompting: cuándo usar cada una y evidencia

Técnica Mecánica Cuándo usarla en finanzas Evidencia
Zero-shot directo Instrucción + salida inmediata, temp 0 Clasificación simple de sentimiento (3 clases), extracción de campos únicos CoT no mejora y a veces degrada la clasificación (metricgate.com)
Few-shot (3-shot) 3 ejemplos diversos entrada→salida Clasificación con taxonomía propia; formato de salida rígido 0→3 shot: 0,67→0,74 acc; 3→5 plano (arXiv.org) ; few-shot la estrategia más consistente en dominio legal (arXiv.org)
Chain-of-thought Pasos intermedios verbalizados Cálculo y QA numérico multi-paso sobre filings Precisión de cálculo 60,0%→76,9%; alucinación ~15%→~5% (🦜️🔗 LangChain) ; FinQA 28,4→51,4–55,1 (metricgate.com)
Self-consistency \(k\) cadenas + voto mayoritario Extracción crítica de una métrica; detección de inestabilidad GSM8K 72,0%→80,4% (\(k=40\)) (Financial Wisdom TV) ; riesgo de majority hallucination (arXiv.org)
Least-to-most / descomposición Subproblemas secuenciales con schemas intermedios Tesis multi-paso, análisis de filings largos SCAN ≥99% vs 16% CoT (arxiv.org) ; descomposiciones inestables sin esqueleto humano (arXiv.org)
Grounding estricto Contexto XML + instrucción negativa + cita verbatim Toda tarea sobre documentos recuperados (RAG) Faithfulness ~86–87% en pipelines financieros reales (CallSphere) ; control [CONTROL] documentado (Learnsignal)

Interpretación. La tabla condensa la regla de routing del módulo: la técnica se elige por la estructura cognitiva de la tarea, no por moda ni por capacidad del modelo. El patrón transversal de la evidencia es que el razonamiento verbalizado paga cuando la tarea es composicional y numérica (FinQA, cálculo de ratios), y cuesta cuando es de reconocimiento de patrones o clasificación con excepciones —ahí el modelo "se convence a sí mismo" de la respuesta incorrecta mediante razonamiento excesivo (ryanoconnellfinance.com) . El few-shot ocupa el centro: barato, robusto y con rendimientos decrecientes a partir de tres ejemplos, lo que simplifica el mantenimiento en producción. Self-consistency y la descomposición son técnicas de segunda capa: multiplican coste y latencia, y solo se justifican donde el error es caro (una cifra que alimentará un límite de riesgo) o donde la tarea excede la longitud de los ejemplos. El grounding, en cambio, no es opcional en este dominio: es la condición de auditabilidad, y se desarrolla en la sección siguiente.

EXPANDE

Trampa común: poner chain-of-thought a todo

El instinto de 2023 era «si el modelo razona en voz alta, acertará más». La contra-evidencia de esta sección lo desmiente con cifras incómodas: −36,3 puntos porcentuales en aprendizaje estadístico implícito y hasta +331 % de iteraciones en clasificación con excepciones a la regla general.

El mecanismo del fallo es sutil: en una tarea con excepciones, verbalizar fuerza al modelo a enunciar la regla — y una vez enunciada, se ancla en ella e ignora los tokens del contexto que marcaban la excepción. Ejemplo financiero: «Las acciones suben un 8 % tras la dimisión del CEO por fraude». La regla general dice «fraude → negativo»; el titular describe exactamente la excepción. El modelo directo lee el dato; el CoT «razona» hasta la regla y se equivoca con solvencia retórica.

La heurística operativa del módulo: CoT solo cuando la tarea es composicional y numérica (un cálculo en pasos, un QA sobre un filing). Si es reconocimiento de patrones o clasificación, directo con few-shot — y ahí la palanca está en las descripciones verbosas de las categorías y en una clase "Other" de escape, no en el razonamiento.

6.2 Grounding y anti-alucinación numérica

6.2.1 La instrucción "responde solo con datos del contexto" y sus límites documentados

El patrón de grounding estricto tiene cinco componentes observados en arquitecturas financieras documentadas: (1) contexto delimitado con etiquetas XML y metadatos (source, as_of, page); (2) instrucción negativa explícita ("si la respuesta no está en el contexto, responde NO_DISPONIBLE; nunca uses conocimiento del entrenamiento"); (3) cita obligatoria con proveniencia por cada cifra; (4) campo confidence y evidence_quote por afirmación en el schema; (5) verificación de dos pasos posterior (Learnsignal) . El bloque de control canónico de la literatura multi-agente es literal: [CONTROL] Do not introduce new data; rely exclusively on the CONTEXT (Learnsignal) . Las citas con fuente y fecha reducen alucinaciones y facilitan la auditoría (Learnsignal) ; en pipelines reales sobre FinanceBench, la métrica Faithfulness de RAGAS —fracción de afirmaciones soportadas por el contexto recuperado— se sitúa en ~86–87% (CallSphere) .

Los límites son estructurales, no de redacción. NumericBench documenta que incluso modelos frontera (GPT-4o, DeepSeek-V3) fallan en aritmética simple, recuperación de números y razonamiento multi-paso, porque tratan los números como tokens discretos sin semántica numérica; perturbaciones triviales de cifras reducen significativamente la precisión (博客园) . El caso paradigmático es 9.11 vs 9.9: "9.11" tokeniza como ["9", ".", "11"] y el modelo compara los fragmentos 11 y 9 como enteros, reforzado por patrones de versionado de software en el entrenamiento; lo grave es que Claude Sonnet 4 y GPT-4o articulan el procedimiento de comparación decimal con precisión de manual mientras lo ejecutan mal —el llamado computational split-brain (langchain.js) . A escala de dominio, un estudio de 2024 citado por FailSafeQA estima alucinación en hasta el 41% de las consultas financieras, y diferencias menores de redacción ("net income" vs "earnings") alteran las salidas (博客园) . En extracción de filings, los fallos dominantes son: fallo de retrieval (42%), brecha multi-estado (23%), error de escala de valores (15%) —leer "millones" como "miles"— y fabricación de cifras (10%) (🦜️🔗 LangChain) . Por eso escala y unidad son campos obligatorios del schema. El contexto de dificultad: GPT-4 con retrieval obtuvo ~19% en FinanceBench en la configuración original, y GPT-4 se queda en el 62,87% en FinQA frente al 91,16% del experto humano (las cifras completas del benchmark, en §5.1) (arXiv.org) .

EXPANDE

En palabras llanas: por qué 9.11 «parece» mayor que 9.9 para un LLM

El modelo no ve números: ve tokens. La cadena "9.11" se fragmenta en ["9", ".", "11"] y, al comparar, el fragmento 11 pesa más que el 9 de "9.9" — reforzado porque en el corpus de entrenamiento la «versión 9.11» efectivamente va después de la «versión 9.9». El resultado es el computational split-brain: el modelo recita el procedimiento de comparación decimal con precisión de manual y lo ejecuta mal al mismo tiempo.

La consecuencia práctica es la que da título a la sección siguiente: esto no se arregla con mejor redacción, porque no es un problema de instrucciones sino de representación. Se arregla sacando la aritmética del modelo — calculator, xbrl_lookup, código — y usando el LLM para lo que sí hace bien: localizar la cifra, citarla verbatim y ponerla en contexto. De ahí que unidad y scale sean campos obligatorios del schema: el 15 % de los fallos de extracción en filings son errores de escala («millones» leídos como «miles»).

PAL y tool-calling como mitigación: el LLM nunca calcula

La mitigación con mayor evidencia cuantificada es delegar el cómputo. PAL (Program-Aided Language Models) demostró que el modo de fallo dominante del CoT en matemáticas no es el razonamiento sino la aritmética —en 16 de 25 casos, el CoT generaba "pensamientos" casi idénticos con números distintos— y que ejecutar el razonamiento como programa eleva GSM-Hard del ~20% del CoT al 61,2% (Financial Wisdom TV) . Toolformer ya había mostrado que con acceso a una calculadora el modelo resuelve aritmética que los modelos puros fallan consistentemente (稀土掘金) . El contrato de tool calling es explícito: el LLM no ejecuta la función; propone qué función llamar y con qué argumentos, y el código valida y ejecuta (supermemory.ai) .

from langchain_core.tools import tool
import ast, operator as op

_OPS = {ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul,
        ast.Div: op.truediv, ast.Pow: op.pow, ast.USub: op.neg}

@tool
def calculator(expression: str) -> float:
    """Evalúa una expresión aritmética. ÚNICA vía autorizada para TODO cálculo;
    el LLM no debe hacer aritmética en texto."""
    def ev(node):
        if isinstance(node, ast.Constant): return node.value
        if isinstance(node, ast.BinOp): return _OPS[type(node.op)](ev(node.left), ev(node.right))
        if isinstance(node, ast.UnaryOp): return _OPS[type(node.op)](ev(node.operand))
        raise ValueError("expresión no permitida")
    return ev(ast.parse(expression, mode="eval").body)  # AST restringido, nunca eval()

@tool
def xbrl_lookup(ticker: str, concept: str, period_end: str) -> dict:
    """Devuelve un concepto XBRL point-in-time de un filing SEC con cita (doc, página)."""
    ...

Verificación de dos pasos con fail-closed

El segundo pilar es la verificación determinista posterior a la generación: un verificador en código comprueba que cada cifra aparece literalmente en la cita verbatim declarada. Si falla, el registro no se persiste: se reintenta devolviendo el error al modelo y, agotados los reintentos, se rechaza (fail-closed). Es la aplicación del insight institucional I6: para cifras, exact-match en código > LLM-as-judge, porque pedir a otro LLM que juzgue una cifra es circular.

Diagrama
def extract_with_retry(prompt: str, max_retries: int = 2) -> FilingMetric:
    last_error = None
    for _ in range(max_retries + 1):
        out = extractor.invoke([
            {"role": "system", "content": SYSTEM},
            {"role": "user", "content": prompt + (f"\nError previo: {last_error}" if last_error else "")},
        ])
        if out["parsing_error"] is None:
            metric = out["parsed"]
            # Verificación de dos pasos: la cifra debe estar literalmente en la cita
            if metric.value is None or str(metric.value).replace(",", "") in \
               metric.evidence_quote.replace(",", ""):
                return metric
            last_error = "evidence_quote no contiene la cifra literal"
        else:
            last_error = str(out["parsing_error"])
    raise ValueError(f"extracción fallida tras reintentos: {last_error}")

Nótese la asimetría deliberada: value = null pasa la verificación (el modelo se abstiene), pero una cifra que no está en la cita no pasa jamás. La abstención es un resultado legítimo; la fabricación es un fallo de sistema.

En la práctica institucional. El patrón exact-match sobre cifras no es una excentricidad académica: Kensho (S&P Global) opera en producción "Grounding", un framework multi-agente sobre LangGraph cuya evaluación multi-etapa usa métricas exact-match de routing y tool-calling sobre datos financieros reales (IDEAS/RePEc) —precisamente porque un juicio de LLM sobre una cifra de riesgo no es auditable ante un regulador. Las mesas que operan estos pipelines aplican la misma división que este módulo: la validación sintáctica la resuelve el constrained decoding; la semántica —rangos, monotonía \(P5 \le P50 \le P95\), consistencia de unidades, verificación de citas— es responsabilidad del equipo en código defensivo (A.L. Capital Advisory) . El presupuesto de reintentos se fija en 2–3 y todo rechazo alimenta una cola de revisión humana, nunca un valor por defecto silencioso.

EXPANDE

Ejemplo trabajado: el exact-match que atrapa una cifra sin proveniencia

Supón que el pipeline extrae las ventas netas de un 10-K y el contexto recuperado contiene la frase: «Total net sales were $391,035 million in fiscal 2025.»

Intento 1 — cifra correcta, proveniencia incorrecta. El modelo devuelve value = 391.035, scale = "billions" y la cita verbatim. Numéricamente la conversión es correcta, pero el verificador normaliza separadores y busca "391.035" en la cita: no está (la cita dice 391,035 millones). El sistema rechaza una cifra verdadera — y es el comportamiento deseado: exact-match no juzga si el número es cierto, juzga si tiene proveniencia literal. La conversión de escala es aritmética, y la aritmética corresponde a una herramienta, no al modelo (as_reported quedaría en False solo tras una tool call). last_error = "evidence_quote no contiene la cifra literal" → reintento con el error devuelto al modelo.

Intento 2 — corrección. El modelo devuelve value = 391035, scale = "millions". Ahora str(391035) sí aparece en la cita normalizada → pasa → se persiste con doc_id, página y hash del prompt.

Intento 3 — abstención legítima. Si la cifra pedida no estuviera en el contexto, la respuesta correcta es value = null: pasa la verificación por diseño y el registro queda marcado como no disponible. Solo si el modelo insiste en fabricar agota los max_retries = 2 y el pipeline rechaza: fail-closed, cola de auditoría humana, ningún valor por defecto silencioso. Rechazar una conversión correcta de tanto en tanto es el precio de interceptar todas las fabricadas.

6.3 Schemas Pydantic para el front office

6.3.1 InvestmentThesis y TradingSignal listos para OMS/risk

La jerarquía de fiabilidad de mecanismos de salida está documentada: JSON mode solo garantiza JSON sintácticamente válido (la truncación es su causa principal de fallo (博客园) ); function/tool calling tipa los argumentos con ~86% de cumplimiento de schema; y Structured Outputs (json_schema estricto) alcanza ~100% mediante decodificación restringida por gramática (A.L. Capital Advisory) . En LangChain, with_structured_output es el punto de integración: en langchain-openai el método por defecto pasó de function_calling a json_schema en la 0.3.0, y con strict=True los modelos Pydantic no pueden usar metadata de Field (min/max) ni valores por defecto (oneuptime.com) ; en agentes, create_agent elige ProviderStrategy (structured output nativo) si el proveedor lo soporta y ToolStrategy en caso contrario, con handle_errors para reintentos y el resultado en structured_response (Red Hat Developer) . Hecho de diseño esencial: el nombre de la clase, el docstring y las descripciones de campos se inyectan en el prompt —el schema ES parte del prompt (Quant Memo) .

Schema completo — tesis de inversión:

from pydantic import BaseModel, Field
from typing import Literal, Optional
from datetime import date

class Evidence(BaseModel):
    """Cita obligatoria de cada afirmación factual."""
    doc_id: str = Field(description="Identificador del documento, p.ej. 'AAPL_10K_FY2025'")
    page: int = Field(description="Página del documento fuente")
    quote: str = Field(description="Extracto VERBATIM (<= 40 palabras) que soporta la afirmación")

class MetricValue(BaseModel):
    """Una métrica financiera con unidad, escala y proveniencia explícitas."""
    value: Optional[float] = Field(
        description="Valor numérico. null si NO aparece en el contexto. NUNCA inventar.")
    unit: Literal["USD", "EUR", "shares", "percent", "ratio", "other"]
    scale: Literal["units", "thousands", "millions", "billions"] = Field(
        description="Escala tal como aparece en el filing (evita errores 10^3/10^6)")
    period_end: date = Field(description="Fecha de cierre del periodo reportado")
    as_reported: bool = Field(description="True si la cifra es literal del documento; "
                                          "False si se derivó de una tool call")
    evidence: Optional[Evidence] = None

class InvestmentThesis(BaseModel):
    """Tesis de inversión estructurada generada exclusivamente a partir del contexto."""
    ticker: str
    as_of: date = Field(description="Fecha de corte de la información (point-in-time)")
    rating: Literal["strong_buy", "buy", "hold", "sell", "strong_sell"]
    horizon_months: Literal[3, 6, 12, 24]
    revenue_ltm: MetricValue
    eps_ltm: MetricValue
    net_debt: MetricValue
    bull_case: list[str] = Field(max_length=3)
    bear_case: list[str] = Field(max_length=3)
    key_risks: list[str]
    confidence: Literal["low", "medium", "high"]
    reasoning_summary: str = Field(description="<= 100 palabras; marca [HECHO]/[INFERENCIA]")

Schema completo — señal de trading para integración OMS/risk:

class TradingSignal(BaseModel):
    """Señal consumible por un OMS; ningún campo calculado por el LLM."""
    instrument_id: str = Field(description="Identificador canónico (ISIN/FIGI/ticker interno)")
    as_of: date
    direction: Literal["long", "short", "flat"]
    strength: float = Field(ge=-1.0, le=1.0, description="Intensidad normalizada [-1, 1]")
    signal_family: Literal["sentiment_news", "fundamental", "technical", "composite"]
    valid_from: date
    valid_until: date = Field(description="Caducidad de la señal (point-in-time safety)")
    max_position_pct_nav: float = Field(ge=0.0, le=100.0)
    rationale_codes: list[str] = Field(description="Códigos de la taxonomía interna, NO texto libre")
    model_version: str = Field(description="Snapshot del modelo + hash del prompt, para auditoría")
    compliance_flags: list[Literal["restricted_list", "mnpi_risk", "liquidity_low"]] = []

Las notas de diseño para consumo por un OMS o motor de riesgo son cinco: enums cerrados y rangos numéricos en los campos decisionales; caducidad explícita (valid_until) como defensa point-in-time; trazabilidad (model_version, hash del prompt) por registro; flags de cumplimiento tipados; y la separación de poderes del insight I1 —el LLM propone y el motor de riesgo dispone: la señal nunca ejecuta directamente. Para diagnóstico, include_raw=True devuelve {'raw', 'parsed', 'parsing_error'} y permite capturar errores sin excepción (oneuptime.com) ; los parsers auto-reparadores estilo OutputFixingParser reintentan con un LLM hasta validez o límite (博客园) ; y conviene fijar max_tokens a 2–3× la longitud esperada contra la truncación (博客园) .

Nota de riesgo — "structured output garantiza la forma, no la verdad". El cumplimiento de schema cercano al 100% puede elevar la tasa de respuestas confidently wrong. En un caso fintech documentado de extracción de PDFs de préstamos, la ejecución con conformidad total tuvo la mayor tasa de errores confiados: cuando el dato no estaba en el documento, la versión restringida emitía {"income": 75000} porque la gramática exigía que income fuera un número —el modelo ya no podía negarse (metricgate.com) . El equivalente en front office es un net_debt inventado pero perfectamente tipado que atraviesa el OMS sin levantar alarmas. Las mitigaciones son estructurales: hacer null/"unknown" parte del schema de cada campo (la abstención debe ser representable), emparejar con un chequeo de self-consistency sin restricciones, y mantener la verificación de dos pasos antes de persistir (metricgate.com) . El riesgo residual vive en la validación semántica, no en la sintáctica: "structured outputs eliminan la clase de fallos de parsing, pero no eliminan la necesidad de código defensivo en producción" (supermemory.ai) .

EXPANDE

Trampa común: confundir «schema válido» con «dato verdadero»

El salto de ~86 % (function calling) a ~100 % (structured output estricto) elimina una clase entera de fallos — la de parsing — y por eso mismo crea una trampa nueva: todo lo que sale está bien formado, incluidos los datos inventados. El caso fintech de la nota de riesgo es canónico: al exigir la gramática que income fuera un número, el modelo emitió {"income": 75000} cuando el documento no contenía ese dato, y la ejecución con conformidad total tuvo la mayor tasa de errores confiados.

La lección de diseño tiene dos partes. Primero: la abstención debe ser representable en el schema (Optional[float] con null documentado como «no aparece en el contexto»), porque un campo obligatorio e invenible es una orden implícita de fabricar. Segundo: como el constrained decoding solo garantiza la forma, la verdad se defiende en capas posteriores, ninguna opcional en front office:

Diagrama

El riesgo residual vive en la validación semántica: por eso el ejercicio 2 pide un @model_validator (monotonía, evidencia presente si hay valor) y no solo Field(ge=…) — que, además, strict=True ni siquiera admite.

6.4 Reasoning models y routing de técnicas en 2026

6.4.1 reasoning_effort / budget_tokens: cuándo pagar por razonamiento

Desde 2025–2026 la profundidad de razonamiento es un parámetro de API gobernable: la serie o de OpenAI expone reasoning_effort (low/medium/high; GPT-5 añade minimal) y Claude expone thinking.budget_tokens (típicamente 1024, 4096 o 16000) (Github) . La guía oficial de OpenAI formula la distinción: los reasoning models generan una cadena de pensamiento interna, destacan en tareas complejas y planificación multi-paso, y son más lentos y caros; la analogía oficial es colega senior (objetivo de alto nivel) frente a junior (instrucciones explícitas) (towardsai.net) . La regla de routing es simétrica: subir el esfuerzo para matemáticas, código y planificación de tool calls; bajarlo para clasificación simple, extracción y formateo —"la profundidad de razonamiento no es cuanto más alta mejor" (Github) . En benchmarks financieros multi-capacidad los reasoning models lideran (o1: 67,3% en XFinBench), pero en juicios de oportunidad de trading todos los LLM fallaron el componente de compra en FinTradeBench (Github) .

Detalles de producción que rompen sistemas reales: budget_tokens es un tope blando, pero max_tokens debe ser estrictamente mayor o la API devuelve error 400 —bug enviado a producción por equipos reales—; la respuesta es multi-bloque (thinking + text) y hay que iterar response.content (arXiv.org) . El interleaved thinking permite seguir razonando entre tool calls, útil en cadenas agénticas largas (Github) .

Tabla 6.2 — Routing técnica × tarea con evidencia

Tarea financiera Técnica / modelo recomendado Por qué Evidencia
Clasificación de sentimiento (3 clases) Zero/few-shot directo, modelo barato, temp 0, sin CoT El CoT no mejora la clasificación y puede estancar al modelo en la regla generalizable −36,3 pp en aprendizaje implícito; +331% iteraciones (Day Trading) ; sin mejora en ningún modelo (metricgate.com)
Clasificación con excepciones / reglas arbitrarias Directo + descripciones verbosas de categorías + clase "Other"; nunca CoT La palanca es la definición de categorías, no el razonamiento Descripciones detalladas = mayor palanca de precisión (metricgate.com)
Extracción de métricas de un filing Structured output estricto + grounding + citas; CoT solo si hay cómputo El contrato de schema elimina fallos de parsing; la cita verbatim habilita verificación ~100% vs ~86% cumplimiento de schema (A.L. Capital Advisory) ; errores de escala = 15% de fallos (🦜️🔗 LangChain)
Cálculo de ratios, agregaciones, QA numérico CoT + calculator tool (PAL) + self-consistency La aritmética es el modo de fallo dominante del CoT; el intérprete lo elimina GSM-Hard ~20%→61,2% (Financial Wisdom TV) ; cálculo 60,0%→76,9% (🦜️🔗 LangChain)
Tesis multi-paso, escenarios, stress testing Reasoning model (effort alto) o CoT + descomposición con esqueleto humano Tarea composicional; la planificación se beneficia del pensamiento interno o1 lidera XFinBench 67,3% (Github) ; descomposición ≥99% SCAN (arxiv.org)
Cualquier cifra derivada Tool call, jamás aritmética verbal Fallos de tokenización estructurales (9.11 vs 9.9) no se resuelven con prompts Computational split-brain documentado (langchain.js)

Interpretación. La tabla operacionaliza la economía del razonamiento: el esfuerzo se paga por token de pensamiento, de modo que enrutar mal tiene doble coste —monetario y de precisión—. La fila de clasificación contradice la intuición de 2023: para el volumen típico de un desk (miles de titulares diarios), la configuración óptima es la más barata posible —modelo ligero, temperatura cero, tres ejemplos, sin cadena de pensamiento— y añadir sofisticación degrada el resultado (Day Trading) . En el extremo opuesto, el análisis multi-paso justifica el reasoning model con esfuerzo alto, con un matiz de gobernanza: el pensamiento interno no es auditable, así que la salida debe seguir pasando por schema, citas y verificación exact-match. La fila de cálculo es la de mayor impacto institucional: la evidencia de PAL (+41 puntos porcentuales en GSM-Hard) convierte "el LLM nunca calcula" de heurística en política con ROI medible (Financial Wisdom TV) . El routing es, en síntesis, una función de coste-riesgo: se gasta razonamiento donde el error es composicional y caro, y se ahorra donde la tarea es de reconocimiento.

EXPANDE

El mapa de routing en una imagen

La tabla 6.2 condensada como árbol de decisión operativo — la pregunta nunca es «¿qué modelo es mejor?» sino «¿qué estructura tiene la tarea?»:

Diagrama

Y la magnitud de lo que se gana o se pierde al enrutar bien, con las cifras de las secciones 6.1–6.2:

Pares antes/después de la evidencia de técnicas de prompting: 3-shot, CoT, descomposición, PAL y least-to-most

Dos lecturas: la ganancia del few-shot es real pero modesta y se agota en el tercer ejemplo (+7 pp de 0 a 3-shot, plano de 3 a 5); las de PAL y la descomposición son de otro orden (+27 a +83 pp) porque atacan el modo de fallo dominante — la aritmética y la composición —, no la redacción. Enrutar mal no solo encarece: en clasificación, añadir CoT mueve la barra hacia abajo.

Prompting vs fine-tuning: criterios de decisión

La decisión no es ideológica. Con buen prompting se alcanza el 80–90% del rendimiento del fine-tuning con coste de entrenamiento cero e iteración instantánea; el fine-tuning se justifica para formato estrictamente consistente, vocabulario de dominio, coste a alto volumen y latencia (財經無界) . En dominios regulados hay un argumento adicional: "el prompt engineering no da control completo sobre la salida del modelo; en dominios de alto riesgo y regulados como legal, finanzas y salud debe usarse fine-tuning" (Elastic) . La viabilidad económica ya existe: LLMs ligeros fine-tuneados (Qwen3-8B, Llama3-8B) son competitivos en sentimiento financiero incluso con el 5% de los datos (arXiv.org) . Los criterios operativos son cuatro: (1) si el cuello de botella es formato o vocabulario, fine-tuning; si es acceso a información o razonamiento, prompting con grounding y tools; (2) si el coste de tokens de few-shot supera el coste amortizado de entrenamiento, fine-tuning; (3) si el regulador exige control demostrable de salidas, fine-tuning más structured output; (4) en ambos casos, evals continuas —los cambios de snapshot cambian el comportamiento del prompt, y OpenAI recomienda fijar snapshots en producción con suites de evaluación (towardsai.net) .

Hay, además, límites que ninguna de las dos técnicas resuelve: el look-ahead bias no se corrige con prompts (requiere datos y evaluación point-in-time) (metricgate.com) ; la incompetencia numérica es representacional y se mitiga con herramientas, no con instrucciones (langchain.js) ; y la predictibilidad de sentimiento tipo Lopez-Lira se arbitra conforme se difunde —el prompting da acceso a la capacidad, no un foso defensivo (arXiv.org) . El edge sistemático requiere datos propietarios, ejecución y gestión de riesgo; el prompting solo nunca fue una estrategia de inversión.


Ejercicios

  1. System prompt por rol. Escriba el system prompt completo de un analista de crédito que evalúa un 10-K para un comité de riesgo, con la estructura Identidad → Instrucciones → Ejemplos → Contexto. Debe incluir fecha as_of, instrucción negativa de grounding, etiquetado [HECHO]/[INFERENCIA] y prohibición de aritmética en texto. Justifique cada línea citando qué modo de fallo de la sección 6.2 mitiga; elimine las que no mitiguen ninguno.

  2. Schema con validadores semánticos. Extienda InvestmentThesis con: (a) un campo target_price: MetricValue cuya escala y unidad se validen contra revenue_ltm; (b) un @model_validator que rechace tesis con rating extremo y confidence="low" simultáneos; (c) un validador que exija evidence no nulo siempre que value no sea nulo. Explique por qué (c) no puede garantizarlo el constrained decoding.

  3. Experimento de routing. Implemente el clasificador de la Plantilla 3 en dos variantes —zero-shot directo y con CoT— sobre 200 titulares etiquetados. Mida precisión, latencia y coste de tokens; contraste con la evidencia de −36,3 pp y +331% de iteraciones (Day Trading) e identifique en qué subconjunto de titulares el CoT falla primero.

  4. Pipeline de verificación de dos pasos. Construya el pipeline del diagrama Mermaid: extractor con with_structured_output(..., include_raw=True), verificador exact-match normalizado (puntuación, separadores de miles, escala) y política fail-closed con max_retries=2. Inyecte un filing donde la cifra pedida no existe y documente si el sistema devuelve null (correcto) o una cifra fabricada (fallo); reporte la tasa de confidently wrong antes y después de hacer null parte del schema.

  5. Presupuesto de razonamiento. Configure tres rutas de un mismo agente de research —clasificación de noticias (effort mínimo), extracción de métricas (effort bajo + tools), tesis multi-paso (effort alto)— y mida coste y calidad por ruta. Añada el guardarraíl max_tokens > budget_tokens y un test de regresión que falle si se viola (Github) .

  6. Decisión prompting vs fine-tuning. Redacte una nota de una página recomendando prompting o fine-tuning para un clasificador de eventos corporativos de alto volumen en un dominio regulado, aplicando los cuatro criterios de la sección 6.4 y cuantificando el punto de cruce de costes con los precios vigentes de su proveedor.


Módulo 6 de 15 — LangChain para Trading Cuantitativo. Datos y versiones verificados a julio de 2026; precios y cifras de mercado sujetos a cambio. LangChain 1.3.14 / langchain-core 1.5.2.


EXPANDE

Recursos de élite para seguir profundizando

CHECK

Comprueba lo aprendido

Autoevaluación con feedback inmediato. No se guarda ninguna puntuación: es solo para ti.