docs(dcy-035): 멀티데이 WAC 실현PnL 운영리포트 — discovery confirmed + REQ-109/110/111 approved
- 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
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
# req-110: 운영 리포트 WAC 실현손익 통합 — 전 인스턴스 공통
|
||||
|
||||
- Status: Approved
|
||||
- Type: Interface
|
||||
- Priority: High
|
||||
- Owner: trex-core-dev
|
||||
- Approved By: 팀장 (Claude), 2026-06-26 (confirm-req)
|
||||
|
||||
## Intent
|
||||
- 현재 `operator_report.py`(REQ-088)의 `realized_pnl(trades)`은 당일 net 현금흐름(`Σ매도대금 − Σ매수대금 − 수수료 − 세금`)을 사용한다. 중장기 인스턴스에서 전일 매수→당일 매도 시 cost basis가 반영되지 않아 실현손익이 왜곡된다. portfolio-hub WAC API(`/pnl/realized`)를 소비해 전 인스턴스 공통으로 정확한 실현손익을 산출하고 리포트에 표시한다. (dcy-035 FR-2, FR-3, FR-4, OQ-1=전 인스턴스 WAC 통일, NFR-2)
|
||||
|
||||
## Requirement
|
||||
- `operator_report.py`의 `OperatorReport`에 WAC 실현손익 관련 필드를 추가한다: `realized_pnl_wac: float`, `realized_pnl_wac_by_asset: dict[str, float]`, `buy_fee_only_assets: dict[str, float]`(매수만 한 기간의 수수료 비용 별도), `data_completeness_warning: bool`.
|
||||
- 운영 리포트(`trex-core report` CLI)는 당일 net 대신 portfolio-hub WAC 실현손익(`/pnl/realized`)을 **전 인스턴스 공통**으로 사용해 실현손익을 표시한다.
|
||||
- 매도가 있는 자산: WAC 기준 실현손익(`(매도가 − WAC) × qty − fee − tax`)을 자산별로 분해해 출력한다.
|
||||
- 매수만 한 기간(해당 자산의 매도 0): 실현손익 0으로 표시하고, **수수료 비용(`buy_fee_only_assets`)을 별도 항목으로 명시**한다. 수수료 출처는 `ledger_outbox` 당일 거래(기존 경로 재사용; OQ-3 deferred).
|
||||
- portfolio-hub 응답의 `data_completeness_warning: true` 시 리포트 출력에 경고를 표면화한다(텍스트/JSON 모두 포함).
|
||||
- `render_text` / `render_json`을 WAC 모드에 맞게 갱신한다.
|
||||
- CLI `report` 서브커맨드에서 portfolio-hub 설정(`cfg.portfolio_hub.base_url`)이 있을 때 WAC 경로를 사용하고, 미설정이면 REQ-111 degrade 경로로 위임한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
1. Given 전일 매수 + 당일 매도 시나리오(portfolio-hub `/pnl/realized` 모킹 응답), When `report` 실행, Then 실현손익이 WAC 기준 정확값(`(매도가 − WAC) × qty − fee − tax`)으로 표시되고 당일 net 왜곡값과 다르다.
|
||||
2. Given 동일 날 매수 + 매도(일중) 시나리오(WAC = 당일 매수가), When `report` 실행, Then WAC 실현손익 == 기존 당일 net과 수치 일치한다(NFR-2 회귀 보장).
|
||||
3. Given 매수만 한 기간(매도 0), When `report` 실행, Then 실현손익 0 + `buy_fee_only_assets` 수수료 비용이 별도 항목으로 표시된다.
|
||||
4. Given portfolio-hub 응답에 `data_completeness_warning: true`, When `report` 실행, Then 텍스트 출력과 `--json` 출력 모두에 completeness 경고가 표시된다.
|
||||
5. Given 자산별 실현손익 분해, When `report` 실행, Then `realized_pnl_wac_by_asset`에 자산(symbol)별 WAC 실현손익이 분해된다.
|
||||
6. Given `--json` 플래그, When `report` 실행, Then `render_json` 출력에 `realized_pnl_wac`, `realized_pnl_wac_by_asset`, `buy_fee_only_assets`, `data_completeness_warning` 필드가 포함된다.
|
||||
7. Given portfolio-hub `base_url` 미설정(cfg.portfolio_hub None 또는 base_url 미정의), When `report` 실행, Then REQ-111 degrade 경로로 처리된다(에러 표시).
|
||||
|
||||
## Impacted Area
|
||||
- Docs:
|
||||
- `docs/operations.md` — 리포트 실현손익 정의 갱신(당일 net → WAC 기준, 매수일 수수료 표시 명시)
|
||||
- `docs/runtime-flows.md` — operator report 흐름에 portfolio-hub WAC 호출 경로 추가
|
||||
- Modules:
|
||||
- `trex_core/application/operator_report.py` — `OperatorReport` 필드 확장, 기존 `realized_pnl(trades)` 함수는 legacy/테스트 목적 유지(NFR-2 회귀 비교용), WAC 모드 신규 함수/빌더, `render_text`/`render_json` 갱신
|
||||
- `trex_core/runtime/cli.py` — `_cmd_report` 내 portfolio-hub WAC 호출 분기, `from_dt`/`to_dt` 파라미터 전달 (OQ-2 deferred: 기본값=오늘 KST 경계로 구현)
|
||||
- Tests:
|
||||
- 신규: 멀티데이 픽스처(전일 매수+당일 매도) 통합 테스트, 매수만 기간 테스트, data_completeness_warning 테스트, NFR-2 일중 회귀 단위 테스트
|
||||
- 기존 `test_operator_report.py` 회귀 (당일 net 함수 동작 보존)
|
||||
|
||||
## Notes
|
||||
- OQ-2(기간 모델): from_dt/to_dt는 오늘(KST 경계) 기본값으로 구현. 기간 범위 확장(지정 기간)은 design/팀장 결정 대기 → 기본 구현은 "당일 KST 매도 기준" 유지, `--from`/`--to` CLI 옵션 추가는 OQ-2 확정 후 별도 change-req 또는 design 인계.
|
||||
- OQ-3(수수료 출처): 매수만 한 날의 수수료는 `ledger_outbox` 당일 거래에서 집계(기존 경로 재사용). portfolio-hub 거래내역(REQ-039) 사용 여부는 design 인계.
|
||||
- OQ-4(N콜 vs 집계): 슬롯↔portfolio 1:1이므로 portfolio_id별 N콜이 기본 구현. 집계 최적화는 design 인계.
|
||||
- 기존 `realized_pnl(trades)` 함수는 삭제하지 않고 유지한다(NFR-2 회귀 비교, 기존 테스트 보존).
|
||||
- NFR-1(wire 계약 불변): report는 read-only 운영 표면 — slots RPC/AMQP 계약 무관. REQ 명시 불필요.
|
||||
- NFR-3(데몬 본업 격리): `_cmd_report`는 CLI 직접 실행 경로이며 데몬 루프와 무관 — 격리는 구조적으로 보장됨.
|
||||
|
||||
## Change Log
|
||||
|
||||
### CHG-20260626-01
|
||||
- Date: 2026-06-26
|
||||
- Author: trex-core-dev
|
||||
|
||||
#### Change Summary
|
||||
- dcy-035 FR-2/FR-3/FR-4, OQ-1(전 인스턴스 WAC 통일), NFR-2(일중 회귀)로부터 최초 생성(Proposed).
|
||||
|
||||
#### Intent
|
||||
- 중장기 인스턴스 실현손익 왜곡 해소 + 단기 회귀 보장 + 매수일 수수료 표시 + completeness 경고 표면화.
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- Added:
|
||||
- AC-1~7 신규
|
||||
- Updated:
|
||||
- none
|
||||
- Removed:
|
||||
- none
|
||||
|
||||
#### Impacted Area Delta
|
||||
- Docs:
|
||||
- docs/operations.md, docs/runtime-flows.md
|
||||
- Modules:
|
||||
- operator_report.py 확장, cli.py _cmd_report 분기
|
||||
- Tests:
|
||||
- 신규 멀티데이/매수전용/completeness/NFR-2 테스트, 기존 회귀
|
||||
|
||||
#### Delivery Trace Delta
|
||||
- Batches:
|
||||
- none (미배치)
|
||||
- Releases:
|
||||
- none
|
||||
|
||||
#### Revalidation Impact
|
||||
- Reverification Needed: no
|
||||
- Existing Implementation Invalidated: no
|
||||
- Status Recommendation: keep-current
|
||||
- Follow-up Action: confirm-req 승인 게이트 후 suggest-batch-reqs
|
||||
Reference in New Issue
Block a user