docs: batch 상태 released 동기화(REL-001/002) + README 현행화(거래내역/실현PnL API)

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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
This commit is contained in:
2026-06-22 09:51:13 +09:00
co-authored by Claude Opus 4.8
parent 16746008cc
commit b1c34068e5
19 changed files with 87 additions and 39 deletions
+53 -5
View File
@@ -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/<id>/trades?date=2026-06-19" \
-H "Authorization: Bearer <READ_TOKEN>"
# Date range
curl -X GET "http://localhost:8000/v1/portfolios/<id>/trades?from=2026-06-01&to=2026-06-19" \
-H "Authorization: Bearer <READ_TOKEN>"
```
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/<id>/pnl/realized?from=2026-06-01&to=2026-06-19" \
-H "Authorization: Bearer <READ_TOKEN>"
```
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 "<BASE_URL>/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).
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
+17 -17
View File
@@ -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/) |