From b1c34068e5644998c1c90c97ddbe3a352ec93927 Mon Sep 17 00:00:00 2001 From: Justin Ko Date: Mon, 22 Jun 2026 09:51:13 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20batch=20=EC=83=81=ED=83=9C=20released?= =?UTF-8?q?=20=EB=8F=99=EA=B8=B0=ED=99=94(REL-001/002)=20+=20README=20?= =?UTF-8?q?=ED=98=84=ED=96=89=ED=99=94(=EA=B1=B0=EB=9E=98=EB=82=B4?= =?UTF-8?q?=EC=97=AD/=EC=8B=A4=ED=98=84PnL=20API)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit batch drift 정합 — REL-001(BAT-001~016)·REL-002(BAT-017) released에 맞춰 batches/index 및 개별 index 상태를 release-candidate→released 동기화(17건). README: bootstrap 문구 제거, dcy-007 엔드포인트(GET /trades·/pnl/realized) 추가, planned-next 현행화. 코드 무변경. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5 --- README.md | 58 +++++++++++++++++-- .../index.md | 2 +- .../index.md | 2 +- .../index.md | 2 +- .../bat-004_20260520_tags-http-api/index.md | 2 +- .../index.md | 2 +- .../index.md | 2 +- .../index.md | 2 +- .../index.md | 2 +- .../index.md | 2 +- .../index.md | 2 +- .../index.md | 2 +- .../index.md | 2 +- .../index.md | 2 +- .../index.md | 2 +- .../index.md | 2 +- .../index.md | 2 +- .../index.md | 2 +- docs/batches/index.md | 34 +++++------ 19 files changed, 87 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 3caa16d..2f007ab 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,13 @@ Portfolio Hub is a FastAPI service that extracts portfolio management from `jsbo ## Current status -This repository is in bootstrap phase. - - FastAPI application entrypoint is available. - Token-based authentication and role checks are implemented. - Portfolio and user management API contracts are implemented. - Core portfolio domain services are ported from `jsbot-kis`. - Postgres-backed portfolio and user persistence is implemented and gated behind `pfhub_DB_ENABLED=true`. +- Alembic-managed schema migrations are applied in production (head: `20260605_0025`). +- Trade history and realized PnL query API is implemented (`GET /v1/portfolios/{id}/trades`, `GET /v1/portfolios/{id}/pnl/realized`). ## Configuration @@ -425,6 +425,52 @@ The default `.env.example` includes example tokens for development. When `pfhub_DB_ENABLED=true` and both `pfhub_BOOTSTRAP_USERNAME` and `pfhub_BOOTSTRAP_PASSWORD` are set, the app creates that admin user automatically on startup only if the `users` table is empty. This is intended for first-run bootstrap, not recurring synchronization. +## Portfolio API + +Portfolio management and ledger access are exposed through `/v1/portfolios`. + +- `POST /v1/portfolios`: create a portfolio (requires `trade-write` or session token) +- `GET /v1/portfolios`: list portfolios for the authenticated user +- `PATCH /v1/portfolios/{id}`: update portfolio metadata +- `DELETE /v1/portfolios/{id}`: delete a portfolio (requires `admin`) +- `POST /v1/portfolios/{id}/ledger/trades`: record a trade entry with accounting (`cash_balance_after`, `asset_quantity_after`) +- `GET /v1/portfolios/{id}/tags`: list tags on a portfolio +- `POST /v1/portfolios/{id}/tags`: apply a tag to a portfolio +- `DELETE /v1/portfolios/{id}/tags/{tag_id}`: remove a tag from a portfolio +- `POST /v1/portfolios/{id}/comments`: add a comment +- `GET /v1/portfolios/{id}/comments`: list comments +- `PATCH /v1/portfolios/{id}/comments/{comment_id}`: update a comment +- `DELETE /v1/portfolios/{id}/comments/{comment_id}`: delete a comment +- `GET /v1/portfolios/{id}/trades`: query trade history with date filter (requires `read` or higher) +- `GET /v1/portfolios/{id}/pnl/realized`: compute WAC-based realized PnL over a date range (requires `read` or higher) + +### Trade history query (`GET /v1/portfolios/{id}/trades`) + +Supports single-date and range queries via query parameters. At least one date parameter is required. + +```bash +# Single date +curl -X GET "http://localhost:8000/v1/portfolios//trades?date=2026-06-19" \ + -H "Authorization: Bearer " + +# Date range +curl -X GET "http://localhost:8000/v1/portfolios//trades?from=2026-06-01&to=2026-06-19" \ + -H "Authorization: Bearer " +``` + +Response fields per trade item: `trade_id`, `side`, `quantity`, `price`, `executed_at`, `fee_amount`, `tax_amount`. + +### Realized PnL query (`GET /v1/portfolios/{id}/pnl/realized`) + +Computes weighted-average cost (WAC) based realized PnL over the specified date range. `from` and `to` are required. `symbol` is an optional filter. + +```bash +curl -X GET "http://localhost:8000/v1/portfolios//pnl/realized?from=2026-06-01&to=2026-06-19" \ + -H "Authorization: Bearer " +``` + +Response fields: `total_realized_pnl`, `cost_basis_from`, `items` (per-sell realized PnL), `data_completeness_warning` (set when buy history before `from` is incomplete). + ## Production Operator Runbook 이 섹션은 실배포 환경에서 admin 접근, release smoke credential 관리, provenance 확인, 로그 증적 수집을 반복 가능한 절차로 정리한다. @@ -514,6 +560,8 @@ curl -X POST "/auth/service-tokens" \ ## Planned next steps -1. Apply and verify Alembic migrations against a real PostgreSQL/Timescale instance. -2. Add integration tests for DB-backed portfolio and user flows. -3. Design token-to-user mapping if ownership or user-scoped authorization is needed later. +1. Add integration tests for DB-backed portfolio and user flows. +2. Add unrealized PnL (current price integration) — deferred from dcy-007. +3. Add pagination for trade history and PnL endpoints. +4. Remove legacy `POST /portfolios/{id}/buy` and `POST /portfolios/{id}/sell` endpoints (currently deprecated-only). +5. Fix `pfhub tag apply asset` / `pfhub tag remove asset` CLI mismatch (targets portfolios table instead of assets). diff --git a/docs/batches/bat-001_20260519_asset-catalog-db-foundation/index.md b/docs/batches/bat-001_20260519_asset-catalog-db-foundation/index.md index 6ae1293..670197f 100644 --- a/docs/batches/bat-001_20260519_asset-catalog-db-foundation/index.md +++ b/docs/batches/bat-001_20260519_asset-catalog-db-foundation/index.md @@ -1,6 +1,6 @@ # BAT-001: asset catalog DB 기반 도입 -- Status: verified +- Status: released - Profile: standard - Source Discovery: dcy-001 - Included REQ: REQ-009, REQ-011, REQ-014 diff --git a/docs/batches/bat-002_20260519_asset-catalog-api-completion/index.md b/docs/batches/bat-002_20260519_asset-catalog-api-completion/index.md index d7c89e8..ebfe311 100644 --- a/docs/batches/bat-002_20260519_asset-catalog-api-completion/index.md +++ b/docs/batches/bat-002_20260519_asset-catalog-api-completion/index.md @@ -1,6 +1,6 @@ # BAT-002: asset catalog API 완결 -- Status: release-candidate +- Status: released - Profile: standard - Source Discovery: dcy-001 - Included REQ: REQ-010, REQ-012, REQ-013, REQ-015 diff --git a/docs/batches/bat-003_20260519_tags-db-foundation/index.md b/docs/batches/bat-003_20260519_tags-db-foundation/index.md index 6d085de..c148834 100644 --- a/docs/batches/bat-003_20260519_tags-db-foundation/index.md +++ b/docs/batches/bat-003_20260519_tags-db-foundation/index.md @@ -1,6 +1,6 @@ # BAT-003: tags DB 기반 -- Status: release-candidate +- Status: released - Profile: standard - Source Discovery: dcy-002 - Included REQ: REQ-001, REQ-002, REQ-003, REQ-006 diff --git a/docs/batches/bat-004_20260520_tags-http-api/index.md b/docs/batches/bat-004_20260520_tags-http-api/index.md index 61466f1..1dfce5f 100644 --- a/docs/batches/bat-004_20260520_tags-http-api/index.md +++ b/docs/batches/bat-004_20260520_tags-http-api/index.md @@ -1,6 +1,6 @@ # BAT-004: tags HTTP API -- Status: release-candidate +- Status: released - Profile: standard - Source Discovery: dcy-002 - Included REQ: REQ-004, REQ-005 diff --git a/docs/batches/bat-005_20260520_pfhub-tag-cli-and-docs/index.md b/docs/batches/bat-005_20260520_pfhub-tag-cli-and-docs/index.md index 3eb6c40..cc8bbd6 100644 --- a/docs/batches/bat-005_20260520_pfhub-tag-cli-and-docs/index.md +++ b/docs/batches/bat-005_20260520_pfhub-tag-cli-and-docs/index.md @@ -1,6 +1,6 @@ # BAT-005: pfhub tag CLI 및 baseline docs 갱신 -- Status: release-candidate +- Status: released - Profile: standard - Source Discovery: dcy-002 - Included REQ: REQ-007, REQ-008 diff --git a/docs/batches/bat-006_20260520_token-surface-code-fixes/index.md b/docs/batches/bat-006_20260520_token-surface-code-fixes/index.md index 09123df..c18b17c 100644 --- a/docs/batches/bat-006_20260520_token-surface-code-fixes/index.md +++ b/docs/batches/bat-006_20260520_token-surface-code-fixes/index.md @@ -1,6 +1,6 @@ # BAT-006: token surface 코드 수정 (client 폐지 / rotate index 보강 / daemon_id forward 보정) -- Status: release-candidate +- Status: released - Profile: standard - Source Discovery: dcy-004 - Included REQ: REQ-016, REQ-017, REQ-018 diff --git a/docs/batches/bat-007_20260520_daemon-lifecycle-token-enforcement/index.md b/docs/batches/bat-007_20260520_daemon-lifecycle-token-enforcement/index.md index 68af9ba..d6bedb1 100644 --- a/docs/batches/bat-007_20260520_daemon-lifecycle-token-enforcement/index.md +++ b/docs/batches/bat-007_20260520_daemon-lifecycle-token-enforcement/index.md @@ -1,6 +1,6 @@ # BAT-007: daemon lifecycle token 정책 (deactivation 자동 revoke + NULL daemon 마이그레이션 CLI) -- Status: release-candidate +- Status: released - Profile: standard - Source Discovery: dcy-004 - Included REQ: REQ-022, REQ-023 diff --git a/docs/batches/bat-008_20260521_token-surface-docs/index.md b/docs/batches/bat-008_20260521_token-surface-docs/index.md index 28964bc..526acc2 100644 --- a/docs/batches/bat-008_20260521_token-surface-docs/index.md +++ b/docs/batches/bat-008_20260521_token-surface-docs/index.md @@ -1,6 +1,6 @@ # BAT-008: dcy-004 토큰 surface baseline 문서화 -- Status: release-candidate +- Status: released - Profile: standard - Source Discovery: dcy-004 - Included REQ: REQ-019, REQ-020, REQ-021, REQ-024 diff --git a/docs/batches/bat-009_20260521_v1-portfolios-crud-core/index.md b/docs/batches/bat-009_20260521_v1-portfolios-crud-core/index.md index 5c98f2c..a2d1dbd 100644 --- a/docs/batches/bat-009_20260521_v1-portfolios-crud-core/index.md +++ b/docs/batches/bat-009_20260521_v1-portfolios-crud-core/index.md @@ -1,6 +1,6 @@ # BAT-009: v1 portfolio CRUD core (POST/PATCH/DELETE/GET) -- Status: release-candidate +- Status: released - Profile: standard - Source Discovery: dcy-003 - Included REQ: REQ-025, REQ-026, REQ-027, REQ-028 diff --git a/docs/batches/bat-010_20260521_v1-portfolios-sub-resources/index.md b/docs/batches/bat-010_20260521_v1-portfolios-sub-resources/index.md index 8323cf0..92c83ea 100644 --- a/docs/batches/bat-010_20260521_v1-portfolios-sub-resources/index.md +++ b/docs/batches/bat-010_20260521_v1-portfolios-sub-resources/index.md @@ -1,6 +1,6 @@ # BAT-010: v1 portfolio sub-resources (tags/comments + baseline docs) -- Status: release-candidate +- Status: released - Profile: standard - Source Discovery: dcy-003 - Included REQ: REQ-030, REQ-031, REQ-032 diff --git a/docs/batches/bat-011_20260521_v1-portfolios-ledger-path-migration/index.md b/docs/batches/bat-011_20260521_v1-portfolios-ledger-path-migration/index.md index 38caabb..7fc5a5c 100644 --- a/docs/batches/bat-011_20260521_v1-portfolios-ledger-path-migration/index.md +++ b/docs/batches/bat-011_20260521_v1-portfolios-ledger-path-migration/index.md @@ -1,6 +1,6 @@ # BAT-011: v1 portfolios ledger path migration -- Status: release-candidate +- Status: released - Profile: standard - Source Discovery: dcy-003 - Included REQ: REQ-029 diff --git a/docs/batches/bat-012_20260521_assets-tagging-and-admin-get-redefinition/index.md b/docs/batches/bat-012_20260521_assets-tagging-and-admin-get-redefinition/index.md index 1b2f554..4881faf 100644 --- a/docs/batches/bat-012_20260521_assets-tagging-and-admin-get-redefinition/index.md +++ b/docs/batches/bat-012_20260521_assets-tagging-and-admin-get-redefinition/index.md @@ -1,6 +1,6 @@ # BAT-012: assets tag_ids 컬럼 + admin GET /v1/assets 재정의 -- Status: release-candidate +- Status: released - Profile: standard - Source Discovery: dcy-002 (REQ-002), dcy-001 + dcy-003 augmentation (REQ-010) - Included REQ: REQ-002, REQ-010 diff --git a/docs/batches/bat-013_20260521_asset-tag-apply-remove-fix/index.md b/docs/batches/bat-013_20260521_asset-tag-apply-remove-fix/index.md index ed97bfe..0c518ad 100644 --- a/docs/batches/bat-013_20260521_asset-tag-apply-remove-fix/index.md +++ b/docs/batches/bat-013_20260521_asset-tag-apply-remove-fix/index.md @@ -1,6 +1,6 @@ # BAT-013: asset tag apply/remove SQL 정합화 (REQ-005) -- Status: release-candidate +- Status: released - Profile: batch-lite - Source Discovery: dcy-002 (REQ-005) - Included REQ: REQ-005 diff --git a/docs/batches/bat-014_20260524_portfolioitem-symbol-response-contract/index.md b/docs/batches/bat-014_20260524_portfolioitem-symbol-response-contract/index.md index 7579b2b..9d9f07d 100644 --- a/docs/batches/bat-014_20260524_portfolioitem-symbol-response-contract/index.md +++ b/docs/batches/bat-014_20260524_portfolioitem-symbol-response-contract/index.md @@ -1,6 +1,6 @@ # BAT-014: PortfolioItem symbol 응답 계약 보강 (REQ-025, REQ-026, REQ-027, REQ-028, REQ-032) -- Status: release-candidate +- Status: released - Profile: batch-lite - Source Discovery: dcy-003 - Included REQ: REQ-025, REQ-026, REQ-027, REQ-028, REQ-032 diff --git a/docs/batches/bat-015_20260601_rel-001-feedback-cleanup/index.md b/docs/batches/bat-015_20260601_rel-001-feedback-cleanup/index.md index d29c524..be04bcb 100644 --- a/docs/batches/bat-015_20260601_rel-001-feedback-cleanup/index.md +++ b/docs/batches/bat-015_20260601_rel-001-feedback-cleanup/index.md @@ -1,6 +1,6 @@ # BAT-015: REL-001 Feedback 정합화 (ledger 컬럼명 / LoginRequest 엄격화 / health db_enabled) -- Status: release-candidate +- Status: released - Profile: standard - Source Discovery: dcy-005 - Included REQ: REQ-033, REQ-034, REQ-035 diff --git a/docs/batches/bat-016_20260605_ledger-accounting-consolidation/index.md b/docs/batches/bat-016_20260605_ledger-accounting-consolidation/index.md index 621a1a3..bb28133 100644 --- a/docs/batches/bat-016_20260605_ledger-accounting-consolidation/index.md +++ b/docs/batches/bat-016_20260605_ledger-accounting-consolidation/index.md @@ -1,6 +1,6 @@ # BAT-016: ledger 회계 책임 단일화 + portfolio_ledger 통합 -- Status: release-candidate +- Status: released - Profile: standard - Source Discovery: dcy-006 - Included REQ: REQ-036, REQ-037, REQ-038 diff --git a/docs/batches/bat-017_20260618_trade-history-and-pnl-api/index.md b/docs/batches/bat-017_20260618_trade-history-and-pnl-api/index.md index 3513447..455aa78 100644 --- a/docs/batches/bat-017_20260618_trade-history-and-pnl-api/index.md +++ b/docs/batches/bat-017_20260618_trade-history-and-pnl-api/index.md @@ -1,6 +1,6 @@ # BAT-017: 일일 거래내역 + 실현 PnL 조회 API (dcy-007 M1 fast-track) -- Status: in-delivery +- Status: released - Profile: standard - Source Discovery: dcy-007 - Included REQ: REQ-039, REQ-040, REQ-041, REQ-042 diff --git a/docs/batches/index.md b/docs/batches/index.md index f14d5b1..722e603 100644 --- a/docs/batches/index.md +++ b/docs/batches/index.md @@ -8,20 +8,20 @@ | BAT ID | Profile | Status | Included REQ | Discovery | Folder | | --- | --- | --- | --- | --- | --- | -| BAT-001 | standard | release-candidate | REQ-009, REQ-011, REQ-014 | dcy-001 | [bat-001](./bat-001_20260519_asset-catalog-db-foundation/) | -| BAT-002 | standard | release-candidate | REQ-010, REQ-012, REQ-013, REQ-015 | dcy-001 | [bat-002](./bat-002_20260519_asset-catalog-api-completion/) | -| BAT-003 | standard | release-candidate | REQ-001, REQ-002, REQ-003, REQ-006 | dcy-002 | [bat-003](./bat-003_20260519_tags-db-foundation/) | -| BAT-004 | standard | release-candidate | REQ-004, REQ-005 | dcy-002 | [bat-004](./bat-004_20260520_tags-http-api/) | -| BAT-005 | standard | release-candidate | REQ-007, REQ-008 | dcy-002 | [bat-005](./bat-005_20260520_pfhub-tag-cli-and-docs/) | -| BAT-006 | standard | release-candidate | REQ-016, REQ-017, REQ-018 | dcy-004 | [bat-006](./bat-006_20260520_token-surface-code-fixes/) | -| BAT-007 | standard | release-candidate | REQ-022, REQ-023 | dcy-004 | [bat-007](./bat-007_20260520_daemon-lifecycle-token-enforcement/) | -| BAT-008 | standard | release-candidate | REQ-019, REQ-020, REQ-021, REQ-024 | dcy-004 | [bat-008](./bat-008_20260521_token-surface-docs/) | -| BAT-009 | standard | release-candidate | REQ-025, REQ-026, REQ-027, REQ-028 | dcy-003 | [bat-009](./bat-009_20260521_v1-portfolios-crud-core/) | -| BAT-010 | standard | release-candidate | REQ-030, REQ-031, REQ-032 | dcy-003 | [bat-010](./bat-010_20260521_v1-portfolios-sub-resources/) | -| BAT-011 | standard | release-candidate | REQ-029 | dcy-003 | [bat-011](./bat-011_20260521_v1-portfolios-ledger-path-migration/) | -| BAT-012 | standard | release-candidate | REQ-002, REQ-010 | dcy-001, dcy-002, dcy-003 | [bat-012](./bat-012_20260521_assets-tagging-and-admin-get-redefinition/) | -| BAT-013 | batch-lite | release-candidate | REQ-005 | dcy-002 | [bat-013](./bat-013_20260521_asset-tag-apply-remove-fix/) | -| BAT-014 | batch-lite | release-candidate | REQ-025, REQ-026, REQ-027, REQ-028, REQ-032 | dcy-003 | [bat-014](./bat-014_20260524_portfolioitem-symbol-response-contract/) | -| BAT-015 | standard | release-candidate | REQ-033, REQ-034, REQ-035 | dcy-005 | [bat-015](./bat-015_20260601_rel-001-feedback-cleanup/) | -| BAT-016 | standard | release-candidate | REQ-036, REQ-037, REQ-038 | dcy-006 | [bat-016](./bat-016_20260605_ledger-accounting-consolidation/) | -| BAT-017 | standard | release-candidate | REQ-039, REQ-040, REQ-041, REQ-042 | dcy-007 | [bat-017](./bat-017_20260618_trade-history-and-pnl-api/) | +| BAT-001 | standard | released | REQ-009, REQ-011, REQ-014 | dcy-001 | [bat-001](./bat-001_20260519_asset-catalog-db-foundation/) | +| BAT-002 | standard | released | REQ-010, REQ-012, REQ-013, REQ-015 | dcy-001 | [bat-002](./bat-002_20260519_asset-catalog-api-completion/) | +| BAT-003 | standard | released | REQ-001, REQ-002, REQ-003, REQ-006 | dcy-002 | [bat-003](./bat-003_20260519_tags-db-foundation/) | +| BAT-004 | standard | released | REQ-004, REQ-005 | dcy-002 | [bat-004](./bat-004_20260520_tags-http-api/) | +| BAT-005 | standard | released | REQ-007, REQ-008 | dcy-002 | [bat-005](./bat-005_20260520_pfhub-tag-cli-and-docs/) | +| BAT-006 | standard | released | REQ-016, REQ-017, REQ-018 | dcy-004 | [bat-006](./bat-006_20260520_token-surface-code-fixes/) | +| BAT-007 | standard | released | REQ-022, REQ-023 | dcy-004 | [bat-007](./bat-007_20260520_daemon-lifecycle-token-enforcement/) | +| BAT-008 | standard | released | REQ-019, REQ-020, REQ-021, REQ-024 | dcy-004 | [bat-008](./bat-008_20260521_token-surface-docs/) | +| BAT-009 | standard | released | REQ-025, REQ-026, REQ-027, REQ-028 | dcy-003 | [bat-009](./bat-009_20260521_v1-portfolios-crud-core/) | +| BAT-010 | standard | released | REQ-030, REQ-031, REQ-032 | dcy-003 | [bat-010](./bat-010_20260521_v1-portfolios-sub-resources/) | +| BAT-011 | standard | released | REQ-029 | dcy-003 | [bat-011](./bat-011_20260521_v1-portfolios-ledger-path-migration/) | +| BAT-012 | standard | released | REQ-002, REQ-010 | dcy-001, dcy-002, dcy-003 | [bat-012](./bat-012_20260521_assets-tagging-and-admin-get-redefinition/) | +| BAT-013 | batch-lite | released | REQ-005 | dcy-002 | [bat-013](./bat-013_20260521_asset-tag-apply-remove-fix/) | +| BAT-014 | batch-lite | released | REQ-025, REQ-026, REQ-027, REQ-028, REQ-032 | dcy-003 | [bat-014](./bat-014_20260524_portfolioitem-symbol-response-contract/) | +| BAT-015 | standard | released | REQ-033, REQ-034, REQ-035 | dcy-005 | [bat-015](./bat-015_20260601_rel-001-feedback-cleanup/) | +| BAT-016 | standard | released | REQ-036, REQ-037, REQ-038 | dcy-006 | [bat-016](./bat-016_20260605_ledger-accounting-consolidation/) | +| BAT-017 | standard | released | REQ-039, REQ-040, REQ-041, REQ-042 | dcy-007 | [bat-017](./bat-017_20260618_trade-history-and-pnl-api/) |