- dcy-035 confirm-discovery: OQ-1=전 인스턴스 WAC 통일, OQ-5=섹션 에러 degrade - REQ-109 portfolio-hub /pnl/realized read 어댑터(포트+HTTP+stub) - REQ-110 운영리포트 WAC 실현손익 통합(전 인스턴스, 매수일 수수료, completeness, 일중 net 회귀) - REQ-111 portfolio-hub 미가용 시 실현손익 섹션 에러 degrade(폴백 없음) - srs/index register 갱신 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
13 KiB
13 KiB
0. 문서 상태
- 상태: confirmed
- 문서 ID: dcy-035_20260626_multiday-realized-pnl-report-wac
- 이슈명: 중장기 운영 리포트 — portfolio-hub WAC 실현PnL(/pnl/realized) 연동 (멀티데이 정확 실현손익)
- 작성 시각(KST): 2026-06-26 (KST)
- 마지막 갱신 시각(KST): 2026-06-26 (KST)
- 대체됨: 없음
- 후속 Discovery 참조: 없음
- 생성된 REQ 참조: REQ-109, REQ-110, REQ-111
1. 계획 상태 요약
- 연계 문서 현황:
- 관련 TODO/메모: GitHub 보드 #7 "중장기 운영 리포트 — portfolio-hub WAC 실현PnL API(/pnl/realized) 연동 (멀티데이, M3)". M3 중장기 인스턴스 운영 도구(슬롯 동기화 dcy-034의 리포트 짝).
- 선행: dcy-029(운영 관측성·실현 PnL 뷰, REQ-088 operator report), dcy-032(체결가 누락→cost basis 오염), portfolio-hub dcy-007/REQ-040(WAC 실현 PnL API).
- 해석:
- 현행 trex-core 운영 리포트(
application/operator_report.py, REQ-088/dcy-029)는 실현 PnL을 당일 net 매매 현금흐름(Σ매도(qty·price−fee−tax) − Σ매수(qty·price+fee))으로 계산한다. 일중 진입·청산 전략에선 net ≈ 실현손익이라 충분했으나(M1/M2 단기), 중장기(수일~수개월 보유)에선 cost basis(WAC)를 무시한 당일 net이 실현손익과 다르다. - portfolio-hub는 이미 WAC 기반 실현 PnL(
GET /v1/portfolios/{id}/pnl/realized, REQ-040/041:(매도가−running_wac)·qty−fee−tax)을 제공한다. M3 중장기 인스턴스의 운영 리포트는 이 WAC API를 소비해 멀티데이 정확 실현손익을 보여야 한다. - 본 Discovery는 그 연동을 trex-core 변경 단위로 정식화한다(portfolio-hub는 기존 API 그대로 — 무변경).
- 현행 trex-core 운영 리포트(
2. 요구사항 판정 결과
- 판정: 신규
- 근거
- dcy-029(REQ-088)는 당일 net 실현 PnL을 정의했다(
operator_report.py주석: "일중 진입·청산 전략에서는 net ≈ 실현손익"). 멀티데이 WAC 실현손익은 다른 계산 정의이며, 외부(portfolio-hub) WAC API 소비라는 신규 연동이다. - trex-core에 portfolio-hub
/pnl/realized클라이언트 메서드/포트가 없다(신규).
- dcy-029(REQ-088)는 당일 net 실현 PnL을 정의했다(
3. 문제점의 요약
- 현재 상태
operator_report.py(REQ-088):realized_pnl(trades)가ledger_outbox당일 거래로 net(매도대금−매수대금−수수료−세금)을 계산. 자산별 분해 포함.trex-core reportCLI로 노출.- 이 정의는 당일 매수→당일 매도(일중) 에서만 실현손익과 일치한다. 전일 이전 매수분을 오늘 매도하면, 당일 net은 "오늘 매도대금 − (오늘 없는 매수)"가 되어 cost basis가 빠진 채 실현손익이 과대/왜곡된다(중장기 보유의 본질).
- portfolio-hub
/pnl/realized(REQ-040)는 매수 누적 WAC를 cost basis로 써 매도별 정확 실현손익을 주지만, trex-core 리포트가 이를 소비하지 않는다.
- 기대 상태
- 중장기 인스턴스 운영 리포트의 실현 PnL이 portfolio-hub WAC API(/pnl/realized) 기준의 멀티데이 정확 실현손익으로 표시된다(매수 cost basis 반영).
- portfolio-hub 이력 불완전 시(
data_completeness_warning)가 리포트에 표면화된다. - portfolio-hub 미가용 시 리포트가 안전하게 degrade(에러 표시 또는 당일 net 폴백)한다.
- 이해관계자
- 사장님 — 리포트 정의(멀티데이 기준)·범위 결정
- 팀장(Claude) — Discovery/게이트
- trex-core-dev — delivery
- 운영자 — 중장기 인스턴스 손익 리포트 소비자
- 제약사항
- portfolio-hub
/pnl/realized는 매도 기준 date-filter, 전 매수 WAC 참여(REQ-041): 즉 기간 내 매도의 실현손익을 주고, 그 cost basis는 기간 밖 매수도 포함. (멀티데이 정의에 부합.) - 매수만 한 날은 매도가 없어 realized=0 — 사장님 정의("매수만 한 경우 수수료 비용")를 충족하려면 리포트가 수수료(비용)를 별도 표시해야 함(realized와 분리).
- trex-core wire 계약(slots RPC) 무관(리포트는 read-only 운영 표면). portfolio-hub HTTP 호출 추가(read).
- portfolio-hub
주요 사용자 시나리오
- 운영자: 중장기 인스턴스의
trex-core report(또는 동등)로 기간 실현손익을 본다 → 전일 매수분을 오늘 매도한 손익이 WAC 기준으로 정확히 표시(당일 net 왜곡 아님). - 운영자: 매수만 한 날 → 실현손익 0 + 수수료 비용 표시. 매도한 날 → WAC 실현손익. 둘 다 → 매수(WAC) 반영 후 매도 실현손익.
4. 이번에 정의할 변경
- 변경 1 — portfolio-hub
/pnl/realized소비 포트/어댑터 신규:PortfolioHubReadPort(또는 신규 포트)에 realized-pnl read 메서드 + HTTP 어댑터(GET /v1/portfolios/{id}/pnl/realized, from/to/symbol). - 변경 2 — 운영 리포트의 실현 PnL을 WAC 기반으로 전 인스턴스 통일(OQ-1 결정):
operator_report.py가 당일 net 대신 portfolio-hub WAC 실현손익을 사용(단·중·장기 공통 — WAC는 일중에도 정확). data_completeness_warning 표면화. 매수만 한 날의 수수료 비용 별도 표시. - 변경 3 — degrade: portfolio-hub 미가용 시 실현손익 섹션에 에러 명시(OQ-5 결정 — 당일 net 폴백 안 함). 나머지 리포트 섹션(보유/체결/대기주문)은 정상 출력.
영향 범위
- 코드 영향:
trex_core/adapters/portfolio/*(realized-pnl read 어댑터 신규),trex_core/application/portfolio.py(포트),trex_core/application/operator_report.py(실현 PnL 소스 분기),trex_core/runtime/cli.py(report 명령 — 기간/모드 옵션 필요시). - 문서 영향:
docs/discovery/index.md, srs/batches.docs/operations.md(리포트 해석 갱신). - 운영 영향: 리포트 실현손익 정의가 중장기 모드에서 WAC로 바뀜 — 런북에 명시. portfolio-hub 호출 의존 추가.
5. 요구사항 목록
기능 요구사항
- FR-1: trex-core가 portfolio-hub
GET /v1/portfolios/{id}/pnl/realized(from/to/symbol)를 호출하는 read 포트+어댑터를 갖는다. - FR-2: 운영 리포트의 실현 PnL을 전 인스턴스 공통으로 portfolio-hub WAC 실현손익 기준으로 산출·표시한다(당일 net 대체, 멀티데이 cost basis 반영). 자산별 분해 유지.
- FR-3: 매수만 한 기간(매도 0)은 실현손익 0 + 수수료 비용을 별도 항목으로 표시(사장님 정의).
- FR-4: portfolio-hub
data_completeness_warning(이력 불완전)을 리포트에 표면화한다. - FR-5: portfolio-hub 미가용 시 실현손익 섹션에 에러를 명시하고(폴백 없음), 나머지 리포트 섹션은 정상 출력한다.
비기능 요구사항
- NFR-1: trex-core wire 계약(slots RPC) 불변 — 리포트는 read-only 운영 표면.
- NFR-2: 전 인스턴스 통일이므로, 일중 매수+매도(같은 날) 케이스에서 WAC 실현손익이 기존 당일 net과 일치함을 회귀 테스트로 보장한다(단기 라이브 의미 보존 — WAC(=당일 매수가)·매도가 동일 정의).
- NFR-3: portfolio-hub 호출 실패가 데몬 본업(슬롯/집행)에 영향 주지 않는다(리포트 격리).
범위 경계
- In Scope
- portfolio-hub /pnl/realized 소비(포트+어댑터) + 중장기 운영 리포트 WAC 실현손익 + 매수일 수수료 표시 + completeness 경고 + degrade.
- Out of Scope
- portfolio-hub 측 변경(이미 REQ-040 제공 — 무변경).
- 미실현 손익(현재가 결합), 세무 리포트.
- 슬롯↔계좌 동기화(dcy-034 별건).
6. 리스크/가정 목록
리스크
- R-1 (Medium): WAC 실현손익 소스 전환이 단기 인스턴스 리포트(당일 net)에 회귀를 줄 수 있다.
- 완화: 모드/인스턴스로 분리(단기=net 유지 or WAC 통일은 OQ-1), 회귀 테스트.
- R-2 (Low): portfolio-hub 호출 추가로 리포트가 외부 의존·지연. 미가용 시 리포트 실패.
- 완화: degrade(폴백/에러 명시, OQ-5) + 본업 격리(NFR-3).
가정
- A-1: portfolio-hub
/pnl/realized(REQ-040/041)는 멀티데이 WAC 실현손익을 정확히 제공한다(매도 date-filter + 전 매수 WAC). - A-2: 중장기 인스턴스는 portfolio_id별로 실현손익을 조회한다(슬롯↔portfolio_id 1:1).
- A-3: trex-core는 portfolio-hub를 세션/토큰으로 호출 가능하다(기존 whoami/get_portfolios 경로 재사용).
오픈 질문
- OQ-1: WAC 실현손익을 전 인스턴스 통일인지, 중장기 모드만인지.
- 상태: Answered (2026-06-26, 사장님) — 전 인스턴스 WAC 통일(당일 net 폐기). WAC는 일중에도 정확하므로 단기 라이브도 WAC로 통일하되, NFR-2 회귀(일중 케이스 net 일치)로 의미 보존.
- OQ-2: 리포트 기간 정의 — 당일/지정 기간(from~to). /pnl/realized는 from_dt/to_dt(매도 기준). 멀티데이 리포트의 기본 기간·옵션.
- 상태: Open / 처리: design, 팀장 / 종료: 기간 모델 확정 시 Answered
- OQ-3: 매수만 한 날 "수수료 비용" 표시 방식 — 실현손익과 별도 라인(비용)으로. 수수료 출처(portfolio-hub 거래내역 REQ-039 또는 trex-core ledger).
- 상태: Open / 처리: design, 팀장 / 종료: 표시·출처 확정 시 Answered
- OQ-4: trex-core가 realized PnL을 어떻게 조회 — portfolio_id별 N콜 vs daemon 집계. (slots↔portfolio 1:1이라 N콜이 자연스러우나 종목 多면 비용.)
- 상태: Open / 처리: design, 팀장 / 종료: 조회 단위 확정 시 Answered
- OQ-5: portfolio-hub 미가용 시 degrade.
- 상태: Answered (2026-06-26, 사장님) — (b) 실현손익 섹션 에러 명시(당일 net 폴백 없음). 나머지 섹션(보유/체결/대기주문) 정상 출력.
오픈 질문 처리 기준
Open/Answered/Deferred/Dropped표준 처리.
7. 초기 성공 기준
- S-1: 전일 이전 매수분을 당일 매도한 시나리오에서 리포트 실현손익이 WAC 기준 정확값(당일 net 왜곡 아님)으로 표시된다.
- S-2: 매수만 한 기간 → 실현손익 0 + 수수료 비용 표시.
- S-3: portfolio-hub
data_completeness_warning이 리포트에 표면화된다. - S-4: portfolio-hub 미가용 시 리포트가 degrade(정의된 방식)하고 데몬 본업 무영향.
- S-5: 일중 매수+매도(같은 날) 케이스에서 WAC 실현손익 = 기존 당일 net (단기 의미 보존, NFR-2).
측정 방식 및 데이터 출처
- S-1/S-2: 멀티데이 픽스처(전일 매수+당일 매도, 매수만) 통합 테스트(portfolio-hub 모킹) / 신규 테스트.
- S-3/S-4: 경고 주입·미가용 모킹 테스트.
- S-5: 기존 operator_report 테스트 회귀.
8. REQ로 넘기기 전 확인 체크
- 적용 범위 확정 — OQ-1 = 전 인스턴스 WAC 통일
- degrade 정책 — OQ-5 = 실현손익 섹션 에러 명시
- 기간/수수료/조회단위 design 인계 — OQ-2/3/4 (draft-req/design 단계)
- 성공지표 측정 이견 없음
- Freeze 담당자(CONFIRMED_BY) 지정 — 팀장
9. 파일 처리 결과
- 처리 결과: 생성
- 생성 경로: docs/discovery/dcy-035_20260626_multiday-realized-pnl-report-wac.md
- 참조 문서:
- docs/discovery/dcy-029(운영 리포트 REQ-088), dcy-032(cost basis 오염)
- portfolio-hub dcy-007/REQ-040/041(WAC 실현 PnL), app/api/v1_portfolios.py:712, app/domain/pnl.py
- trex_core/application/operator_report.py(현행 당일 net), runtime/cli.py(report)
10. 사용자 결정 필요 항목 요약
DECIDE
- (OQ-1) WAC 실현손익 적용 범위: 전 인스턴스 통일 vs 중장기 모드만.
- (OQ-5) portfolio-hub 미가용 시 degrade 방식.
CONFIRM
- 본 건을 M3 중장기 운영 리포트(멀티데이 WAC 실현손익) 단위로 채택 — portfolio-hub 무변경, trex-core 연동.
DATA
- (OQ-3 보조) 매수일 수수료 출처(portfolio-hub 거래내역 REQ-039 vs trex-core ledger) — 팀장 design서 확인.
11. Discovery Freeze
섹션 참조
- 범위: # 5 > 범위 경계 / 리스크·OQ: # 6 / 성공: # 7 / 인계 전 확인: # 8 / 결정: # 10
Freeze 플래그
- Handoff Decision: 진행 (인계) — OQ-1/OQ-5 사장님 결정 완료, OQ-2/3/4는 draft-req/design 단계 처리
- Handoff Rationale: portfolio-hub WAC API는 이미 존재(무변경), trex-core 연동만. 적용범위=전 인스턴스 WAC 통일, degrade=섹션 에러 명시 확정. 기간/수수료/조회단위는 REQ·design에서 구체화.
- Ready for REQ Drafting: true
- Confirmed By: 팀장 (Claude)
- Confirmed At (KST): 2026-06-26
12. 작성 가이드
- trex-core dcy 템플릿 기반. Open Questions는 가정 대체 금지. confirm-discovery 시 OQ 처리 + Freeze 갱신.