Skip to main content
Glama
Daegyu519

portfolio-agent

by Daegyu519

portfolio-agent

근거와 무효화 조건이 붙은 투자 판단을 내리는 개인용 의사결정 에이전트

뉴스 요약기가 아니라 의사결정 시스템이다. 모든 판단에는 근거 원문 링크와 "이 판단이 뒤집히려면 무엇이 참이어야 하는가" 가 붙는다.

Python MySQL MCP Claude Code Read-only Tests License

WARNING

개인 의사결정보조 도구다. 매매 기능은 없고(토스 API 읽기전용), 출력은 투자 권유가 아니다.


왜 이렇게 만들었나

LLM에게 포트폴리오를 물으면 그럴듯한 수치를 지어내고, 틀려도 조용하다. 이 시스템은 그 실패 모드를 구조로 막는다.

원칙

의미

🔢 수치는 LLM이 만들지 않는다

가격은 토스, 공시는 DART/EDGAR 원문. 계산은 engines/의 순수 코드. LLM은 그라운딩된 텍스트 위에서 종합만 한다.

근거 + 무효화 조건 강제

근거 원문 링크와 무효화 조건이 없는 추천은 코드 게이트가 반려한다. 설득이 아니라 검증이다.

👁️ 읽기 전용

주문·정정·취소 엔드포인트는 코드에 존재하지 않는다.

📍 사실 하나당 소스 하나

정형 상태는 MySQL, 서술은 마크다운 vault. 중복 저장 = drift.

🧪 관찰 트랙 격리

기술적 지표·뉴스 감성은 확률적 신호다. 판단 엔진에 들어가지 않고 사람이 보는 병렬 트랙으로만 존재한다.

Related MCP server: CRASH - Cascaded Reasoning with Adaptive Step Handling

어떻게 도는가

flowchart LR
    subgraph SRC["📥 sources · 읽기전용"]
        T["토스증권<br/>보유·시세"]
        D["DART / EDGAR<br/>공시 원문"]
    end
    subgraph ENG["⚙️ engines · LLM 없음"]
        Q["quant<br/>집중도·상관·리스크"]
        TH["thesis<br/>논지 상태머신"]
    end
    subgraph JUD["🧠 판단"]
        B["근거 번들 E#<br/>(그라운딩 원장)"]
        L["Claude Code<br/>종합"]
        G{"게이트<br/>근거·무효화·수치 대조"}
    end
    ST[("MySQL<br/>SoT")]
    V["📓 vault<br/>Obsidian 미러"]

    T --> Q --> B
    D --> TH --> B
    B --> L --> G
    G -->|"통과"| ST
    G -->|"반려"| L
    ST --> V

    style G fill:#D97757,stroke:#8B3A2B,color:#fff
    style ST fill:#4479A1,stroke:#2C5378,color:#fff

게이트는 ① 인용된 근거 E#이 실제로 원장에 있는지 ② 무효화 조건이 붙었는지 ③ 수치가 원본과 일치하는지 ④ 보유 종목 전원에 판단이 있는지를 검사한다. 통과분만 저장된다.

셋업

요구사항 — Python 3.11+, MySQL 8.x (uv 권장) LLM API 키는 필요 없다. 판단 합성은 Claude Code 또는 로컬 CLI로만 실행된다.

# 1) 의존성
uv venv --python 3.12 && source .venv/bin/activate
uv pip install -e ".[dev]"

# 2) 시크릿 — MYSQL_DSN · TOSS_* · DART_API_KEY 를 채운다
cp .env.example .env

# 3) 스키마 + 점검
python -m src.cli.brief init-db
python -m src.cli.brief doctor

사용

python -m src.cli.brief review          # 온디맨드 심층 판단
python -m src.cli.brief review --mock   # 토스 키 없이 mock 픽스처로 파이프라인 확인
python -m src.cli.brief daily           # 일일 다이제스트 (코드 수치만, LLM 없음)
python -m src.cli.brief watch           # 백그라운드 논지 감시 — 무효화 트리거 시에만 알림
python -m src.cli.brief retrospect      # 제안 vs 실제 행동 vs 결과 회고

논지 레코드가 판단의 상태머신이다. 신규 공시·실적이 들어오면 thesis.py가 무효화 조건을 점검해 statusvalid → watch → broken으로 갱신한다.

python -m src.cli.brief thesis add <TICKER> --entry-price <가격> --weight <비중> \
    --thesis "<왜 샀는가 한 줄>" --assumption "<핵심 가정>" \
    --cond "<서술>|price<<임계값>|broken" --cond "<질적 조건>||watch"

--cond설명|룰|심각도 형식이다. 룰을 비우면 코드가 아니라 사람이 판정하는 질적 조건이 된다.

.envOBSIDIAN_VAULT_PATH를 주면 review 성공 시 Companies/·Thesis/·Daily/·Decision/ 마크다운이 생성된다.

MySQL이 유일한 SoT이고 vault는 생성물 미러다 — 비워두면 조용히 비활성화되고(경고 없음), Obsidian 설치도 불필요하다. 보유에서 빠진 종목 문서는 삭제되지 않고 Archived로 표시되어 이력이 남는다.

판단 LLM = Claude Code

1차 경로 — Claude Code 안에서 /review. portfolio MCP 서버의 review_begin이 그라운딩 근거 번들을 만들고, Claude Code가 내부 추론으로 판단 JSON을 작성해 review_submit에 제출한다.

폴백 — 터미널 단독 실행 시 SYNTHESIS_PROVIDER=auto가 로컬 CLI를 탐지한다: claude -pgeminiollama → 없으면 번들만 출력. 어떤 엔진이든 게이트는 동일하다.

claude mcp add portfolio -s project -- python -m src.mcp.portfolio_server
claude mcp add sources   -s project -- python -m src.mcp.sources_server
claude mcp list   # 헬스 확인

구조

계층은 위에서 아래로만 의존한다. 관찰 트랙(회색 점선)은 판단 경로에 닿지 않는다 — 확률적 신호가 의사결정에 새어드는 걸 구조로 막는다.

flowchart TB
    subgraph L1[" ①  진입  ·  <i>Claude Code · 터미널</i> "]
        direction LR
        CLI["<b>cli/</b><br/>brief.py<br/><sub>review · daily · watch</sub>"]
        MCPS["<b>mcp/</b><br/>portfolio · sources<br/><sub>stdio 서버</sub>"]
    end

    subgraph L2[" ②  판단  ·  <i>여기서만 LLM</i> "]
        SYN["<b>synthesis/</b><br/>decision · prompts · llm<br/><sub>근거·무효화 게이트</sub>"]
    end

    subgraph L3[" ③  도메인  ·  <i>LLM 없음 · 순수 코드</i> "]
        direction LR
        ENG["<b>engines/</b><br/>quant · thesis<br/><sub>계산 · 상태머신</sub>"]
        OBSV["<b>engines/</b><br/>technical · sentiment<br/><sub>관찰 트랙 — 격리</sub>"]
    end

    subgraph L4[" ④  데이터 "]
        direction LR
        SRC["<b>sources/</b><br/>toss · dart · edgar<br/><sub>읽기전용</sub>"]
        STO["<b>storage/</b><br/>Repository → MySQL<br/><sub>정형 SoT</sub>"]
        KNW["<b>knowledge/</b><br/>vault export<br/><sub>생성물 미러</sub>"]
    end

    CLI --> SYN
    MCPS --> SYN
    SYN --> ENG
    ENG --> SRC
    ENG --> STO
    STO --> KNW
    OBSV -.->|"판단 우회"| KNW
    SRC -.-> OBSV

    style SYN fill:#D97757,stroke:#8B3A2B,stroke-width:2px,color:#fff
    style STO fill:#4479A1,stroke:#2C5378,stroke-width:2px,color:#fff
    style OBSV fill:#F0F1F3,stroke:#8C959F,stroke-dasharray:4 3,color:#57606A
    style KNW fill:#F0F1F3,stroke:#8C959F,color:#24292F
    linkStyle 6,7 stroke:#8C959F,stroke-dasharray:4 3

계층

모듈

불변식

cli/ · mcp/

MCP 서버는 stdout에 프로토콜 메시지만 — 로그는 stderr

synthesis/

근거 E# · 무효화 조건이 없으면 저장을 거부한다

engines/

LLM 호출이 존재하지 않는다. 같은 입력 → 같은 출력

sources/ · storage/ · knowledge/

매매 함수 없음 · 사실 하나당 소스 하나

테스트

pytest   # 전부 오프라인 — 외부 API · LLM · MySQL 불필요 (fake/mock 기반)

라이선스

이 저장소는 MIT다. 핵심 의존성(httpx · pymysql · cryptography · python-dotenv · mcp · numpy)은 전부 BSD/MIT/Apache 계열이라 충돌이 없다.

IMPORTANT

선택적 extra [yolo] 는 AGPL-3.0 이다. 차트 패턴 탐지에 쓰이는 ultralytics는 AGPL-3.0 이며, 이는 이 저장소의 MIT 와 다른 조건이다. 이 저장소는 ultralytics 코드도 모델 가중치도 포함하지 않는다engines/patterns.py 에서 lazy import 할 뿐이고, 미설치 시 조용히 비활성화된다. uv pip install -e ".[yolo]" 를 실행하는 순간부터 AGPL-3.0 조건이 적용되며, 준수 책임은 설치한 쪽에 있다. AGPL 이 곤란하다면 이 extra 를 설치하지 마라 — 의사결정 코어는 YOLO 없이 완전히 동작한다 (애초에 관찰 트랙이라 판단 경로에 닿지 않는다).

[sentiment] extra(transformers, Apache-2.0)와 [technical] extra(matplotlib, PSF)는 허용적 라이선스다.

문서

CLAUDE.md

설계 규율 — 행동 계약

TASKS.md

작업 백로그

docs/spec.md

원본 설계 명세

docs/hallucination.md

그라운딩 게이트 설계

docs/running.md · docs/docker.md

운영

docs/technical.md · docs/sentiment.md

관찰 트랙

docs/token-economy.md

토큰 예산

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Daegyu519/portfolio-agent'

If you have feedback or need assistance with the MCP directory API, please join our Discord server