virtual-insanity
← 리포트 목록

260421 analyst reports audit

2026-04-21 analyst [analyst, audit, patch, no-send, hermes]

2026-04-21 4개 analyst 리포트 전수 감사·교정

결론

  • 실측 체크: 15/15 PASS (/tmp/analyst_audit_260421_v2/checks.md)
  • 재발송 없음: 모든 analyst 본문 검증은 ANALYST_COMMON_NO_SEND=1 또는 dry-run으로 수행했다. 정유/탱커 collector만 A1 복구 목적의 수집 재실행이며 알림 전송 로직을 호출하지 않았다.
  • 내일 07시 자동 발송부터 반영: sender/collector 원본을 수정했고, DM/알림센터 재발송은 하지 않았다.

PASS/FAIL 체크리스트

이슈 판정 증거
A1 정유/탱커 수집 0건·4/14 stale PASS 정유 2026-04-21T08:30:31+09:00, 6/6 수집. 탱커 2026-04-21T08:30:34+09:00, 7/7 수집.
A2 섹터 PER ±50%+ 이상치 PASS peer 최소 5개, 2σ 이상치 제거, 중앙값 기준, ±50% 초과 노출 제외.
A3 PEG 과도값 PASS PEG <0.3 또는 >4.0, 성장률 누락/음수/과대 가정은 PEG 저신뢰로 표시.
B1 FX (-) 의미 불명 PASS DXY 98.23(보합) 형식으로 변경.
B2 WTI 출처 불일치 PASS 매크로 WTI가 oil-supply-monitor/yfinance CL=F provenance 우선 사용. 기존 WTI 82.59 제거.
B3 Kpler/한국 비축유 문장 혼선 PASS “호르무즈: Kpler … / 한국 비축유: KNOC/MOTIE …”로 분리.
C1 stale 채권 트레이더 브리핑 주입 PASS STALE DATA WARNING, 입력 자료 N일 전 credit markdown 필터링.
C2 DART 단순 나열 PASS portfolio/watchlist 관련 또는 중대 이벤트만 노출. 부도/거래정지 등은 🚨.
C3 Top 3 테마 1개만 노출 PASS fallback 포함 3개 고정 생성.
D1 Technical 보조 해석 YAML 노출 PASS frontmatter 파싱 후 title/body만 사용. source_channel, original_url 제거.
D2 WTI 1주 -13.3% 기준점 불명 PASS WTI -13.3%(2026-04-13→2026-04-20)처럼 기준 구간 표시.
D3 data_quality_note PASS VIX9D/Put-Call/AAII 대체 명시는 유지.
E1 PM raw JSON 노출 PASS {"type":"stale_input"...} 대신 “매크로 분석이 2026-04-20 기준(1일 전)…”로 치환.
E2 섹터 비중 합계 85% PASS 기타 기존 보유·미배정 15% 추가, 합계 100%.
E3 PM 해석 주입 소스 메타 노출 PASS daily index/숫자 suffix/source meta 제거.

수정 파일과 백업

파일 백업 주요 수정
/Users/ron/.hermes/workspace/scripts/pipeline/vault_fundamental_bridge.py .bak-analyst-audit-20260421 PEG 신뢰도 플래그, 섹터 PER robust median/2σ/min5/±50% 가드
/Users/ron/.hermes/workspace/scripts/fundamental_context_filter.py .bak-analyst-audit-20260421 stale credit 필터, DART 중요도 필터, Top3 테마 3개 보장
/Users/ron/.hermes/workspace/scripts/macro_redesign_report.py .bak-analyst-audit-20260421 FX 보합 표기, oil monitor WTI 우선, Kpler/비축유 문장 분리, top-level date/as_of 오늘로 강제
/Users/ron/.hermes/workspace/scripts/technical_context_filter.py .bak-analyst-audit-20260421 NEPCON frontmatter 제거, WTI 주간 변화 기준일 표시
/Users/ron/.hermes/workspace/scripts/pm_context_filter.py .bak-analyst-audit-20260421 stale/conflict 한국어화, 미배정 15% 추가, source label 정리
/Users/ron/.hermes/workspace/scripts/shared/vault_industry_context.py .bak-analyst-audit-20260421 수집 0건/stale 산업맥락을 정상처럼 표시하지 않도록 가드
/Users/ron/.hermes/workspace/scripts/analyst_common_sender.py .bak-analyst-audit-20260421 PM 해석 주입 소스 라벨 클린업

전체 diff 캡처: /tmp/analyst_audit_260421_v2/diffs.txt (587 lines)

원인·패치 상세

A. 펀더 브리핑

A1. 정유/탱커 수집 0건 + 2026-04-14 stale

  • 원인: memory/refining-indicators/latest.json, memory/tanker-indicators/latest.json가 4/14 0건 상태였다. 산업맥락 formatter가 이를 정상 맥락처럼 보여줄 수 있었다.
  • 조치:
  • 정유 수동 수집: 6/6 성공.
  • 탱커 수동 수집: 7/7 성공.
  • shared/vault_industry_context.py:164에서 collected==0 또는 2일 이상 stale이면 “수집 불완전/재실행 필요”로 표시하게 수정.
  • 검증:
  • refining_tracker.py --collect 결과: collected=6 failed=0.
  • tanker_tracker.py --collect 결과: collected=7 failed=0.

A2. 섹터 PER 이탈 숫자 이상

  • 원인: peer 수가 작은 섹터 평균이 한두 종목에 끌리면 -65%, +138% 같은 숫자가 그대로 노출될 수 있었다.
  • 조치: vault_fundamental_bridge.py:410-485
  • peer 최소 5개 미만이면 노출 제외.
  • PER 2σ 이상치 제거.
  • 평균 대신 robust median 기준.
  • 계산 premium이 ±50% 초과면 섹터 분류/모수 문제로 보고 DM 노출 제외.
  • 검증: 코드 검사 + py_compile 통과.

A3. PEG 수치 재검증

  • 원인: 성장률 출처가 없거나 비정상인 PEG도 동일 신뢰도로 표시됐다.
  • 조치: vault_fundamental_bridge.py:109
  • 성장률 누락/음수/150% 초과, PEG <0.3 또는 >4.0이면 PEG 저신뢰.
  • 기존 값은 삭제하지 않고 “저신뢰 사유”를 붙여 오해를 줄임.
  • 검증: fundamental_collector.py --dry-run에서 PEG 저신뢰 (...) 출력 확인.

B. 매크로 브리핑

B1. (-) 의미 불명

  • 원인: 변화율 누락/0 값을 (-)로 렌더링.
  • 조치: macro_redesign_report.py:189에서 누락·0에 가까운 변화는 보합으로 표시.
  • 검증 샘플:
  • DXY 98.23(보합)
  • EUR/USD 1.18(보합)
  • USD/JPY 159.2(보합)

B2. WTI 출처 불일치

  • 원인: 매크로가 market-indicators 값을 우선 사용해 oil-supply-monitor와 다른 숫자가 나왔다.
  • 조치: macro_redesign_report.py:213oil_indicator() 추가. WTI/Brent는 oil-supply-monitor provenance를 우선 사용.
  • 검증 샘플:
  • WTI 86.47(2026-04-17 yfinance CL=F)
  • WTI 82.59 미검출.
  • 비고: 해리 지적의 $83.85는 당시 oil pipeline 기준값이고, 현재 oil-supply-monitor 최신 state는 $86.47로 확인됐다. 핵심 패치는 하드코딩이 아니라 동일 출처 우선이다.

B3. Kpler/한국 비축유 문장 혼선

  • 원인: Kpler transit 데이터와 한국 비축유 근거가 한 문장에 섞였다.
  • 조치: macro_redesign_report.py:372 문장 분리.
  • 검증 샘플:
  • 호르무즈: 부분봉쇄 (Kpler 2026-04-20 20척+ 통과) / 한국 비축유: 200일분 (KNOC/MOTIE 2026-04-06)

C. 펀더 리포트

C1. stale 채권 브리핑 주입

  • 원인: credit/newsletter context가 stale warning이 붙은 자료도 그대로 주입했다.
  • 조치: fundamental_context_filter.py:560에서 STALE DATA WARNING, 입력 자료 N일 전, stale data 패턴 제외.
  • 검증: 재생성 본문에 2026-04-21/04-20 자료만 노출, STALE DATA WARNING 미검출.

C2. DART 공시 단순 나열

  • 원인: DART 공시를 관련성/중요도 없이 최신순 나열.
  • 조치: fundamental_context_filter.py:268
  • 포트폴리오/watchlist 관련 공시 또는 부도·회생·상장폐지·거래정지·불성실공시·감사의견·관리종목 등 중대 이벤트만 통과.
  • 중대 이벤트는 🚨 prefix.
  • 검증 샘플:
  • 🚨 DART 유일에너테크(340930) — 주요사항보고서(부도발생)

C3. Top 3 테마 1개만 노출

  • 원인: theme source가 부족하면 1개만 남는 구조.
  • 조치: fundamental_context_filter.py:670에서 fallback 포함 unique 3개 보장.
  • 검증 샘플:
  • 퀄리티 현금흐름 선호
  • 공시 이벤트 선별
  • 크레딧 비용 점검

D. 테크니컬 리포트

D1. YAML frontmatter 원문 노출

  • 원인: NEPCON markdown을 그대로 context snippet으로 잘라 넣었다.
  • 조치: technical_context_filter.py:233 _split_frontmatter_text() 추가. frontmatter는 metadata로 분리하고 본문에는 title/body만 사용.
  • 검증 샘플:
  • nepcon-premium: 미국 키친사이클 계산 업데이트 — 미국 키친사이클 계산 업데이트
  • ---, source_channel, original_url 미검출.

D2. WTI 1주 변화 기준점 불명

  • 원인: 1주 -13.3% 산출의 시작/끝 날짜가 표시되지 않았다.
  • 조치: technical_context_filter.py:415, :783에서 perf_basis() 추가.
  • 검증 샘플:
  • WTI 1주 -13.3%, MA20 -11.5% 기준 2026-04-13→2026-04-20

D3. data_quality_note

  • 조치 없음. 해리 지적대로 “솔직한 명시 OK”라 유지.
  • 검증: no-send 본문에 VIX9D·Put/Call·AAII는 로컬 수집 부재로 VIX3M/HYG 상대강도 대체 유지.

E. PM 리포트

E1. raw JSON 노출

  • 원인: methodology_audit.stale_inputs dict가 conflict 문장에 그대로 들어갔다.
  • 조치: pm_context_filter.py:63 humanize_stale_input() 추가.
  • 검증 샘플:
  • 매크로 분석이 2026-04-20 기준(1일 전)이라 오늘 판단에는 보수적 가중치를 적용한다.
  • "type": "stale_input" 미검출.

E2. 섹터 비중 합계 85%

  • 원인: 6개 가이드 합계가 85%였고 잔여 15% 설명이 없었다.
  • 조치: pm_context_filter.py:527기타 기존 보유·미배정 15% 추가.
  • 검증: sector_positions.weight_guide 합계 100%.

E3. 해석 주입 소스 메타 문자열 제거

  • 원인: PM sender가 context path/title 원문을 너무 직접 표시했다.
  • 조치:
  • pm_context_filter.py에서 context label compact 처리.
  • analyst_common_sender.py:166에서 PM context label 재정리.
  • 검증 샘플:
  • 블로그 · 2026-04-20 — 중동산 원유가 아니라 미국산이 대안이 될 수 있을까? 2
  • Blog insights daily index, / 5961, source_channel 미검출.

검증 명령 요약

cd /Users/ron/.hermes/workspace
python3 -m py_compile \
  scripts/pipeline/vault_fundamental_bridge.py \
  scripts/fundamental_context_filter.py \
  scripts/macro_redesign_report.py \
  scripts/technical_context_filter.py \
  scripts/pm_context_filter.py \
  scripts/shared/vault_industry_context.py \
  scripts/analyst_common_sender.py

통과.

무발송 본문 검증:

ANALYST_COMMON_NO_SEND=1 ANALYST_COMMON_PRINT_BODY=1 python3 scripts/macro_redesign_report.py ... --print-body
ANALYST_COMMON_NO_SEND=1 ANALYST_COMMON_PRINT_BODY=1 python3 scripts/fundamental_redesign_report.py ...
ANALYST_COMMON_NO_SEND=1 ANALYST_COMMON_PRINT_BODY=1 python3 scripts/analyst_common_sender.py technical ...
ANALYST_COMMON_NO_SEND=1 ANALYST_COMMON_PRINT_BODY=1 python3 scripts/analyst_common_sender.py pm ...

검증 산출물:

  • /tmp/analyst_audit_260421_v2/macro_body.txt
  • /tmp/analyst_audit_260421_v2/fundamental2.out
  • /tmp/analyst_audit_260421_v2/technical_sender.out
  • /tmp/analyst_audit_260421_v2/pm_sender.out
  • /tmp/analyst_audit_260421_v2/checks.md
  • /tmp/analyst_audit_260421_v2/diffs.txt

남은 리스크

  1. macro latest의 기존 파일에는 이미 2026-04-20 stale metadata가 남아 있었다. 이번 패치로 다음 자동 생성부터 top-level date/as_of를 실행일 KST로 강제한다. 재발송 금지 조건 때문에 현재 Telegram 재발송으로 즉시 덮지는 않았다.
  2. 정유 collector는 EIA DEMO_KEY 429를 계속 맞았다. 다만 이번 펀더 브리핑에 필요한 equity proxy 6/6은 정상 수집됐다. EIA 키 교체는 별도 작업.
  3. PM이 macro stale을 오늘 본문에서 경고한 것은 현 상태에서는 맞는 동작이다. 내일 매크로 자동 생성 후 PM 경고가 사라지는지 확인 필요.

자체평가

  • 정확성: 4.6/5
  • 완성도: 4.6/5
  • 검증: 4.5/5
  • 최소 변경: 4.4/5
  • 종합: 4.5/5