stock-html: 한 번에 이해하는 손그림 해설 페이지
자료를 하나의 단일 HTML 파일로 만듭니다: 모눈종이 / 칠판 두 가지 손그림 테마, 고정된 캐릭터의 두 칸 만화, 모든 숫자는 다시 계산 가능. 두 가지 용도:
- 주식 보고서(
kind="stock", 기본값): 한 주식, 하나의 실적 보고서, 하나의 M&A 또는 주요 뉴스 → 완전한 그림 보고서. - 일반 학습 페이지(
kind="general"): 기사, 논문, 기술 문서, 강의 노트 → 메인라인 + 개념 의존성 체인 + 만화 카드 + 학습 경로.
이 디렉토리에는 도구 모음이 포함되어 있습니다. HTML을 처음부터 직접 작성하지 마십시오:
| 파일 | 역할 |
|---|---|
scripts/sketch.py | 캔버스, 두 칸 만화, 기성 차트, 전체 페이지 조립; save() 시 자동 오프라인 레이아웃 검사 |
scripts/blocks.py | 반제품 블록: 메인라인 차트, 해자, 장기 대조표, 세 가지 두 칸 만화 템플릿, 주가 시나리오 표——여러 보고서를 한 번에 작성할 때 사용 |
scripts/verify.py | 실제 Chrome 렌더링으로 페이지 내장 자체 점검 결과를 읽고, 구간별 스크린샷 촬영 |
assets/template.html | 페이지 템플릿: 두 테마, 떨림 필터, 도장 진행률, 내장 자체 점검 스크립트 |
examples/boba_merger.py | 완전한 참고 코드(가상 회사의 개별 주식 보고서), 작업 시작 전에 먼저 읽어볼 것 |
references/stock-report.md | 주식 보고서 각 섹션 작성법, 데이터 규율 |
references/visual-style.md | 시각적 규범, 캔버스 좌표, 손글씨 SVG 규칙 |
references/qa.md | 3단계 자체 점검, 그림 보는 요령, Chrome 없을 때의 대체 방법 |
세 가지 불가침 원칙
- 독자는 해당 주제에 대해 전혀 모른다. 각 전문 용어가 처음 등장할 때 한 문장으로 설명하고, 괄호 안에 영문 원어를 병기합니다. "아시다시피", "명백히", "쉽게 이해할 수 있듯이" 등의 표현은 금지.
- 결론 먼저, 원리 나중. 각 섹션의 첫 문장은 반드시 결론이어야 하며, 배경 설명이 아닙니다.
- 숫자는 절대 기억에 의존하지 않는다. 모든 숫자는 먼저 확인하고, 스크립트로 계산한 후에 그림을 그립니다. 추정값은 "모식도"라고 표시하고, 확률은 "주관적 추정, 예측이 아님"이라고 표시합니다.
작업 흐름
- 모든 자료를 읽는다——사용자가 제공한 파일, 스크린샷, 링크를 빠짐없이 확인합니다.
- 온라인으로 사실 확인——1차 출처(회사 공시, 8-K, 보도 자료, 실적 보고서)를 우선 사용하고, 사용할 각 숫자의 근거를 확보합니다. 세부 사항은
references/stock-report.md의 "데이터 규율" 참조. - Build 스크립트를 작성하고, 숫자는 맨 위에 배치한다——모든 입력과 추정값을 변수로 만들고,
assert를 사용하여 상호 대조(등락률 분해, 가격 차이, 증대/희석, 배수 × EPS)합니다. 계산이 맞지 않으면 그림을 그리지 마십시오. - 개념 의존성 체인을 정리한다(8–13개 개념)——"다음 개념은 이전 개념이 초래한 문제를 해결하기 위한 것"이라는 순서로 배열하며, 자료의 원래 순서를 따르지 않습니다. 어떤 개념이 이전 개념의 어떤 문제를 해결하는지 설명할 수 없다면 순서가 잘못된 것입니다.
- 페이지를 조립한다——
examples/boba_merger.py의 방식을 따릅니다:import sys; sys.path.insert(0, "<이 skill 디렉토리>/scripts") from sketch import * p = Page("제목", "부제목") # 기본 kind="stock" p.mainline(...); p.checkup(...); p.section(..., role="moat"); p.chain(...); p.card(...) # … p.save("out.html") # 파일 쓰기 + 오프라인 사전 검사, ERROR가 없을 때까지 수정 - 실제 렌더링 검사——
python3 scripts/verify.py out.html --shots shots/.[CHECK light] PASS와[CHECK dark] PASS를 반드시 확인한 후, 스크린샷을 하나씩 검토(밝은 테마, 어두운 테마 각각 최소 두 구간 이상). 세부 사항은references/qa.md참조. - 납품——환경에 Artifact 게시 도구가 있으면 게시(게시 후 콘솔을 확인하여 두 테마 모두 PASS인지 확인); 없으면 HTML 파일을 사용자에게 전달합니다.
- 사용자에게 응답——먼저 2–3문장으로 그의 질문에 직접 답변(예: "펀더멘털이 변했나요?")하고, 5–8개 요점으로 페이지에 무엇이 있는지 설명하며, 예상과 다른 점(날짜 미확인, 역추정된 숫자, 폰트 폴백)을 명시한 후, 마지막에 출처를 나열합니다.
주식 보고서의 기본 구조
아래 각 섹션은 기본적으로 모두 포함되어야 합니다(Page.save()는 누락된 섹션에 대해 경고합니다). 이것은 "최소한 있어야 할 것"이지 "이것만 있어야 한다"는 의미가 아닙니다. 자료에 다른 중요한 점(밸류에이션 및 경쟁사 비교, 경영진과 자본 배분, 현금 흐름과 부채, 고객 집중도 등)이 더 있다면 section()을 추가하세요. 각 섹션 본문은 ≤ 4문장이며, 그림 위주입니다.
| # | 섹션 | 호출 방법 | 반드시 답해야 할 질문 | 사용할 그림 |
|---|---|---|---|---|
| 1 | 메인라인 | mainline() | 이 일은 도대체 무엇을 하는 것인가? (메인 루프 / 파이프라인 / 핵심 모순 중 하나 선택) | 한 문장 + 한 장의 그림 |
| 2 | 건강 검진표 | checkup() | 펀더멘털이 변했나요? 각 행에 숫자와 기준 포함 | ✓ 초록 체크 / — 주황 가로줄 / ✗ 빨간 엑스 |
| 3 | 핵심 경쟁력 | section(role="moat") | 다른 회사가 정말 따라할 수 없는 2–3가지는? 그 증거는 어떤 숫자인가? 약점은? | 해자 그림 + tiles |
| 4 | 개념 의존성 체인 | chain() | 이 회사 / 이 뉴스를 이해하기 위해 먼저 알아야 할 8–13개 개념은? | 뱀형 순서도 |
| 5 | 개념 카드 | card() × N | 각 개념: 없을 때의 불편 → 해결 방법 → 해결된 것과 대가 | 두 칸 만화 |
| 6 | 기술 로드맵 | section(role="roadmap") | 현재 어디까지 왔는가, 다음 단계는 무엇인가, 어떤 것들이 단순한 비전인가? | roadmap() 계단 그림 |
| 7 | 장기 비전 | section(role="vision") | 경영진이 3–5년 후에 어디로 가려 하는가? 현재 속도로 도달할 수 있는가, 얼마나 차이가 나는가? | 목표 vs 현재 속도 비교 그림 |
| 8 | 숨은 위험 | section(role="risks") | 공시와 매수 측 내러티브에 적히지 않은 4–6가지; 각각의 조기 경보 신호는 어떤 숫자인가? | risk_matrix() + 경보 표 |
| 9 | 주요 일정 | section(role="timeline") | 향후 6–12개월 중 결과가 나올 날짜는? 아직 확인되지 않은 날짜는? | timeline() + 일정표 |
| 10 | 주가 시나리오 | section(role="paths") | 2–3가지 경로 각각에 필요한 상황, 예상 가격대, 주관적 확률은? | paths_chart() + 시나리오 표 |
| 11 | 가치 평가 자 | section(role="ruler") | 좋고 나쁨을 측정하는 2–3개 지표; 각 해결책이 어떤 지표를 개선하고 어떤 것을 희생하는가? | ruler_chart() + 대조표 |
| 12 | 초보자용 버전 (필요시) | section(role="eli5") | 가장 반직관적인 메커니즘을 단계별로 계산식과 함께 설명 | 폭포수 차트 + 단계 + 비교표 |
| 13 | 학습 경로 | route() | 3–4개 정류장: 가는 이유, 소요 시간, 링크 | 지하철 노선도 |
| — | 바닥글 | sources() | 전체 출처 + "학습 목적으로만 사용되며, 투자 조언이 아닙니다" | — |
각 섹션의 작성법, 흔한 빈말 및 반례는 **references/stock-report.md(주식 보고서 작성 전 필독)**를 참조하세요.
일반 학습 페이지의 구조
Page(..., kind="general"): 메인라인 → 개념 의존성 체인 → 개념 카드 → 가치 평가 자(이 분야의 2–3개 지표를 한 그림에 표시) → 초보자용 버전 (필요시) → 학습 경로. 건강 검진표, 주가 시나리오 및 면책 조항은 없습니다.
페이지 전체에 적용되는 규칙
- 고정 캐릭터. 페이지의 모든 그림은 동일한 캐릭터 세트를 사용하며, 다른 개념에서 캐릭터를 바꾸지 않습니다. 주식 기본값: A, B, C 세 명의 기존 주주 + D 한 명의 신규 주주; 파이 = 주식, 코인 = 이익. 메인라인 그림 아래에 한 줄의 작은 글씨로 캐릭터를 설명합니다.
- 숫자 축소 버전. 9.21억 주를 6조각의 파이로, 10억 달러 이익을 10개의 코인으로 그립니다; 비율은 실제 데이터와 일치해야 하며, 그림에 "모식값"이라고 표시합니다.
- 개념 카드는 두 줄만 작성: "해결된 것"과 "대가". 대가는 비워두거나 "대가가 거의 없다"고 쓰지 마십시오——대가를 찾을 수 없다면 제대로 생각하지 못한 것입니다.
- 고정 색상 의미(페이지 전체 일관): 초록 = 진행 중인 것(사업, 이익); 주황 = 새로 온 것(새로운 이벤트, 새 주주); 파랑 = 저장된 것(주식, 현금, 가치); 빨간 점선 = 폐기/해제된 것(손실). 도장은 보라색 사용.
하드 요구 사항 (게시 전 하나씩 확인)
- 각 만화 칸의 설명文字 ≤ 15자(숫자와 기호 포함; 영문 페이지 ≤ 32자).
- 文字가 절대 프레임을 벗어나거나 서로 겹치지 않아야 합니다.
- 그림 위주, 본문은 각 섹션 ≤ 4문장.
- 모든 그림은 손글씨 인라인 SVG(
sketch.py로 생성)입니다. Chart.js / D3 / Mermaid를 사용하지 않습니다. - CSS, JS, SVG는 모두 하나의 HTML 파일에 인라인으로 포함; 외부 링크를 추가하지 않습니다(Google Fonts 포함——일부 Artifact 환경의 CSP가 차단할 수 있음).
- 文字는 떨림 필터에 포함되지 않으며,
transform을 적용하지 않습니다(Canvas.text()가 이미 보장; 손글씨 SVG 작성 시 스스로 주의). - 학습 경로의 링크는 반드시 크롤링 도구로 열어서 확인하고, 내용이 일치하는 경우에만
verified=True로 작성합니다. 차단되거나 열리지 않으면 다른 링크를 사용하거나url을 제공하지 않습니다(페이지에 "직접 검색 필요"라고 표시됨). 링크를 조작하는 것은 이 스킬의 가장 심각한 실패입니다. - 사용자의 포지션과 옵션은 언급하지 않고, 주식 자체만 분석합니다; 매매 지시를 하지 않습니다.
verify.py에서 두 테마 모두 PASS하고, 스크린샷을 확인했습니다.
도구 상자 요약
# 캔버스: 색상은 의미론적 이름만 사용: ink / ink2 / green / orange / blue / red / purple
c = Canvas(760, 300, "이름") # 큰 그림 760 너비, 글꼴 크기 ≥ 12
c.rect / line / arrow / curve / circle / path / poly / bar # fill="green" 밝은색, "green!" 채움
c.text(x, y, "文字", size=14, anchor="middle", color="ink", bold=False)
c.person(cx, top, "A", "blue", mood="happy") # 고정 캐릭터 사람(약 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
# 두 칸 만화:560×232; 왼쪽 칸 중심 x=140, 오른쪽 칸 중심 x=420; 당신의 그리기 영역 y 44–188
k = Comic("왼쪽 칸 설명 ≤15자", "오른쪽 칸 설명 ≤15자")
# 기성 차트(모두 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 = Page(title, subtitle, kind="stock", notice=None)
p.mainline(한 문장, canvas, kind="핵심 모순", note="고정 캐릭터:…")
p.checkup([("ok" | "mid" | "bad", "숫자가 포함된 한 줄"), ...])
p.chain([(개념명, 그 개념이 가져오는 새 문제), ...])
p.card(name, en, definition, comic, solves, cost, stamp="next" | "redo" | "done")
p.section(title, prose, canvas=, table=(표 머리, 행), steps=[…], tiles=[…], after=, note=, role=)
p.route([Stop(name, why, time, url, link_text, verified=True), ...])
p.sources([(제목, url), ...]); p.save("out.html")
영문 페이지: Comic / Page를 생성하기 전에 set_lang("en")을 호출하세요. 각 함수의 매개변수 세부 사항은 scripts/sketch.py의 docstring을 직접 확인하세요.
여러 보고서를 한 번에 작성할 때(예: ETF의 상위 10개 구성 종목)는 scripts/blocks.py의 블록을 사용하여 각 보고서에 대해 숫자와 문장만 작성하면 됩니다:
from blocks import * # sketch의 모든 도구를 함께 가져옴
m = mainline_tug(왼쪽 제목, [(레이블, 값, 가이드 여부)×3], 단위 주석, 질문, 하위 질문, [(힘, 색상)×3], 오른쪽 제목, [(날짜, 주가), ...], "−6%")
mo = moat(["① 가장 깊음", "② 그 다음", "③ 가장 얕음"], "TICK")
vi = vision([(값, 레이블1, 레이블2, 색상, 점선)×3], gap_between=(1, 2), note="알고리즘…")
c1 = C_bars(왼쪽 설명, 오른쪽 설명, [(레이블, 값, 색상)], [(레이블, 값, 색상)], lnote=, rnote=, fmt="%g") # 전후 비교 막대
c2 = C_talk(왼쪽 설명, 오른쪽 설명, "A", "말풍선 안의 문장", "불편한 물건", "D", "해결 물건", "한 줄 주석") # 캐릭터 + 물건
c3 = C_flow(왼쪽 설명, 오른쪽 설명, ["상자", "상자"], ["상자", "상자", "상자"], rnote="한 줄 주석") # 흐름 상자
sc = [scen("경로", 확률, 모식EPS, 낮은 배수, 높은 배수, "green"), ...]; expect(sc); scen_table(sc, 필요한 상황)
p = Page(..., notice=disclaimer("2026-11-11"))
블록으로 그린 그림은 "표준 부품" 스타일입니다; 단일 보고서를 더 정교하게 그리고 싶다면 여전히 Canvas / Comic으로 직접 그릴 수 있으며, 둘을 혼용할 수 있습니다.
기성 차트가 충분하지 않을 때는 Canvas의 기본 도형을 직접 사용하여 그리세요——도구 상자는 시작점이지 제약이 아닙니다; 文字가 모두 c.text()를 통해 작성되는 한 검사는 계속 적용됩니다.
Python을 실행할 수 없을 때
assets/template.html을 복사하고, {{BODY}}를 직접 작성한 HTML + 인라인 SVG로 바꾼 후, 나머지 플레이스홀더({{TITLE}} {{LANG}} {{CAPMAX}} {{PAGE_KEY}} {{LABELS}})는 sketch.py의 Page.html()에 있는 값으로 채웁니다. 손글씨 SVG는 반드시 references/visual-style.md의 캔버스 좌표와 class 규칙(svg.chk, rect.panel, text.cap)을 따라야 내장 자체 점검이 인식할 수 있습니다. 브라우저에서 페이지.html?check=1을 열면, 하단의 검사 막대가 반드시 초록색 PASS여야 합니다.
일반적인 실패 패턴
- ❌ 개념을 자료의 원래 순서대로 나열 → 의존성 체인에 정보량이 없음, 재배열 필요
- ❌ "대가는 무엇인가"를 "대가가 거의 없다"고 작성 → 제대로 생각하지 못함, 다시 생각 필요
- ❌ 다른 개념의 그림에서 캐릭터를 변경 → 독자가 캐릭터를 다시 인식해야 함, 통일 필요
- ❌ 핵심 경쟁력이 형용사("브랜드 강력", "기술 선도")에 그치고 숫자와 기준이 없음 → 증거로 대체
- ❌ 경영진의 비전을 실적 가이던스처럼 장기 비전에 작성 → 목표임을 명확히 표시하고 현재 속도와 대조
- ❌ 숨은 위험을 "거시적 불확실성", "경쟁 심화" 같은 일반적인 표현으로 작성 → 구체적인 전달 경로와 주시할 숫자를 작성
- ❌ 공시되지 않은 날짜를 확정적으로 기재 → "12월 초 예상(작년은 12/2, 회사 공시 기준)"으로 작성
- ❌ 확률과 가격대에 "주관적 추정 / 모식"을 표시하지 않음 → 독자가 예측으로 받아들임
- ❌ 2차 미디어에서 "새로운 소식 없음"이라고 하면 그대로 믿음 → 먼저 회사 공시와 SEC 서류 확인
- ❌ 본문을 장문으로 작성 → 각 섹션 ≤ 4문장
- ❌
verify.py를 실행하지 않고, 스크린샷을 보지 않고 납품 → 文字가 겹친 페이지가 발송됨