Files
portfolio-hub/docs/srs/Interface/req-039_trade-history-query-endpoint.md
T
genichinandClaude Opus 4.8 bd34450ee9 feat(pnl): trade history + realized PnL API (WAC) — BAT-017, REQ-039~042 Implemented
- 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
2026-06-18 16:45:01 +09:00

6.2 KiB

REQ-039: GET /v1/portfolios/{id}/trades 체결 내역 조회 엔드포인트 신설

  • Status: Implemented
  • Type: Interface
  • Priority: High
  • Owner: Justin Ko

Intent

  • portfolio_ledger(TimescaleDB hypertable)에 이미 적재된 체결 기록(side, quantity, price, fee_amount, tax_amount, executed_at 등)을 날짜/범위 필터로 외부에 노출하는 GET 엔드포인트를 신설한다.
  • 현재 list_recent_trades(portfolio_id, limit=5) 내부 메서드만 존재하며 날짜 필터 없이 최근 5건만 반환하는 한계를 해소한다.
  • 운영자 및 프론트엔드가 trex_core ledger_outbox 수기 조회 없이 portfolio-hub API 단독으로 체결 내역을 조회할 수 있게 한다(dcy-007 FR-1, S-1).

Requirement

  • 시스템은 GET /v1/portfolios/{portfolio_id}/trades 엔드포인트를 제공해야 한다.
  • date(YYYY-MM-DD) 단일 날짜 파라미터 또는 from/to 날짜 범위 파라미터로 portfolio_ledger를 필터링해 체결 기록 목록을 반환해야 한다.
  • 응답 각 항목은 side, quantity, price, fee_amount, tax_amount, executed_at, order_id, execution_id 필드를 포함해야 한다.
  • 인증은 기존 read_token 이상 권한(DB 토큰)으로 접근 가능해야 하며, 별도 권한 추가는 없다(dcy-007 FR-4, A-3).
  • 호출자 소유권 확인: 해당 portfolio_id가 호출 토큰 소유자의 portfolio인지 확인하고, 비소유자 비관리자 호출은 HTTP 403을 반환해야 한다.

Acceptance Criteria

  1. Given read_token 이상 권한 보유 사용자, portfolio_id에 2026-06-15 체결 기록 3건 존재, When GET /v1/portfolios/{id}/trades?date=2026-06-15, Then HTTP 200 + items 배열에 3건 반환, 각 항목에 side/quantity/price/fee_amount/tax_amount/executed_at/order_id/execution_id 포함.
  2. Given 동일 포트폴리오, 2026-06-01~2026-06-15 기간에 체결 기록 7건 존재, When GET /v1/portfolios/{id}/trades?from=2026-06-01&to=2026-06-15, Then HTTP 200 + items 7건 반환, from/to 범위 경계 날짜 포함.
  3. Given date 파라미터 누락 AND from/to 모두 누락, When 호출, Then HTTP 422 + 날짜 파라미터 필요 오류 메시지 반환.
  4. Given date 형식이 YYYY-MM-DD가 아닌 값(예: "20260615", "2026/06/15"), When 호출, Then HTTP 422 반환.
  5. Given 해당 날짜 범위에 체결 기록 0건, When 호출, Then HTTP 200 + {"items": [], "total": 0} 반환(404 아님).
  6. Given 비소유자 사용자 token(admin 아님), When 타인 portfolio_id 조회, Then HTTP 403 반환.
  7. Given 존재하지 않는 portfolio_id, When 호출, Then HTTP 404 반환.
  8. Given 엔드포인트 구현 완료, When OpenAPI /docs 또는 openapi.json 확인, Then GET /v1/portfolios/{portfolio_id}/trades 경로가 파라미터 설명과 함께 문서화되어 있음(NFR-2 반영).
  9. Given 30일 범위(from=D-30, to=today) 쿼리, When portfolio_ledger idx_portfolio_ledger_portfolio_executed 인덱스 사용 환경에서 호출, Then p95 응답 시간 500ms 이하(NFR-1 반영 — 통합/성능 테스트 환경에서 검증).

Impacted Area

  • Docs:
    • docs/runtime-flows.md — GET /v1/portfolios/{id}/trades 흐름 추가 필요
    • docs/project-structure.md — app/api/v1_portfolios.py 책임 갱신, app/schemas/v1.py TradeHistoryResponse 추가
  • Modules:
    • app/api/v1_portfolios.py — GET 엔드포인트 추가(날짜 파라미터 파싱, 소유권 확인, repository 위임)
    • app/repositories/postgres.py — list_trades_by_date(portfolio_id, date, from_, to_) 메서드 추가
    • app/repositories/portfolio_repository.py — abstract method 추가
    • app/schemas/v1.py — TradeHistoryItem, TradeHistoryResponse 스키마 추가
  • Tests:
    • tests/test_v1_portfolios_trades.py 신규 — AC-1~9 커버

Notes

  • date vs from/to 파라미터 중 하나만 허용하거나 date가 from=to의 단축형으로 동작하는지 구현 단계에서 결정. 단, AC-3(둘 다 없으면 422)는 확정.
  • portfolio_ledger TimescaleDB hypertable의 파티션 키는 recorded_at(또는 executed_at)이며, 날짜 범위 쿼리는 기존 idx_portfolio_ledger_portfolio_executed 인덱스를 활용해야 한다(NFR-1, dcy-007 R-2 완화).
  • 페이지네이션 요구사항은 이번 범위에 명시되지 않음. 구현 단계에서 대용량 결과 처리 방식 결정 필요(NFR 미정 — 현재 범위 밖으로 이연).
  • DB 마이그레이션 불필요 — 기존 portfolio_ledger 스키마로 조회 가능(dcy-007 영향 범위 확인).
  • Source: dcy-007 FR-1, FR-4, NFR-1, NFR-2, S-1.

Change Log

CHG-20260618-01

  • Date: 2026-06-18
  • Author: Justin Ko

Change Summary

  • 최초 생성 — dcy-007 confirm-discovery 후 draft-req 실행. 일일 거래내역 조회 API 산출물.

Intent

  • dcy-007 FR-1(체결 내역 조회 엔드포인트 신설)을 구현 가능한 Interface REQ로 정규화.

Acceptance Criteria Delta

  • Added:
    • AC-1~9 최초 작성

Impacted Area Delta

  • Docs: docs/runtime-flows.md, docs/project-structure.md — 최초 지정
  • Modules: app/api/v1_portfolios.py, app/repositories/postgres.py, app/repositories/portfolio_repository.py, app/schemas/v1.py — 최초 지정
  • Tests: tests/test_v1_portfolios_trades.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 후 batch 계획 편입

Validation Plan

  • pytest TestClient로 AC-1~8 검증; AC-9 성능은 통합/성능 테스트 환경에서 검증

CHG-20260618-02

  • Date: 2026-06-18
  • Author: 팀장 (Claude)

Change Summary

  • confirm-req: Proposed → Approved. dcy-007 FR-1/FR-4 정합, AC 구체적·test 가능, blocker 없음. date vs from/to 상호작용은 구현 단계 결정(AC-3 422 확정). M1 fast-track — REQ-040~042와 동일 batch.

CHG-20260618-03

  • Date: 2026-06-18
  • Author: 팀장 (Claude)

Change Summary

  • confirm-req-implemented: Approved → Implemented. Evidence: BAT-017 release-candidate, 독립 QC PASS-WITH-NOTES, test_v1_portfolios_trades.py 12 passed(AC-1~8), 성능 AC-9는 환경제약 미검증. metrics/DB 마이그레이션 무.