dcy-008(confirmed)/REQ-043(Approved)/BAT-018. trex-core dcy-034 FR-7 cold-start seed 의존. AC 11/11, QC PASS. worktree+PR 워크플로 첫 파일럿. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
61 lines
3.4 KiB
Markdown
61 lines
3.4 KiB
Markdown
# BAT-018 Planning
|
|
|
|
- Status: confirmed
|
|
- Batch: BAT-018
|
|
- Profile: batch-lite
|
|
|
|
## Included REQ
|
|
- REQ-043 (Interface, Approved) — GET /v1/portfolios/{id}/holdings/cost-basis 현재 보유 평단(WAC) read 엔드포인트 신설.
|
|
|
|
## Delivery Plan
|
|
|
|
### 구현 순서
|
|
1. **domain 함수 추가** (`app/domain/pnl.py`)
|
|
- `calculate_current_wac(rows)` 신규 함수 — 기존 `calculate_realized_pnl`의 running_wac 누적 로직 재사용, 매도 완료 후 잔여 running_wac/running_qty/cost_basis_from/data_completeness_warning 반환.
|
|
- 반환 타입: 새 `CurrentWacResult` dataclass (wac, quantity, cost_basis_from, data_completeness_warning).
|
|
2. **스키마 추가** (`app/schemas/v1.py`)
|
|
- `HoldingsCostBasisResponse` 스키마 신규 추가 (REQ-043 응답 필드 전체 포함).
|
|
3. **엔드포인트 추가** (`app/api/v1_portfolios.py`)
|
|
- `GET /{portfolio_id}/holdings/cost-basis` 핸들러 — `require_read` 의존성.
|
|
- 소유권 분기: service token → `daemon_id == managed_by_daemon_id` 일치 확인(불일치/null → 403). user token → admin 외 비소유자 403.
|
|
- `portfolio.asset_quantity`에서 current_quantity 직접 읽기.
|
|
- WAC: `get_all_trades_for_pnl` 재사용 → `calculate_current_wac` 호출.
|
|
4. **테스트** (`tests/test_v1_portfolios_holdings.py` 신규)
|
|
- AC-1~11 커버. MagicMock repo 주입 패턴(기존 test_v1_portfolios_pnl.py 참조).
|
|
|
|
### 파일 변경 목록
|
|
- **신규 생성**:
|
|
- `tests/test_v1_portfolios_holdings.py` — AC-1~11 테스트
|
|
- `docs/batches/bat-018_20260625_holdings-cost-basis-endpoint/` — batch 문서
|
|
- **수정**:
|
|
- `app/domain/pnl.py` — `CurrentWacResult` dataclass + `calculate_current_wac` 함수 추가
|
|
- `app/schemas/v1.py` — `HoldingsCostBasisResponse` 추가
|
|
- `app/api/v1_portfolios.py` — 엔드포인트 추가, import 갱신
|
|
- `docs/batches/index.md` — BAT-018 register 행 추가
|
|
|
|
## Dependencies
|
|
- `app/domain/pnl.py`의 `calculate_realized_pnl` running_wac 로직(REQ-041) — 이미 구현됨.
|
|
- `app/repositories/portfolio_repository.py`의 `get_all_trades_for_pnl` — 이미 구현됨.
|
|
- `require_read` 인증 의존성 — 변경 없음.
|
|
- `portfolio.asset_quantity` 컬럼 — 이미 존재.
|
|
|
|
## Design Gate
|
|
- Design Required Before Implementation: **no**
|
|
- Reason:
|
|
- 기존 `get_realized_pnl` 핸들러(L710)의 직계 변형. HTTP contract·schema·계층 경계 모두 기존 패턴 답습.
|
|
- WAC 함수: `calculate_realized_pnl`의 running_wac 추출 — 구조적 신규 설계 없음.
|
|
- 소유권 정책: REQ-029 선례(`_require_service_token` + `managed_by_daemon_id` 검사)를 read 엔드포인트에 적용, 분기만 추가.
|
|
|
|
## Milestones
|
|
1. domain 함수(`calculate_current_wac`) + 단위 테스트 작성
|
|
2. 스키마(`HoldingsCostBasisResponse`) 추가
|
|
3. 엔드포인트(`GET /holdings/cost-basis`) 추가
|
|
4. 통합 테스트(`test_v1_portfolios_holdings.py`) AC-1~11 작성
|
|
5. `pytest` 전체 실행 — 신규 + 기존 회귀 확인
|
|
|
|
## Risks
|
|
| Risk | 완화 |
|
|
| --- | --- |
|
|
| R-1 (Low): current_quantity와 WAC 수량 불일치 시 data_completeness_warning 조건 | `portfolio.asset_quantity`는 직접 읽고, WAC는 ledger replay 독립 계산. 불일치 시 warning 트리거 → REQ-043 Notes 항목 준수. |
|
|
| R-2 (Low): service token 인증 분기가 기존 user token 패턴과 충돌 | `_get_portfolio_or_404`는 user token 전용 소유권 검사. service token 분기는 핸들러 내 명시적 분기로 별도 처리. |
|