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:
2026-06-26 18:18:39 +09:00
co-authored by Claude Opus 4.8
parent 5b2e256c8d
commit e32eb78656
5 changed files with 404 additions and 1 deletions
@@ -0,0 +1,81 @@
# req-109: portfolio-hub /pnl/realized read 포트 메서드 + HTTP 어댑터
- Status: Approved
- Type: Integration
- Priority: High
- Owner: trex-core-dev
- Approved By: 팀장 (Claude), 2026-06-26 (confirm-req)
## Intent
- 현재 `PortfolioHubReadAdapter`(`hub_read.py`)에는 portfolio-hub WAC 실현 PnL 조회(`GET /v1/portfolios/{id}/pnl/realized`) 메서드가 없다. 운영 리포트가 WAC 기반 실현손익을 정확하게 표시하려면 이 엔드포인트를 소비하는 포트 메서드와 HTTP 어댑터가 필요하다. (dcy-035 FR-1)
## Requirement
- `PortfolioHubReadPort`(프로토콜, `trex_core/application/portfolio.py`)에 `get_realized_pnl(portfolio_id, from_dt, to_dt, *, symbol)` 메서드를 추가한다. 반환 타입은 `RealizedPnlResult` 데이터클래스로 정의한다.
- `RealizedPnlResult`는 다음 필드를 포함한다: `items: list[RealizedPnlItem]`, `cost_basis_from: str | None`, `data_completeness_warning: bool`, `total_realized_pnl: float`. `RealizedPnlItem`은 최소 `symbol`, `realized_pnl`, `sell_qty`를 포함한다.
- `PortfolioHubReadAdapter`(`hub_read.py`)에 위 메서드를 구현한다: `GET /v1/portfolios/{portfolio_id}/pnl/realized` 를 `from_dt`(ISO8601 date), `to_dt`(ISO8601 date), `symbol`(optional)을 query param으로 전달해 호출하고, 응답을 `RealizedPnlResult`로 파싱·반환한다. 네트워크/HTTP 오류 시 `PortfolioHubUnavailableError`를 raise 한다.
- `StubPortfolioRead`(`stub_read.py`)에도 동일 메서드를 결정론 stub로 추가한다(테스트/CI용).
- 기존 `whoami`, `get_portfolios`, `get_cost_basis` 메서드와 동작은 변경하지 않는다.
## Acceptance Criteria
1. Given portfolio-hub가 portfolio_id/from_dt/to_dt에 대해 `{"items": [...], "cost_basis_from": "...", "data_completeness_warning": false}` 형태의 200 응답을 반환할 때, When `get_realized_pnl` 호출, Then `RealizedPnlResult`가 올바른 items/cost_basis_from/data_completeness_warning/total_realized_pnl으로 반환된다.
2. Given `symbol` 파라미터가 제공될 때, When `get_realized_pnl` 호출, Then `?symbol=<값>`이 쿼리 파라미터로 포함된다.
3. Given portfolio-hub가 네트워크 오류 또는 비-2xx 응답을 반환할 때, When `get_realized_pnl` 호출, Then `PortfolioHubUnavailableError`가 raise 된다.
4. Given `stub_read.py` stub, When `get_realized_pnl` 호출, Then 네트워크 없이 미리 설정한 고정 `RealizedPnlResult`를 반환한다.
5. Given import sweep, When `trex_core/domain`을 검사, Then 신규 포트/어댑터 관련 IO/네트워크 의존이 domain에 없다(NFR: 도메인 순수성 불변).
6. Given `data_completeness_warning: true` 응답, When 파싱, Then `RealizedPnlResult.data_completeness_warning == True`로 반영된다.
## Impacted Area
- Docs: 없음(리포트 표면 갱신은 REQ-110/111)
- Modules:
- `trex_core/application/portfolio.py` — `PortfolioHubReadPort`에 `get_realized_pnl` 메서드 추가, `RealizedPnlResult`/`RealizedPnlItem` 데이터클래스 신규 정의
- `trex_core/adapters/portfolio/hub_read.py` — `get_realized_pnl` HTTP 구현 추가
- `trex_core/adapters/portfolio/stub_read.py` — stub 메서드 추가
- Tests:
- `tests/adapters/portfolio/test_hub_read.py` — 신규 AC-1~3, AC-6 케이스 추가
- `tests/adapters/portfolio/test_stub_read.py` — AC-4 stub 케이스 추가
- `tests/domain/test_domain_import_sweep.py` — AC-5 회귀(기존 sweep 재실행)
## Notes
- portfolio-hub `GET /v1/portfolios/{id}/pnl/realized` 계약(REQ-040/041): from_dt/to_dt는 **매도 기준** date-filter. cost basis는 기간 밖 매수도 WAC에 포함(멀티데이 정의). 응답 envelope는 portfolio-hub `app/api/v1_portfolios.py:712`·`app/domain/pnl.py`·schemas 기준 — 구현 시 실 계약을 `hub_read.py`의 기존 `get_cost_basis` 패턴(graceful degrade 방식)에 맞춰 구현한다.
- OQ-2(기간 파라미터 기본값 정의), OQ-3(수수료 출처), OQ-4(N콜 vs 집계) 미결 → 이 REQ는 어댑터 계층만 정의. 기간 인자는 caller(REQ-110의 CLI/report 레이어)가 결정해 전달. 어댑터는 전달된 파라미터를 그대로 쿼리에 쓴다.
- `total_realized_pnl`은 `items`의 `realized_pnl` 합산으로 어댑터 내에서 계산(portfolio-hub 응답에 합산 필드가 있으면 재사용, 없으면 클라이언트 합산).
- 기존 `get_cost_basis`(REQ-105 FR-7)는 sync CLI용 포트로 독립 유지 — 이 REQ와 중복 아님.
## Change Log
### CHG-20260626-01
- Date: 2026-06-26
- Author: trex-core-dev
#### Change Summary
- dcy-035 FR-1로부터 최초 생성(Proposed). portfolio-hub WAC 실현 PnL read 포트 + HTTP 어댑터 + stub.
#### Intent
- 운영 리포트(REQ-110)가 WAC 실현손익을 표시하기 위한 하위 의존 어댑터 정의.
#### Acceptance Criteria Delta
- Added:
- AC-1~6 신규
- Updated:
- none
- Removed:
- none
#### Impacted Area Delta
- Docs: 없음
- Modules:
- portfolio.py 포트 확장, hub_read.py/stub_read.py 어댑터 신규 메서드
- Tests:
- test_hub_read.py, test_stub_read.py, test_domain_import_sweep.py
#### 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