- GET /v1/portfolios/{id}/trades and GET /v1/portfolios/{id}/pnl/realized endpoints
- Weighted Average Cost (WAC) realized PnL calculation in app/domain/pnl.py
- cost_basis and data_completeness_warning returned in pnl API response
- Test coverage: 50 passed (WAC 20 + trades 12 + pnl 18), full 427 passed regression ✓
- WAC validated against 199,300 unit e2e test cases
- DB migration: none required
- QC: qc-reviewer PASS-WITH-NOTES; team lead confirm-batch-verification → release-candidate
- Remaining non-blocking: symbol filter edge case testing, HTTP_422 deprecation
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
2.9 KiB
2.9 KiB
BAT-017 Implementation
Status: Complete
Changed Files
New Files
| File | Purpose |
|---|---|
app/domain/pnl.py |
WAC realized PnL calculation (REQ-041) — pure Python, no DB dependency |
tests/test_wac_calculation.py |
WAC unit tests — 20 tests, DB-free (REQ-042) |
tests/test_v1_portfolios_trades.py |
GET /trades integration tests — 12 tests (REQ-042) |
tests/test_v1_portfolios_pnl.py |
GET /pnl/realized integration tests — 18 tests (REQ-042) |
Modified Files
| File | Changes |
|---|---|
app/schemas/v1.py |
Added date import; added TradeHistoryItem, TradeHistoryResponse, RealizedPnlItem, RealizedPnlResponse |
app/api/v1_portfolios.py |
Added date, datetime, timedelta, timezone imports; added calculate_realized_pnl import; added schema imports; added _parse_date_param() helper; added list_portfolio_trades() endpoint (REQ-039); added get_realized_pnl() endpoint (REQ-040) |
app/repositories/postgres.py |
Added list_trades_by_date() method (REQ-039); added get_all_trades_for_pnl() method (REQ-040/041) |
app/repositories/portfolio_repository.py |
Added list_trades_by_date() and get_all_trades_for_pnl() abstract method signatures |
docs/batches/index.md |
Added BAT-017 register row |
Batch Documents
| File | Purpose |
|---|---|
docs/batches/bat-017_.../index.md |
Batch index |
docs/batches/bat-017_.../planning.md |
Planning |
docs/batches/bat-017_.../design.md |
Design |
docs/batches/bat-017_.../implementation.md |
This file |
docs/batches/bat-017_.../verification.md |
Verification |
Key Implementation Decisions
WAC 계산 함수 위치
app/domain/pnl.py신규 — domain 계층 (REQ-041 Notes: domain 계층 권장)app/services/portfolio_service.py수정 없음 — WAC 함수는 domain에 독립 배치
_parse_date_param 날짜 형식 강제
- Python 3.11+
date.fromisoformat()은YYYYMMDD(대시 없음)도 수용함 - REQ-039 AC-4 준수를 위해
re.fullmatch(r"\d{4}-\d{2}-\d{2}", value)사전 검증 추가
get_all_trades_for_pnl 쿼리 설계
- WAC 정확성 확보를 위해 집계 기간(
from/to) 제약 없이 portfolio의 모든 buy/sell 이력 조회 - Python domain 함수에서
from_dt/to_dt파라미터로 sell 집계 필터 적용
list_trades_by_date 날짜 경계
date단일:[date 00:00 UTC, date+1day 00:00 UTC)반개구간to_포함 경계:to_ + timedelta(days=1)exclusive upper bound 적용
data_completeness_warning 경고
- running_qty=0에서 sell 발생 또는 sell qty > running_qty 시 경고 필드 설정
- 계산은 중단하지 않고 최선 추정 계속 (REQ-041 AC-3/AC-4)
서비스/클라이언트 토큰 접근 제한
- 두 엔드포인트 모두
token_type in ("service", "client")→ 403 - DB 토큰 또는 env 토큰(read 이상)만 접근 가능