stock-html: Página ilustrada fácil de entender de un vistazo
Convierte cualquier material en una sola página HTML: dos temas manuscritos (papel cuadriculado / pizarra), viñetas de dos paneles con personajes fijos, y todos los números verificables. Dos usos:
- Informe de acciones (
kind="stock", por defecto): una acción, un informe de ganancias, una fusión o noticia importante → un informe ilustrado completo. - Página de aprendizaje general (
kind="general"): artículos, papers, documentos técnicos, apuntes de cursos → línea principal + cadena de dependencias de conceptos + tarjetas de conceptos + ruta de estudio.
Este directorio incluye un kit de herramientas; no escribas HTML desde cero:
| Archivo | Función |
|---|---|
scripts/sketch.py | Lienzo, viñetas de dos paneles, gráficos listos, ensamblaje de página; save() realiza una verificación offline automática |
scripts/blocks.py | Bloques prediseñados: línea principal, foso competitivo, gráfico de comparación a largo plazo, tres formatos de viñetas, tabla de simulación de precio—útil para múltiples informes a la vez |
scripts/verify.py | Renderiza con Chrome headless, lee los resultados de autoverificación incrustados y toma capturas de pantalla por secciones |
assets/template.html | Plantilla de página: dos temas, filtro de vibración, sello de progreso, script de autoverificación integrado |
examples/boba_merger.py | Ejemplo de referencia completo (informe de acción ficticia), léelo antes de empezar |
references/stock-report.md | Cómo escribir cada sección del informe de acciones, disciplina de datos |
references/visual-style.md | Normas visuales, coordenadas del lienzo, reglas para SVG manuscrito |
references/qa.md | Autoverificación en tres niveles, puntos clave para mirar las imágenes, plan de respaldo sin Chrome |
Tres reglas innegociables
- El lector es principiante absoluto. Explica cada término en su primera aparición en una oración, con el original en inglés entre paréntesis. Prohibido: "como sabes", "obviamente", "no es difícil de entender".
- Primero la conclusión, luego el principio. La primera oración de cada sección debe ser la conclusión, no el contexto.
- Los números no pueden ser de memoria. Todos los números deben verificarse primero, luego calcularse con scripts, y después dibujarse. Los valores estimados deben marcarse como "indicativo", las probabilidades como "estimación subjetiva, no predicción".
Flujo de trabajo
- Lee todo el material—archivos, capturas de pantalla, enlaces que el usuario proporcione, sin omitir ninguno.
- Verifica en línea—prioriza fuentes primarias (comunicados de la empresa, 8-K, notas de prensa, informes financieros), y confirma cada número que vayas a usar. Los detalles están en "Disciplina de datos" de
references/stock-report.md. - Escribe el script de construcción con los números arriba—todas las entradas y cálculos como variables, usa
assertpara cuadrar unos con otros (desglose de cambio porcentual, diferencias de precio, dilución/incremento, múltiplos × EPS). Si no cuadran, no dibujes. - Ordena la cadena de dependencias de conceptos (8–13 conceptos)—ordena según "el concepto siguiente resuelve un problema creado por el anterior", no en el orden original del material. Si no puedes explicar qué problema del anterior resuelve el siguiente, el orden está mal.
- Ensambla la página—sigue el estilo de
examples/boba_merger.py:import sys; sys.path.insert(0, "<ruta de este skill>/scripts") from sketch import * p = Page("Título", "Subtítulo") # por defecto kind="stock" p.mainline(...); p.checkup(...); p.section(..., role="moat"); p.chain(...); p.card(...) # … p.save("out.html") # escribe archivo + verificación offline, si hay ERROR corrígelo hasta que no haya - Verificación con renderizado real—
python3 scripts/verify.py out.html --shots shots/. Debes ver[CHECK light] PASSy[CHECK dark] PASS, luego revisa cada captura (al menos dos secciones del tema claro y del oscuro). Los detalles están enreferences/qa.md. - Entrega—si el entorno tiene herramienta de publicación de Artifact, publícala (después de publicar, revisa la consola para confirmar que ambos temas son PASS); si no, entrega el archivo HTML al usuario.
- Responde al usuario—primero responde directamente a su pregunta en 2–3 oraciones (ej. "¿Han cambiado los fundamentos?"), luego enumera en 5–8 puntos lo que contiene la página, señala las diferencias con lo esperado (fechas no confirmadas, números estimados, fuentes de respaldo), y finalmente lista las fuentes.
Estructura predeterminada del informe de acciones
Cada sección siguiente debe estar presente por defecto (Page.save() te alertará si falta alguna). Esto es "como mínimo", no "solo esto": si el material tiene otros aspectos importantes (valoración vs. pares, gestión y asignación de capital, flujo de caja y deuda, concentración de clientes…), añade más section(). Cada sección de texto ≤ 4 oraciones, prioriza los gráficos.
| # | Sección | Cómo llamarlo | Preguntas a responder | Gráfico a usar |
|---|---|---|---|
| 1 | Línea principal | mainline() | ¿Qué está pasando realmente? (elegir entre: bucle principal / línea de montaje / conflicto central) | Una oración + un gráfico |
| 2 | Diagnóstico | checkup() | ¿Han cambiado los fundamentos? Cada línea con número y métrica | ✓ verde / — naranja / ✗ rojo |
| 3 | Foso competitivo | section(role="moat") | ¿Qué 2–3 cosas otros realmente no pueden copiar? ¿Qué número lo prueba? ¿Cuál es la debilidad? | Gráfico de foso + tiles |
| 4 | Cadena de dependencias | chain() | ¿Qué 8–13 conceptos hay que entender primero para entender esta empresa / noticia? | Diagrama de flujo en serpiente |
| 5 | Tarjetas de conceptos | card() × N | Por cada concepto: problema sin él → su solución → qué resuelve y a qué costo | Viñetas de dos paneles |
| 6 | Hoja de ruta técnica | section(role="roadmap") | ¿Dónde estamos ahora? ¿Cuál es el siguiente paso? ¿Qué es solo visión? | roadmap() gráfico escalonado |
| 7 | Visión a largo plazo | section(role="vision") | ¿A dónde quiere llegar la dirección en 3–5 años? ¿Alcanzable al ritmo actual? ¿Cuánto falta? | Gráfico de comparación objetivo vs. ritmo actual |
| 8 | Riesgos ocultos | section(role="risks") | 4–6 cosas que no están en el comunicado ni en la narrativa alcista; ¿qué número es la señal de alerta de cada una? | risk_matrix() + tabla de alerta |
| 9 | Hitos clave | section(role="timeline") | ¿Qué días en los próximos 6–12 meses se sabrán resultados? ¿Qué fechas no están confirmadas? | timeline() + tabla de fechas |
| 10 | Simulación de precio | section(role="paths") | 2–3 escenarios: ¿qué debe ocurrir en cada uno? ¿En qué precio se traduce? ¿Probabilidad subjetiva? | paths_chart() + tabla de escenarios |
| 11 | Regla | section(role="ruler") | 2–3 indicadores para medir lo bueno y lo malo; cada solución mejora cuál y sacrifica cuál | ruler_chart() + tabla comparativa |
| 12 | Versión para principiantes (opcional) | section(role="eli5") | El mecanismo más contraintuitivo, paso a paso con cálculos | Gráfico de cascada + pasos + tabla comparativa |
| 13 | Ruta de estudio | route() | 3–4 paradas: por qué ir, cuánto tiempo, enlace | Diagrama de línea de metro |
| — | Pie de página | sources() | Todas las fuentes + "Solo con fines educativos, no constituye consejo de inversión" | — |
El detalle de cada sección, frases hechas y contraejemplos están en references/stock-report.md (léelo antes de escribir un informe de acciones).
Estructura de la página de aprendizaje general
Page(..., kind="general"): línea principal → cadena de dependencias de conceptos → tarjetas de conceptos → regla (2–3 indicadores clave del área, dibujados en un mismo gráfico) → versión para principiantes (opcional) → ruta de estudio. Sin diagnóstico, simulación de precio ni descargo de responsabilidad.
Reglas que aplican a toda la página
- Personajes fijos. Todos los gráficos usan el mismo conjunto de personajes; no se cambian entre conceptos. Por defecto para acciones: A, B, C (tres accionistas antiguos) + D (un nuevo accionista); pastel = acciones, moneda = ganancias. Explica los personajes en una línea pequeña debajo del gráfico de línea principal.
- Números a escala reducida. Representa 921 millones de acciones como 6 pasteles, $1,000 millones de ganancias como 10 monedas; la proporción debe coincidir con los datos reales. Marca en el gráfico "valor indicativo".
- Tarjetas de conceptos solo dos líneas: "qué resuelve" y "a qué costo". El costo no puede dejarse vacío ni escribirse "prácticamente sin costo"—si no encuentras el costo, no lo has pensado bien.
- Colores fijos con significado semántico (consistente en toda la página): verde = en curso (negocio, ganancias); naranja = nuevo (nuevo evento, nuevo accionista); azul = acumulado (acciones, efectivo, valor); línea roja discontinua = cancelado / liberado (pérdida). Sello en morado.
Requisitos estrictos (revisa uno por uno antes de publicar)
- Texto de cada viñeta ≤ 15 caracteres (contando números y símbolos; en páginas en inglés ≤ 32 caracteres).
- El texto nunca debe tocar los bordes ni superponerse.
- Prioriza gráficos; cada sección de texto ≤ 4 oraciones.
- Todos los gráficos son SVG manuscrito en línea (generado con
sketch.py). No usar Chart.js / D3 / Mermaid. - CSS, JS, SVG todo en línea en un solo archivo HTML; sin enlaces externos (incluyendo Google Fonts—la CSP de algunos entornos Artifact lo bloquearía).
- El texto no debe entrar en el filtro de vibración ni tener
transform(Canvas.text()ya lo garantiza; al escribir SVG a mano, ten cuidado). - Los enlaces de la ruta de estudio deben abrirse y verificarse con una herramienta de rastreo; solo si el contenido coincide se marca
verified=True. Si está bloqueado o no se abre, cámbialo u omite laurl(la página mostrará "debe buscar por su cuenta"). Inventar enlaces es el fallo más grave de este skill. - No menciones las posiciones u opciones del usuario; analiza solo la acción en sí; no des instrucciones de compra o venta.
verify.pydebe pasar en ambos temas, y debes haber revisado las capturas.
Referencia rápida del kit de herramientas
# Lienzo: colores solo por nombre semántico ink / ink2 / green / orange / blue / red / purple
c = Canvas(760, 300, "nombre") # gráfico grande 760 de ancho, tamaño de fuente ≥ 12
c.rect / line / arrow / curve / circle / path / poly / bar # fill="green" claro, "green!" sólido
c.text(x, y, "texto", size=14, anchor="middle", color="ink", bold=False)
c.person(cx, top, "A", "blue", mood="happy") # personaje fijo (aprox. 30×60)
c.pie(cx, cy, r, ["blue"]*6 + ["orange"]*2, labels) c.coins(x, y, 12, "green", cols=4)
c.shop(cx, base, label="BOBA") c.doc(x, y) c.bubble(x, y, w, h) c.tick / cross / minus
# Viñeta de dos paneles: 560×232; centro del panel izquierdo x=140, centro del derecho x=420; tu área de dibujo y 44–188
k = Comic("Texto izquierdo ≤15 chars", "Texto derecho ≤15 chars")
# Gráficos predefinidos (todos devuelven Canvas)
snake(nodes) metro(stations) timeline(events) roadmap(stages) risk_matrix(items)
paths_chart(history, scenarios) ruler_chart(points, xr, yr, iso, gauge) waterfall(steps)
# Página
p = Page(title, subtitle, kind="stock", notice=None)
p.mainline(una_oración, canvas, kind="conflicto_central", note="Personajes fijos:…")
p.checkup([("ok" | "mid" | "bad", "línea con número"), ...])
p.chain([(nombre_concepto, nuevo_problema_que_crea), ...])
p.card(name, en, definition, comic, solves, cost, stamp="next" | "redo" | "done")
p.section(title, prose, canvas=, table=(headers, rows), steps=[…], tiles=[…], after=, note=, role=)
p.route([Stop(name, why, time, url, link_text, verified=True), ...])
p.sources([(título, url), ...]); p.save("out.html")
Para páginas en inglés: llama a set_lang("en") antes de crear cualquier Comic / Page. Los detalles de los parámetros de cada función están en los docstrings de scripts/sketch.py.
Para hacer varios informes a la vez (ej. los diez principales componentes de un ETF), usa los bloques de scripts/blocks.py. Cada informe solo necesita escribir los números y el texto:
from blocks import * # también importa todas las herramientas de sketch
m = mainline_tug(título_izquierdo, [(etiqueta, valor, es_guía)×3], nota_unidad, problema, subproblema, [(fuerza, color)×3], título_derecho, [(fecha, precio), ...], "−6%")
mo = moat(["① Más profundo", "② Segundo", "③ Más superficial"], "TICK")
vi = vision([(valor, etiqueta1, etiqueta2, color, discontinua)×3], gap_between=(1, 2), note="algoritmo…")
c1 = C_bars(desc_izquierdo, desc_derecho, [(etiqueta, valor, color)], [(etiqueta, valor, color)], lnote=, rnote=, fmt="%g") # barras comparativas
c2 = C_talk(desc_izquierdo, desc_derecho, "A", "texto en burbuja", "objeto_problema", "D", "objeto_solución", "nota_una_línea") # personaje + objetos
c3 = C_flow(desc_izquierdo, desc_derecho, ["caja", "caja"], ["caja", "caja", "caja"], rnote="nota_una_línea") # cajas de flujo
sc = [scen("ruta", probabilidad, EPS_indicativo, múltiplo_bajo, múltiplo_alto, "green"), ...]; expect(sc); scen_table(sc, qué_debe_ocurrir)
p = Page(..., notice=disclaimer("2026-11-11"))
Los gráficos de los bloques tienden a ser "estándar"; para un informe individual con más detalle, sigue usando Canvas / Comic a mano. Ambos se pueden mezclar.
Si los gráficos predefinidos no son suficientes, dibuja directamente con las formas básicas de Canvas—el kit es un punto de partida, no una jaula; mientras el texto use c.text(), la verificación seguirá funcionando.
Cuando no se puede ejecutar Python
Copia assets/template.html, reemplaza {{BODY}} con el HTML + SVG manuscrito, y llena los demás marcadores de posición ({{TITLE}} {{LANG}} {{CAPMAX}} {{PAGE_KEY}} {{LABELS}}) con los valores de Page.html() en sketch.py. El SVG manuscrito debe cumplir con las coordenadas del lienzo y las convenciones de clase en references/visual-style.md (svg.chk, rect.panel, text.cap) para que la autoverificación integrada lo reconozca. Abre página.html?check=1 en el navegador; la barra de verificación en la parte inferior debe ser verde PASS.
Modos de fallo comunes
- ❌ Conceptos ordenados según el material original → la cadena de dependencias no aporta información, reordenar
- ❌ "¿A qué costo?" escrito como "casi sin costo" → no lo has pensado bien, vuelve a pensar
- ❌ Personajes cambiados entre gráficos de diferentes conceptos → el lector debe volver a identificar a los personajes, unificar
- ❌ Foso competitivo solo con adjetivos ("marca fuerte", "tecnología líder"), sin números ni métricas → reemplazar con evidencia
- ❌ Visión de la dirección escrita como guía de resultados en la sección de visión a largo plazo → marcar claramente como objetivo y comparar con el ritmo actual
- ❌ Riesgos ocultos escritos como frases hechas ("incertidumbre macro", "competencia intensificada") → escribir la ruta de transmisión concreta y el número a vigilar
- ❌ Fechas no anunciadas escritas como confirmadas → escribir "se espera a principios de diciembre (el año pasado fue el 2/12, sujeto al comunicado de la empresa)"
- ❌ Probabilidades y precios sin marcar "estimación subjetiva / indicativo" → el lector lo tomará como predicción
- ❌ Creer en medios secundarios que dicen "sin novedades" sin verificar → primero consultar los comunicados de la empresa y los documentos de la SEC
- ❌ Enlaces de la ruta de estudio sin abrir y verificar → el más grave
- ❌ Texto principal extenso → cada sección ≤ 4 oraciones
- ❌ No ejecutar
verify.pyni revisar las capturas antes de entregar → páginas con texto superpuesto enviadas