Files
trex-core/docs/discovery/dcy-005_20260604_portfolio-hub-asset-snapshot-api.md
T
genichinandClaude Opus 4.8 6277d610ea Add dcy-005 Discovery (draft): portfolio-hub asset snapshot read API
- new-discovery dcy-005: read-direction follow-up of dcy-004 (deferred
  get_assets/get_portfolios). trex-core exposes portfolio-hub asset snapshot
  as a read API, returning buy candidates with slot-occupied symbols filtered
  out (slot overlay) and an empty list when no slots remain.
- 6 open questions pinned: snapshot shape, freshness/cache, core-proxy policy,
  in-flight overlay (ledger outbox eventual consistency), availability degrade,
  empty-list semantics.
- Link dcy-004 후속 Discovery 참조 → dcy-005; add dcy-005 to discovery index.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 22:51:30 +09:00

19 KiB

0. 문서 상태

이 문서의 현재 상태와 식별 정보를 기록한다. 문서 추적과 승인 흐름에 필요한 최소 메타데이터를 적는다.

  • 상태: draft
  • 문서 ID: dcy-005_20260604_portfolio-hub-asset-snapshot-api
  • 이슈명: portfolio-hub 종목 스냅샷 read API — 매수 전략 모듈에 슬롯-제외 후보 제공
  • 작성 시각(KST): 2026-06-04 22:46
  • 마지막 갱신 시각(KST): 2026-06-04 22:46
  • 대체됨: 없음
  • 후속 Discovery 참조: 없음
  • 생성된 REQ 참조: 없음

1. 계획 상태 요약

현재 Discovery가 어떤 배경에서 작성되고 있는지, 연계 문서가 있는지, 지금 시점의 해석이 무엇인지 짧게 요약한다.

  • 연계 문서 현황:
    • 관련 점수 파일: 미생성
    • 관련 TODO/메모: dcy-004(portfolio-hub ledger write 통합, BAT-006 진행 중)의 Out of Scope asset master 동기화·get_assets/get_portfolios 연동. orbit app/clients/portfolio_client.py(read 계약 get_assets/get_portfolios 패턴)
  • 해석:
    • dcy-004 는 체결을 portfolio-hub 원장에 기록하는 write 방향이었고, 본 Discovery 는 그 반대인 read 방향 — portfolio-hub 종목 스냅샷을 trex-core API 로 매수 전략 모듈에 제공한다. dcy-004 가 명시적으로 후속으로 미룬 영역을 이어받는다.
    • active-cycle 판정(BAT-006 draft 진행 중)이지만 명시적 신규 입력이고, BAT-006(write)과 read 방향이 분리되어 범위 충돌이 없으므로 병렬 독립 주기로 진행한다. core 경유의 핵심 가치는 단순 패스스루가 아니라 core 의 권위 슬롯 상태를 겹쳐(slot overlay) 이미 점유된 종목을 제외한 매수 후보를 제공하는 것이다.

2. 요구사항 판정 결과

이번 요청이 기존 요구사항과 비교해 신규인지, 유사한지, 중복인지 판단하고 그 근거를 남긴다.

  • 판정: 신규
  • 근거
    • dcy-004 는 write 방향(원장 기록)만 In Scope 였고 read 방향(get_assets/get_portfolios)은 명시적으로 Out of Scope(후속)였다. 본 Discovery 는 그 후속 read 통합이다.
    • 기존 REQ 본문 수정이 아니라 신규 외부 read 통합 + 신규 read API 엔드포인트라 change-req 가 아니라 새 Discovery 다.

3. 문제점의 요약

문제의 현재 상태, 기대 상태, 관련 이해관계자, 제약사항을 정리한다. Discovery의 핵심 맥락을 가장 먼저 이해할 수 있어야 한다.

  • 현재 상태
    • trex-core 의 read API 는 슬롯 자체 조회(GET /v1/slots, /v1/capacity)와 intent 조회뿐이다(trex_core/adapters/api/app.py). portfolio-hub 종목을 노출하는 read 엔드포인트가 없다.
    • portfolio-hub read 어댑터(get_assets/get_portfolios)가 trex-core 에 없다. dcy-004/BAT-006 은 write 방향 LedgerPort + portfolio-hub 어댑터만 추가하며, read 포트는 다루지 않는다.
    • 결과적으로 매수 전략 모듈이 "무엇을 살지" 정할 portfolio-hub 종목 정보를 trex-core 를 통해 받을 경로가 없다.
  • 기대 상태
    • trex-core 가 portfolio-hub 종목 스냅샷을 read API 로 제공하고, 현재 슬롯을 점유(pending/holding)한 종목을 제외한 매수 후보 리스트를 매수 전략 모듈에 반환한다.
    • 가용 슬롯이 없으면(capacity 소진) 매수 후보가 없음을 명확한 시맨틱(빈 리스트)으로 반환한다.
  • 이해관계자
    • 문서 작성자/구현자(AI agent)
    • 리뷰어/승인자(운영자, genichin@gmail.com)
    • 매수 전략 모듈(trex-core 외부 소비자) 및 portfolio-hub(외부 자산/포지션 서비스)
  • 제약사항
    • 도메인 순수성 — trex_core.domain 은 portfolio-hub/네트워크 의존 0(read 어댑터 격리).
    • 단일 통합 경계 — portfolio-hub 자격증명/계약 접점은 trex-core 어댑터(dcy-004 재사용)로 한정.
    • core 는 슬롯/capacity 의 권위 단일 writer(불변식 A) — slot overlay 는 이 권위 상태를 사용한다.

주요 사용자 시나리오

사용자 또는 운영자가 실제로 어떤 상황에서 이 변경을 필요로 하는지 대표 시나리오를 적는다.

  • 매수 전략 모듈이 매수 후보를 정하려고 trex-core 스냅샷 API 를 호출 → portfolio-hub 종목 중 이미 슬롯을 점유한 종목을 뺀 후보 리스트를 받는다.
  • 모든 슬롯이 차 있어 더 살 수 없는 상황 → 스냅샷 API 가 빈 후보 리스트를 반환해 전략이 매수를 시도하지 않는다.
  • 막 체결되어 슬롯이 pending/holding 인 종목 → portfolio-hub 포지션에 아직 반영되기 전이라도 core slot overlay 로 후보에서 즉시 제외되어 중복 매수를 막는다.

4. 이번에 정의할 변경

이번 Discovery에서 다루는 핵심 변경 항목을 목록으로 적는다. 기능, 구조, 규칙 변경을 함께 포함해도 된다.

  • portfolio-hub read 포트 + 어댑터: PortfolioHubReadPort.get_assets()/get_positions() 추상화 + portfolio-hub 어댑터(orbit get_assets/get_portfolios 패턴, dcy-004 어댑터/자격증명 재사용) + 결정론 stub.
  • 종목 스냅샷 read API: trex-core 가 portfolio-hub 종목 스냅샷을 read 엔드포인트로 제공하고, 현재 슬롯 점유(pending/holding) 종목을 제외한 매수 후보 리스트를 반환한다(slot overlay).
  • 빈 후보 시맨틱: 가용 슬롯이 0 이면 매수 후보를 빈 리스트로 반환한다(표현 방식 null vs empty 는 OQ-6).
  • baseline 갱신: interface-contract(read 포트/엔드포인트)·runtime-flows(스냅샷 조회 흐름)·project-structure(read 어댑터) 갱신.

영향 범위

변경이 미칠 코드/문서/운영 범위를 명시해 REQ 정제와 batch planning에서 추정 누락을 줄인다.

  • 코드 영향:
    • 신규: trex_core/application read 포트, trex_core/adapters/ledger(또는 신규 adapters/portfolio) read 어댑터 + stub, trex_core/adapters/api 스냅샷 read 엔드포인트 + 응답 스키마, slot overlay(점유 종목 제외) 로직.
    • 기존: capacity/slot 조회 재사용(점유 종목·가용 슬롯 판정).
  • 문서 영향:
    • interface-contract/runtime-flows/project-structure 갱신.
  • 운영 영향:
    • portfolio-hub read 의존 추가(dcy-004 자격증명 재사용). 캐시 도입 시 신선도/무효화 운영 고려.

5. 요구사항 목록

실제로 구현과 검증으로 이어질 요구사항을 기능/비기능으로 나누어 정리하고, 범위 경계를 명확히 적는다.

기능 요구사항

  • FR-1: trex-core 가 portfolio-hub 종목 스냅샷을 read API 엔드포인트로 제공한다(GET, 매수 전략 모듈이 HTTP 로 소비). 응답 단위(자산 universe / 포지션 / 후보)는 OQ-1 에서 확정한다.
  • FR-2: 스냅샷 응답에서 현재 슬롯을 점유(pending/holding)한 종목을 제외한 매수 후보 리스트를 반환한다. 제외 판정은 core 의 권위 슬롯 상태를 사용한다(slot overlay).
  • FR-3: 가용 슬롯이 0(capacity 소진)이면 매수 후보를 빈 리스트로 반환한다. 빈 리스트의 표현(빈 배열 vs null vs 메타 필드)은 OQ-6 결정에 따른다.
  • FR-4: portfolio-hub read 접근을 PortfolioHubReadPort(get_assets/get_positions) 추상화 + portfolio-hub 어댑터 + 결정론 stub 로 제공하고, dcy-004 의 portfolio-hub 어댑터/자격증명을 재사용한다.
  • FR-5: baseline 문서(interface-contract/runtime-flows/project-structure)를 read 포트·스냅샷 엔드포인트·read 어댑터에 맞게 갱신한다.

비기능 요구사항

성능, 운영성, 일관성, 자동화 안정성 등 기능 외 요구사항을 적는다.

  • NFR-1: 도메인 순수성 유지 — read 포트는 application 계약, 어댑터는 adapters 레이어 격리. trex_core/domain 은 portfolio-hub/네트워크 의존 0(import 스윕).
  • NFR-2: slot overlay 일관성 — 점유 종목 제외/가용 슬롯 판정은 core 의 권위 슬롯 상태(강한 일관성)를 사용한다. portfolio-hub 자산 데이터의 신선도 정책은 OQ-2 에 따른다.
  • NFR-3: 가용성 degrade — portfolio-hub 불가 시 스냅샷 read 의 동작(에러 vs 캐시 fallback vs 빈 응답)은 OQ-5 정책을 따른다.

범위 경계

이번 반복에서 반드시 포함할 범위와 명시적으로 제외할 범위를 구분한다.

  • In Scope
    • portfolio-hub read 포트 + 어댑터 + stub, 종목 스냅샷 read API, 슬롯 점유 종목 제외(slot overlay), 가용 슬롯 0 → 빈 후보, baseline 갱신.
  • Out of Scope (후속 Discovery)
    • 매수 전략 의사결정 로직 자체(점수화·랭킹·진입 타이밍) — 전략 모듈 책임.
    • portfolio-hub ↔ core 양방향 reconciliation, 포지션 재구성, asset master 영속 동기화.
    • 매수/매도 전략 데몬, safety floor, 실계좌 go-live.

6. 리스크/가정 목록

불확실성과 전제 조건을 분리해서 적는다. 리스크는 영향과 완화 방안을, 가정은 현재 판단의 전제를 기록한다.

리스크

  • R-1 (Medium): stale 스냅샷 — portfolio-hub 자산 데이터를 캐시하면 오래된 데이터 위에서 매수 후보가 만들어질 수 있다.
    • 완화 방안(OQ-2): 신선도/캐시 정책(live pass-through 또는 TTL+무효화) 확정. slot overlay 는 core 권위 상태라 강한 일관성 유지.
  • R-2 (Medium): in-flight race — dcy-004 ledger outbox 가 eventually-consistent 라, 막 체결한 종목이 portfolio-hub 포지션에 아직 반영되기 전 후보에 중복 노출될 수 있다.
    • 완화 방안(OQ-4): core slot overlay(pending/holding 제외)로 이 gap 을 메운다. portfolio-hub 포지션과 core 슬롯 상태의 합성 규칙을 명확화한다.
  • R-3 (Medium): 가용성 결합 — portfolio-hub 장애가 매수 전략 read 를 막는다.
    • 완화 방안(OQ-5): 캐시 fallback 또는 명시적 degrade 응답 정책. 어댑터 격리(NFR-1).
  • R-4 (Low): 책임 경계 확장 — core 가 portfolio-hub read gateway 로 비대해질 위험.
    • 완화 방안: slot overlay 부가가치(점유 제외·가용 판정)로 범위를 한정하고 단순 패스스루 프록시는 지양(OQ-3).

가정

아직 확정되지 않았지만 현재 문서 작성의 기반이 되는 전제를 적는다.

  • A-1: portfolio-hub 는 orbit 과 동일 read 계약(get_assets/get_portfolios 류)을 제공한다.
  • A-2: trex-core 는 슬롯/capacity 의 권위 단일 소스이며, 점유 종목·가용 슬롯 판정에 자기 상태를 사용할 수 있다.
  • A-3: 매수 전략 모듈은 trex-core 외부 소비자이며 HTTP 로 스냅샷을 받는다.
  • A-4: dcy-004 의 portfolio-hub 어댑터/자격증명(.env TREX_PORTFOLIO_HUB_*)을 read 방향에서도 재사용한다.

오픈 질문

답을 아직 모르는 항목을 적는다. 추정으로 덮지 말고 REQ 초안 작성 이전에 확인할 질문으로 남긴다.

  • OQ-1: 스냅샷의 정의 — 응답이 (a) 거래 가능 universe(asset master), (b) 현재 포지션/보유, (c) 전략 후보/타깃 비중 중 무엇을 담는가(또는 조합)? 매수 전략에 필요한 최소 필드는?
    • 상태: Open
    • 처리 방안: 운영자/매수 전략 모듈 요구를 confirm-discovery 시점에 확정.
    • 종료 조건: 응답 단위와 필드 집합이 FR-1 에 반영되면 Answered.
  • OQ-2: 신선도/캐시 정책 — live pass-through 인가, 캐시(REQ-016 Redis 패턴)인가? 캐시라면 TTL/무효화 기준은?
    • 상태: Open
    • 처리 방안: 운영자 결정. 매수 결정의 stale 허용도 기준으로 판단.
    • 종료 조건: 캐시 여부와 신선도 기준이 NFR-2/R-1 에 반영되면 Answered.
  • OQ-3: core 경유 정책 — 모든 소비자가 trex-core 를 경유하는가, 일부는 portfolio-hub 직접 호출을 허용하는가? core 경유의 부가가치(slot overlay)를 어디까지 의무화하는가?
    • 상태: Open
    • 처리 방안: 운영자 결정. 직접 호출 대비 indirection 비용과 slot 결합 가치 비교.
    • 종료 조건: 경유 정책이 범위 경계에 반영되면 Answered.
  • OQ-4: in-flight 합성 규칙 — portfolio-hub 포지션과 core 슬롯 상태(pending/holding)를 합쳐 후보를 만들 때, ledger outbox eventual consistency 로 인한 race 를 어떤 규칙으로 제거하는가?
    • 상태: Open
    • 처리 방안: 설계 시 slot overlay 우선순위(core 슬롯이 portfolio-hub 보다 우선) 규칙 확정.
    • 종료 조건: 합성/제외 규칙이 FR-2 와 R-2 완화에 반영되면 Answered.
  • OQ-5: 가용성 degrade 정책 — portfolio-hub 불가 시 read 응답을 에러로 반환하는가, 캐시 fallback 하는가, 빈 응답을 반환하는가?
    • 상태: Open
    • 처리 방안: 운영자 결정. 매수 전략의 안전 기본값(보수적 매수 중단) 우선 검토.
    • 종료 조건: degrade 동작이 NFR-3/R-3 에 반영되면 Answered.
  • OQ-6: 빈 후보 표현 시맨틱 — 가용 슬롯이 0 일 때 빈 배열([])을 반환하는가, null 을 반환하는가, 별도 메타 필드(예: available_slots: 0)로 신호하는가?
    • 상태: Open
    • 처리 방안: 매수 전략 모듈 소비 계약에 맞춰 결정(REST 관례상 빈 배열 + 메타 필드 권장안 검토).
    • 종료 조건: 표현 방식이 FR-3 에 반영되면 Answered.

오픈 질문 처리 기준

  • Open: 아직 답이 없고 다음 단계 진행에 영향이 있는 상태다. 문서에 유지한다.
  • Answered: 답이 확정된 상태다. 관련 본문/요구사항에 반영한 뒤 오픈 질문 목록에서는 제거하거나 resolved 기록으로 이동한다.
  • Deferred: 지금 단계에서 결정하지 않고 다음 단계 또는 후속 이슈로 넘기는 상태다. 넘길 대상과 이유를 반드시 적는다.
  • Dropped: 더 이상 유효하지 않은 질문이다. 삭제 사유를 짧게 남기고 목록에서 제거한다.
  • 처리 원칙 1: 질문만 남기지 말고 반드시 상태, 처리 방안, 종료 조건을 함께 적는다.
  • 처리 원칙 2: 답이 나온 질문은 본문 반영 없이 단순 삭제하지 않는다. 반영 위치를 먼저 갱신한다.
  • 처리 원칙 3: High 영향 질문은 Deferred 처리 후 처리 방안에 REQ 인계 추적 방식을 명시한다.

7. 초기 성공 기준

이 변경이 성공했다고 판단할 기준을 측정 가능하게 정의한다. 가능하면 데이터 출처까지 연결한다.

  • S-1: stub portfolio-hub read 로, 스냅샷 API 가 portfolio-hub 종목을 포함한 매수 후보 리스트를 반환한다.
  • S-2: pending/holding 슬롯이 점유한 종목이 후보 리스트에서 제외된다(slot overlay).
  • S-3: 가용 슬롯이 0 일 때 스냅샷 API 가 빈 후보 리스트를 반환한다.
  • S-4: 도메인 import 스윕에서 portfolio-hub/네트워크 의존이 0 으로 유지된다.
  • S-5: interface-contract/runtime-flows/project-structure 가 read 레이어와 정합한다.

측정 방식 및 데이터 출처

각 성공 기준을 어떻게 측정할지와 어떤 데이터나 문서를 근거로 쓸지 적는다.

  • S-1 측정 방식: stub read 통합테스트(스냅샷 응답) / 데이터 출처: 테스트 결과, 응답 본문.
  • S-2 측정 방식: 슬롯 점유 후 스냅샷 호출 테스트 / 데이터 출처: 후보 리스트 vs 슬롯 점유 종목.
  • S-3 측정 방식: 슬롯 소진(capacity 0) 후 스냅샷 호출 테스트 / 데이터 출처: 후보 리스트 길이.
  • S-4 측정 방식: 정적 import 스윕 / 데이터 출처: trex_core/domain import 목록.
  • S-5 측정 방식: 문서-코드 정합 점검(리뷰) / 데이터 출처: baseline 문서 vs 실제 엔드포인트/포트.

8. REQ로 넘기기 전 확인 체크

REQ 초안 작성 단계로 넘기기 전에 무엇이 확정되어야 하는지 확인한다. 미완료 항목은 후속 결정이 필요함을 뜻한다.

  • 범위(In Scope/Out of Scope) 확정 — 특히 전략 의사결정 로직·reconciliation 제외
    • 기준: 운영자가 read 슬라이스 경계를 확인했다.
  • 성공 지표의 측정 방식/데이터 출처 확정
    • 기준: S-1~S-5 측정 방식·출처 명시(본 문서 # 7).
  • High 영향 리스크 우선순위 및 해소 책임자 지정
    • 기준: 본 Discovery 의 리스크는 현재 전부 Medium/Low. 신선도(R-1)·race(R-2)·가용성(R-3) 처리 방침을 운영자가 확인.
  • 모든 오픈 질문(OQ) Open 상태 없음 확인
    • 기준: OQ-1~OQ-6 이 전부 Answered/Deferred 처리(현재 6개 모두 Open).
  • Freeze 확정 담당자(CONFIRMED_BY) 지정
    • 기준: 운영자가 confirm-discovery 시점에 CONFIRMED_BY 를 지정한다.

9. 파일 처리 결과

이 Discovery 문서 생성/갱신 결과와 참조 문서를 기록한다. 이후 추적과 리뷰 시 근거로 사용한다.

  • 처리 결과: 생성
  • 생성 경로: docs/discovery/dcy-005_20260604_portfolio-hub-asset-snapshot-api.md
  • 참조 문서:
    • docs/discovery/dcy-004_20260604_portfolio-hub-ledger-integration.md (write 방향 — 본 Discovery 가 read 방향으로 이어받음)
    • docs/interface-contract.md, docs/runtime-flows.md, docs/project-structure.md (baseline — 본 Discovery 가 갱신 요구)
    • trex-orbit app/clients/portfolio_client.py (get_assets/get_portfolios read 계약 참고)

10. 사용자 결정 필요 항목 요약

사용자나 승인자가 결정해야 하는 항목만 모아 정리한다. 결정, 확인, 데이터 요청을 구분해서 적는다.

DECIDE

  • {{DECIDE_SNAPSHOT_SHAPE}} — 스냅샷 응답 단위/필드(universe vs 포지션 vs 후보) 확정 (OQ-1)
  • {{DECIDE_FRESHNESS_POLICY}} — live pass-through vs 캐시(TTL/무효화) 신선도 정책 (OQ-2)
  • {{DECIDE_EMPTY_SEMANTICS}} — 가용 슬롯 0 시 빈 배열 vs null vs 메타 필드 표현 (OQ-6)

CONFIRM

  • {{CONFIRM_READ_SCOPE}} — read 슬라이스 범위 경계(전략 로직·reconciliation 제외) 확정
  • {{CONFIRM_CORE_PROXY_POLICY}} — 모든 소비자 core 경유 의무화 vs 일부 직접 호출 허용 (OQ-3)
  • {{CONFIRM_INFLIGHT_OVERLAY}} — portfolio-hub 포지션 + core 슬롯 합성/제외 규칙, 가용성 degrade 정책 (OQ-4/OQ-5)

DATA

  • {{DATA_PORTFOLIO_HUB_READ_CONTRACT}} — portfolio-hub read API 계약(get_assets/get_portfolios) 및 응답 필드(orbit 동일 가정 검증)

11. Discovery Freeze

REQ 초안 작성 인계 시점의 확정 플래그와 섹션 참조만 기록한다. 내용 재작성 없이 원본 섹션을 링크로 대신한다.

섹션 참조

Freeze 플래그

  • Handoff Decision: 보류
  • Handoff Rationale: 초기 Discovery 초안 생성 완료. OQ-1~OQ-6(스냅샷 정의·신선도/캐시·core 경유 정책·in-flight 합성·가용성 degrade·빈 후보 시맨틱)이 미확정이며, confirm-discovery 에서 운영자 결정 후 REQ Drafting 으로 인계한다.
  • Ready for REQ Drafting: false
  • Confirmed By: TBD
  • Confirmed At (KST): TBD