커뮤니티

LLM이 추측하지 않는 주식 분석기 — 4개 전문 AI가 병렬로 리포트를 쓰는 멀티에이전트 대시보드

2026-07-28
관리자
조회수 : 4

LLM이 추측하지 않는 주식 분석기 — 4개 전문 AI가 병렬로 리포트를 쓰는 멀티에이전트 대시보드

종목코드 하나를 넣으면 재무, 뉴스 및 업종 전문 AI가 각자 분석하고, 전략가 AI가 하나의 투자 리포트로 종합한다. Claude Code로 만들어 [dataso.biz](https://www.dataso.biz)에 올린 기록.

한 줄 요약

LLM에게 "삼성전자 분석해줘"라고 하면 그럴듯하게 지어낸다. 이 프로젝트는 그 반대로 설계했다 — 스크립트가 DART, 시세 및 뉴스를 먼저 결정적으로 수집해 JSON으로 정리하고, 그 위에서만 AI가 해석한다. 재무, 뉴스 및 업종 3개 에이전트가 병렬로 분석한 뒤, 종합 전략가 에이전트가 요약본만 받아 최종 시나리오를 낸다. 환각을 구조로 막은 것이 핵심.

  • 결과물: — Railway 배포, 액세스 코드 게이트로 운영
  • 스택: Streamlit, Python 하네스, Anthropic Claude, DART, yfinance, 네이버금융, Google News 및 Firecrawl
  • 저장소: stock-app (Streamlit 단일 앱, app.py 698줄 + 하네스 7모듈)
  • 성격: 교육 및 실습용 예시 (실제 투자 권유 아님)

1. 왜 만들었나 — "LLM은 추측한다"는 문제

주식 분석에 LLM을 쓸 때 진짜 위험은 거짓을 사실처럼 말하는 것이다. 매출, 부채비율 및 PER을 물으면 학습 데이터의 흐릿한 기억으로 그럴듯한 숫자를 뱉는다. 투자 판단에 그대로 쓰면 위험하다.

그래서 이 앱의 1번 원칙은 이렇게 못박혀 있다:

"LLM이 추측하지 않습니다. 스크립트가 DART, 시세 및 뉴스를 먼저 수집해 JSON으로 정리합니다."

이게 랜딩 페이지 첫 화면에 대문짝만하게 적힌 이유다. 결정적 하네스(deterministic harness) — 데이터는 코드가 확정하고, AI는 확정된 데이터만 해석한다.


2. 구조 — 4개 에이전트 + 결정적 하네스

데이터 수집 하네스 (AI 개입 없음)

모듈소스역할
dart_metrics.pyDART OpenAPI정식 재무제표 → 매출, 영업이익, 부채비율 및 ROE
fin_metrics.pyyfinance + 네이버금융시세, PER 및 PBR
news_fetch.pyGoogle News RSS뉴스 수집
firecrawl_news.pyFirecrawl뉴스가 부실할 때 웹 검색으로 보강(백업)
sector_scan.pyyfinance + RSS업종 피어 비교
text_insight.py—토픽, 워드클라우드 및 감성분포

뉴스는 Google News를 먼저 긁고, 결과가 빈약하면 Firecrawl로 자동 보강한다(source: "google+firecrawl"). 이 폴백 하나가 "데이터 없어서 못 씀"을 "그래도 채워옴"으로 바꾼다.

4개 전문 에이전트 (각자 독립 컨텍스트)

```

재무 분석가 ─┐

뉴스 감성 분석가 ─┼─(요약만 전달)→ 종합 전략가(4옵션)

산업 연구원 ─┘

```

  • 💰 재무 분석가 — DART 재무제표로 수익성/안정성 판정
  • 📰 뉴스 감성 분석가 — 뉴스 톤을 0~100 점수로 정량화, 호재, 악재 및 중립 분류
  • 🏭 산업 연구원 — 업종 동향 + 글로벌 피어 PER, PBR 및 성장률로 상대 위치 파악
  • 🎯 종합 전략가 — 공격적🎯, 보수적🛡️, 균형⚖️ 및 퀀트📐 4성향 중 선택해 최종 시나리오

핵심 설계: 각 에이전트는 독립된 컨텍스트에서 분석하고, 종합 단계로는 "요약만" 전달한다. 전체 원본을 한 프롬프트에 욱여넣지 않아 컨텍스트 오염과 환각을 줄인다. 멀티에이전트를 쓰는 진짜 이유가 여기 있다.


3. 점수 엔진 — 재현 가능한 룰 기반 종합

AI의 정성 판단과 별개로, 종합점수는 결정적 공식으로 계산한다(app.py):

```

종합점수 = 0.40 × 재무점수 + 0.25 × 뉴스감성 + 0.35 × 업종점수

```

이 종합점수(0~100)가 4대 전략 시나리오의 목표가, 손절가 및 제안비중을 만든다.

전략판단(예: 점수 70+)제안비중손절
공격적 🎯적극 매수8~10%−15%
균형 ⚖️비중확대4~5%−12%
보수적 🛡️관망 및 소량1~2%−8%
퀀트 📐점수 기반 시그널모델−12%

같은 입력이면 같은 점수 — 재현 가능. AI는 해석과 서술을, 룰 엔진은 숫자를 담당하는 역할 분리.


4. 한 번 검색 → 8개 화면 자동 생성

종목코드(예: 005930, 000660, AAPL) 하나 넣고 실행하면 탭이 전부 자동으로 뜬다:

  • 📄 종합 보고서 — Word 및 Markdown 다운로드 (python-docx)
  • 💬 AI 질문 — 리포트 기반 Q&A + 필요 시 웹 검색 보강 (Claude, 프롬프트 캐싱 사용)
  • 🎯 시나리오 — 종합점수 기반 4대 전략의 목표가, 손절가 및 비중
  • 🔎 인사이트 — 토픽, 워드클라우드 및 감성분포 + AI 인사이트
  • 그 외 재무, 밸류, 감성 및 업종 탭

AI 질문 탭은 ANTHROPIC_API_KEY로 동작하고, 수집된 리포트를 1차 근거로 답하되 부족하면 웹 검색으로 보강한다. cache_control: ephemeral로 리포트 컨텍스트를 캐싱해 반복 질문 비용을 줄였다.


5. 운영까지 — 배포, 게이트 및 비용 통제

Railway 배포. Streamlit 무료 호스팅이 자는 문제를 피해 Railway 컨테이너로 올렸다. railway.json/Procfile에 시작 명령을 넣어 $PORT 자동 주입, Nixpacks 자동 빌드.

액세스 코드 게이트. 이 앱은 운영자의 API(Claude 및 Firecrawl)로 돌아간다 — 즉 호출할 때마다 운영자 돈이 나간다. 그래서 아무나 못 쓰게 ACCESS_CODES 환경변수 기반 접속 게이트를 붙였다. 이용하려면 이메일로 신청 → 승인 후 코드 발급.

캐시로 비용 및 속도 통제. 데이터 수집은 TTL 캐시(재무 및 시세 1시간, 뉴스 15분, AI 응답 10분)로 묶어 같은 종목 반복 조회 시 API 재호출을 막는다.

커밋 3개가 전체 스토리를 요약한다:

  • Initial commit: 주식 분석 멀티에이전트 Streamlit 웹앱
  • 랜딩페이지 + 접속 게이트(ACCESS_CODES) 추가
  • UI 세련화: 기본 개발자 툴바 숨김 + 브랜드 상단바

만들고 → 돈 새는 것 막고 → 얼굴 다듬고. 개인 API로 서비스를 공개할 때 딱 필요한 순서.


6. 이 프로젝트가 잘한 것 (다른 바이브코더에게)

  1. 환각을 프롬프트가 아니라 구조로 막았다. "정확히 답해줘"라고 빌지 않고, 데이터를 코드가 먼저 확정한 뒤 AI에게 넘긴다. 이게 신뢰의 뿌리.
  2. 멀티에이전트를 이유 있게 썼다. 4개로 쪼갠 건 멋져 보여서가 아니라, 독립 컨텍스트 + 요약 전달로 오염을 줄이려는 설계다.
  3. AI와 룰을 분리했다. 서술은 AI, 점수는 결정적 공식. 재현 가능성과 설명력을 둘 다 챙겼다.
  4. 공개 = 비용을 잊지 않았다. 개인 API로 서비스를 열면 반드시 접속 게이트와 캐시가 필요하다. 이걸 처음부터 넣었다.
  5. 폴백을 깔았다. Google News가 비면 Firecrawl로 채운다. "데이터 없음"으로 끝나지 않는다.

링크 및 구성

  • 서비스: (액세스 코드 필요 — [email protected] 신청)
  • 저장소: stock-app (Streamlit)
  • 데이터: 📊 DART, 💹 네이버금융, 🌐 yfinance, 📰 Google News 및 🔥 Firecrawl
  • AI: 🤖 Claude (Anthropic)
  • 배포: Railway (Nixpacks)

이 글은 GitHub 저장소(stock-app)의 코드 및 커밋 이력과 라이브 사이트(dataso.biz)를 근거로 작성했습니다. 종합점수 공식 및 캐시 TTL 및 에이전트 구성 및 배포 방식은 실제 app.py와 README에서 확인한 사실입니다. 본 서비스는 교육 및 실습용 예시이며 투자 권유가 아닙니다.

원문: 천동암, 지피터스 GPTers (2026.07.28) gpters.org 원문 보기