Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
10 KiB
10 KiB
REL-002: 일일 거래내역 + 실현 PnL 조회 API (dcy-007 M1)
- Status: released
- Profile: app-service
- Included Batch: BAT-017
Scope
- Included:
- BAT-017 (REQ-039, REQ-040, REQ-041, REQ-042): dcy-007 M1 fast-track — 일일 거래내역 + 실현 PnL 조회 API 신설
- REQ-039: GET /v1/portfolios/{id}/trades (date 단일/from+to 범위 필터, read_token 이상 인증, 403/404/422)
- REQ-040: GET /v1/portfolios/{id}/pnl/realized (from+to 필수, symbol 선택 필터, WAC 기반 실현 PnL, data_completeness_warning, cost_basis_from)
- REQ-041: WAC cost_basis 산출 로직 — app/domain/pnl.py (순수 Python, DB 무의존, R-1 완화 경고 로직)
- REQ-042: 테스트 커버리지 — test_wac_calculation.py(20건), test_v1_portfolios_trades.py(12건), test_v1_portfolios_pnl.py(18건)
- Freeze 커밋:
bd34450(main HEAD, 2026-06-18)
- BAT-017 (REQ-039, REQ-040, REQ-041, REQ-042): dcy-007 M1 fast-track — 일일 거래내역 + 실현 PnL 조회 API 신설
- Excluded:
- 미실현 PnL (현재가 연동) — dcy-007 OQ-2 Out of Scope
- 전체 portfolio 집계 PnL 뷰 — dcy-007 OQ-2 Out of Scope
- DB 마이그레이션 없음 (기존 portfolio_ledger 스키마로 조회 가능)
- 페이지네이션 — 이번 범위 외 이연
- 성능 테스트 (p95 500ms) — TimescaleDB 통합/성능 환경에서 별도 검증 필요
- BAT-001~016 (REL-001 포함 완료)
Rollout Plan
- 사전 확인: 코드 freeze 커밋
bd34450main HEAD 일치 확인 - DB 마이그레이션 없음: REL-002는 기존
portfolio_ledger스키마(alembic head =20260605_0025, REL-001 적용 완료)를 그대로 사용. 추가 마이그레이션 불필요. - portfolio-hub 서비스 배포: 신규 이미지(freeze 커밋
bd34450) rolling restart- 신규 엔드포인트:
GET /v1/portfolios/{id}/trades(REQ-039) - 신규 엔드포인트:
GET /v1/portfolios/{id}/pnl/realized(REQ-040) - WAC domain 로직:
app/domain/pnl.py신규 (REQ-041) - 기존 엔드포인트 영향 없음 (additive 변경)
- 신규 엔드포인트:
- 배포 후 smoke 검증: 하기 Verification Checklist 배포 직후 항목 실행
Rollback Plan
- 트리거 조건: portfolio-hub 배포 후
GET /health실패, 신규 API 500 대규모 발생, 기존 API 회귀 발생 - 절차:
- portfolio-hub → 이전 이미지(REL-001 freeze
6b812b6) rolling restart - DB 마이그레이션 없으므로 DB 롤백 불필요
- 기존 API (
/v1/portfolios,/v1/assets,/v1/tags,/v1/portfolios/{id}/ledger/trades등) 정상 동작 확인
- portfolio-hub → 이전 이미지(REL-001 freeze
- 롤백 영향: 신규 엔드포인트 2개(
/trades,/pnl/realized)만 제거됨. 기존 운영 기능 영향 없음. additive 변경이라 롤백 리스크 낮음.
Verification Checklist
- 배포 전:
- freeze 커밋
bd34450이 배포 대상 이미지에 포함됨 확인 - pytest 전체 (BAT-017 포함) 427 passed 확인: 50 (BAT-017 신규) + 377 (기존 회귀 0) — 2026-06-18 기준
- DB 마이그레이션 불필요 확인 (alembic head
20260605_0025그대로) - REL-001 운영 인스턴스 health 정상 확인 (배포 베이스라인)
- freeze 커밋
- 배포 직후 (portfolio-hub):
GET /health→ HTTP 200 +db_enabled: true확인 ✅ (2026-06-19 17:27 KST, trex-op)GET /v1/portfolios/{id}/trades?date=YYYY-MM-DD(read_token 이상) → HTTP 200 + 항목 필드(trade_id,side,quantity,price,executed_at,fee_amount,tax_amount) 확인 (REQ-039 AC-1) ✅ (체결 2건 확인)GET /v1/portfolios/{id}/trades(날짜 파라미터 누락) → HTTP 422 확인 (REQ-039 AC-3) ✅GET /v1/portfolios/{id}/pnl/realized?from=YYYY-MM-DD&to=YYYY-MM-DD(read_token 이상) → HTTP 200 +total_realized_pnl,cost_basis_from,items,data_completeness_warning필드 확인 (REQ-040 AC-1) ✅ (total_realized_pnl=-9306.585확인)GET /v1/portfolios/{id}/pnl/realized(from/to 누락) → HTTP 422 확인 (REQ-040 AC-3) ✅- 비소유자 토큰으로
/trades또는/pnl/realized호출 → HTTP 403 확인 (REQ-039 AC-6, REQ-040 AC-7) ✅ - 존재하지 않는 portfolio_id로 호출 → HTTP 404 확인 (REQ-039 AC-7, REQ-040 AC-8) ✅
- OpenAPI
/docs에서 신규 엔드포인트 2개 노출 확인 (REQ-039 AC-8, REQ-040 AC-9) — [비차단] 수동 확인 미완, 운영 관찰 중 - 기존
GET /v1/portfolios,POST /v1/portfolios/{id}/ledger/trades,GET /health정상 동작 회귀 없음 확인 ✅
Known Issues (QC PASS-WITH-NOTES 비차단 잔여)
- symbol 필터 edge 테스트 공백:
GET /v1/portfolios/{id}/pnl/realized?symbol=X호출 시symbol_param != portfolio_symbol케이스(다른 symbol 필터 요청)에 대한 자동 테스트가 불완전. AC-2는 충족이나 완전 커버 아님. 별도 cleanup batch에서 처리 권장. - HTTP_422_UNPROCESSABLE_ENTITY deprecated: FastAPI 최신 버전에서
HTTP_422_UNPROCESSABLE_ENTITY→HTTP_422_UNPROCESSABLE_CONTENT경고. 기존 코드 패턴 유지(breaking change 없음). 별도 cleanup batch에서 처리 권장. - 성능 AC-9/AC-10 미검증:
GET /v1/portfolios/{id}/trades및/pnl/realizedp95 500ms — TimescaleDB 인덱스 환경에서 별도 실행 필요. 환경 제약으로 이번 릴리즈 검증 범위 외(코드 결함 아님). - symbol 컬럼 부재:
portfolio_ledger에 symbol 컬럼 없음. 현재 portfolio 단위(1 portfolio = 1 symbol) 가정으로 동작. 멀티 symbol portfolio 지원 시 별도 설계 필요.
Release Execution Evidence
- Release Status Transition Target: released
Deployment Facts
- Executed At:
- 2026-06-19 17:27 KST
- Completed At:
- 2026-06-19 17:27 KST
- Environment:
- portfolio-hub 운영 인스턴스 (port 8002)
- Operator:
- trex-op (운영팀)
- Revision or Artifact:
- 배포 커밋:
d89f137(main HEAD, push 완료) - 이전 커밋:
50beba3→ 배포 커밋:d89f137 - 비고: Freeze pin
bd34450과 배포 커밋d89f137의 차이는 REL 문서(docs-only) 변경으로 런타임 동일
- 배포 커밋:
- Commands or Procedure:
bash /root/release/scripts/deploy-portfolio-hub.sh- DB 마이그레이션 없음 (alembic head
20260605_0025유지, REL-001 시점과 동일) - 프로세스: PID 461546 (port 8002), RUNNING (2026-06-19 17:33 KST 확인)
Profile-Specific Checks
- app-service:
- Health Endpoint:
GET /health→ HTTP 200,db_enabled: true(2026-06-19 배포 후 확인) ✅
- Startup Log Fields:
- PID 461546 (port 8002), RUNNING 상태 확인 (2026-06-19 17:33 KST) ✅
- Request Log Fields:
- (운영 관찰 계속 중)
- Smoke or Manual Verification:
- 배포 전 자동 테스트 evidence (2026-06-18):
- BAT-017 신규 테스트: 50 passed (test_wac_calculation.py 20건 + test_v1_portfolios_trades.py 12건 + test_v1_portfolios_pnl.py 18건) — pytest 실행 출력:
50 passed, 8 warnings in 3.43s - 기존 회귀 테스트: 377 passed, 0 failed — 회귀 없음
- 합계: 427 passed, 0 failed
- 독립 QC (
qc-reviewer, 2026-06-18): PASS-WITH-NOTES — 50 passed 독립 재현 + 전체 427 passed 회귀 없음, WAC=11,000/realized=199,300 단위+e2e 검증, R-1 경고필드(buy없음·oversell·완전이력 null) 정상, NFR-3 격리(domain DB import 0) 확인, 스코프·DB 마이그레이션 무, 위생 이상 없음. - 운영팀 주간 테스트: 4개 서비스 전수 통과 (2026-06-19 사장님 확인)
- BAT-017 신규 테스트: 50 passed (test_wac_calculation.py 20건 + test_v1_portfolios_trades.py 12건 + test_v1_portfolios_pnl.py 18건) — pytest 실행 출력:
- 배포 후 smoke (2026-06-19 17:27 KST, trex-op):
GET /health→ HTTP 200,db_enabled: true✅GET /v1/portfolios/{id}/trades?date=2026-06-19(read_token 이상) → HTTP 200, 체결 2건, 필드 전체 확인 (trade_id,side,quantity,price,executed_at,fee_amount,tax_amount) ✅ (REQ-039 AC-1)GET /v1/portfolios/{id}/trades(날짜 파라미터 누락) → HTTP 422 ✅ (REQ-039 AC-3)GET /v1/portfolios/{id}/pnl/realized?from=2026-06-01&to=2026-06-19(read_token 이상) → HTTP 200,total_realized_pnl=-9306.585, 필드 전체 확인 (total_realized_pnl,cost_basis_from,items,data_completeness_warning) ✅ (REQ-040 AC-1)GET /v1/portfolios/{id}/pnl/realized(from/to 누락) → HTTP 422 ✅ (REQ-040 AC-3)- 비소유자 토큰으로 신규 엔드포인트 호출 → HTTP 403 ✅ (REQ-039 AC-6, REQ-040 AC-7)
- 존재하지 않는 portfolio_id로 호출 → HTTP 404 ✅ (REQ-039 AC-7, REQ-040 AC-8)
- 기존
GET /v1/portfolios회귀 없음 ✅ - [비차단] OpenAPI
/docs신규 엔드포인트 2개 노출 — 수동 확인 미완 (운영 관찰 중, 차단 아님)
- 배포 전 자동 테스트 evidence (2026-06-18):
- Health Endpoint:
Rollback Outcome
- Rollback Required:
- No
- Rollback Trigger:
- none (트리거 조건 발생 없음)
- Rollback Action:
- none (롤백 수행 없음)
Release Decision Evidence
- Released Decision:
- released 전환 승인.
- Rationale:
- app-service profile released DoD 전항목 충족 판정 근거:
(1) 배포 완료: 2026-06-19 17:27 KST, trex-op 수행, 커밋
d89f137(freezebd34450대비 docs-only 차이, 런타임 동일) ✅ (2) 프로세스 기동 확인: PID 461546 (port 8002) RUNNING (17:33 KST 확인) ✅ (3) health endpoint:GET /health→ HTTP 200,db_enabled: true✅ (4) DB 마이그레이션 없음: alembic head20260605_0025유지 (REL-001과 동일) ✅ (5) 신규 엔드포인트 smoke 전항목 통과: trades 200/422, pnl/realized 200/422, 403/404 정상 ✅ (6) 기존 API 회귀 없음 ✅ (7) 롤백 불필요 (트리거 없음) ✅ (8) 배포 전 QC: BAT-017 50 passed + 전체 427 passed, qc-reviewer PASS-WITH-NOTES (2026-06-18) ✅ - 비차단 잔여 (released 전환을 막지 않음):
- OpenAPI
/docs신규 엔드포인트 노출 수동 확인 미완 — 기능 결함 아님, 운영 관찰 중 - Known Issues 4건 (symbol 필터 edge 테스트, HTTP_422 deprecated, 성능 미검증, symbol 컬럼 부재) — QC PASS-WITH-NOTES 비차단으로 이미 기록됨, cleanup/차기 Discovery 후보
- OpenAPI
- app-service profile released DoD 전항목 충족 판정 근거:
(1) 배포 완료: 2026-06-19 17:27 KST, trex-op 수행, 커밋
- Recorded By:
- 팀장 (portfolio-hub-dev evidence 기입 + released 전환 판정, 2026-06-19)
- Recorded At:
- 2026-06-19 KST
Feedback Handoff
- Observation Summary:
- (배포 후 운영 관찰 기록)
- Discovery Input:
- symbol 필터 edge (다른 symbol 필터 요청 케이스) 자동 테스트 보강 — cleanup batch 후보
- HTTP_422_UNPROCESSABLE_ENTITY deprecated cleanup — cleanup batch 후보
- 성능 테스트 (p95 500ms) — TimescaleDB 인덱스 환경 구성 후 별도 검증 Discovery 후보
- 멀티 symbol portfolio 지원 (symbol 컬럼 portfolio_ledger 추가) — 별도 Discovery 후보
- REQ Input:
- (운영 관찰 후 기록)
- Change Request Input:
- (운영 관찰 후 기록)