# req-109: portfolio-hub /pnl/realized read 포트 메서드 + HTTP 어댑터 - Status: Implemented - 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-02 - Date: 2026-06-26 - Author: trex-core-dev #### Change Summary - BAT-052 구현·검증 완료(PR #33, 머지 커밋 81d06d9). confirm-batch-verification + confirm-req-implemented. Approved → Implemented. #### Intent - dcy-035 FR-1 delivery 완료 확인 및 상태 전환. #### Acceptance Criteria Delta - Updated: - none (모든 AC-1~6 검증 완료, 상태 전환만) - Added: - none - Removed: - none #### Impacted Area Delta - Docs: 없음 - Modules: 변경 없음 (구현 완료 상태 유지) - Tests: 717 passed / 47 skipped / 0 fail (BAT-052 verification) #### Delivery Trace Delta - Batches: - BAT-052 (verified, PR #33, 머지 커밋 81d06d9, 2026-06-26) - Releases: - none (M3 배포 대기) #### Revalidation Impact - Reverification Needed: no - Existing Implementation Invalidated: no - Status Recommendation: Implemented - Follow-up Action: none ### 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