chore: commit current workspace changes
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
- Baseline Seed: .stage-pilot/bootstrap/baseline.yaml
|
||||
- Status: draft
|
||||
- Owner: project maintainers
|
||||
- Last Updated (KST): 2026-06-03 (BAT-002)
|
||||
- Last Updated (KST): 2026-06-04 (BAT-006)
|
||||
- Source Discovery / Batch: bootstrap-baseline (pre-Discovery); HTTP API = dcy-002 / BAT-002
|
||||
- Primary Runtime: daemon (HTTP API) + library (slot 도메인)
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
- HTTP `/v1` API :: 슬롯 코어 데몬이 노출, 매수·매도 전략 데몬이 호출(REQ-005/007/008)
|
||||
- SlotService :: 슬롯 생명주기 도메인 서비스(전이/사전할당/가용성/재진입 카운트)
|
||||
- SlotRepository (Protocol) :: 도메인 ↔ 저장소 경계 계약
|
||||
- BrokerPort (Protocol) :: 단일 브로커 세션 경계(submit/poll/cancel) + `OrderRequest`/`OrderAck`/`FillStatus`
|
||||
- LedgerPort (Protocol) :: 외부 원장(portfolio-hub) 기록 경계 + `LedgerTrade`/`LedgerWriteResult`/예외 (BAT-006)
|
||||
- LedgerOutbox (Protocol) + LedgerWriter :: 체결 → 원장 기록의 outbox/재시도/멱등 (BAT-006)
|
||||
|
||||
## Interface: `HTTP /v1` (슬롯 코어 데몬)
|
||||
|
||||
@@ -113,6 +116,83 @@
|
||||
- 구현체는 advisory lock 직렬화와 append-only 전이 로그 의미를 반드시 보장한다.
|
||||
- 구현체는 lock 보유 중 외부 I/O 를 수행하지 않는다.
|
||||
|
||||
## Interface: `LedgerPort` (BAT-006)
|
||||
|
||||
- Type: external-service (HTTP, portfolio-hub)
|
||||
- Consumers / Producers: `LedgerWriter`(소비) → `PortfolioHubLedger` 어댑터 또는 `InMemoryLedger` stub
|
||||
- Purpose: 체결을 외부 회계/포지션 원장에 기록한다. orbit `post_ledger_trade` 패턴.
|
||||
- Stability: experimental (v1)
|
||||
|
||||
### Inputs
|
||||
|
||||
- record_trade(trade: LedgerTrade) :: 단일 체결을 원장에 기록 (`execution_id` 멱등)
|
||||
|
||||
### `LedgerTrade` Fields
|
||||
|
||||
- asset_id :: str :: ledger path param (= 슬롯 `portfolio_id`, dcy-004 OQ-1)
|
||||
- order_id :: str :: 로컬 주문 식별자 (`broker_order_id`)
|
||||
- execution_id :: str :: 결정적 합성 (paper: `paper:{broker_order_id}:{filled_qty}`, KIS: `kis-daily-ccld:{ord_dt}:{ord_gno_brno}:{odno}:{tot_ccld_qty}`)
|
||||
- side :: 'buy' | 'sell'
|
||||
- qty / price :: float :: 체결 수량 / 평단
|
||||
- fee :: float :: `BrokerPort.calculate_fee(side, qty*price)` 결과
|
||||
- tax :: float :: 기본 0 (정밀 모델 후속)
|
||||
- executed_at :: datetime?
|
||||
- correlation_id (derived) :: `{asset_id}:{order_id}:{execution_id}` — 로컬 dedup 키
|
||||
|
||||
### Outputs / Outcomes
|
||||
|
||||
- `LedgerWriteResult.NEW` :: 새 원장 엔트리 적재
|
||||
- `LedgerWriteResult.DUPLICATE_OK` :: 같은 execution_id 가 이미 기록되어 있음(서버 멱등)
|
||||
|
||||
### Error Contract
|
||||
|
||||
- `LedgerConflictError` :: portfolio-hub 409 — 운영자 해소 대상(자동 재시도 중단)
|
||||
- `LedgerRetryableError` :: 5xx / timeout / network — outbox 가 재시도
|
||||
|
||||
### portfolio-hub Endpoint (어댑터 구현)
|
||||
|
||||
| HTTP | URL | Body | 응답 |
|
||||
|---|---|---|---|
|
||||
| POST | `/v1/assets/{asset_id}/ledger/trades` | `side, qty, price, fee, tax, executed_at, execution_id, order_id` | 2xx OK(`duplicate:true` 면 server-side dedup), 409 conflict, 5xx/network → retryable |
|
||||
|
||||
## Interface: `LedgerOutbox` Protocol + `LedgerWriter` (BAT-006)
|
||||
|
||||
- Type: internal-service (durable work-item store + drainer)
|
||||
- Consumers / Producers: `ExecutionService`(생산자, fill 시 enqueue) → `LedgerWriter`(소비자, 백그라운드 워커)
|
||||
- Purpose: 체결 → 원장 기록을 슬롯 전이와 분리해 무유실 + 멱등으로 처리한다. correlation_id 로 outbox 적재 dedup.
|
||||
- Stability: internal
|
||||
|
||||
### Inputs
|
||||
|
||||
- enqueue(trade: LedgerTrade) :: `correlation_id` 키로 멱등 적재
|
||||
- list_pending(limit) :: FIFO pending work item
|
||||
- get(correlation_id) :: 단일 row 조회
|
||||
- mark_outcome(correlation_id, outcome, error?) :: outcome 기록 + 상태 전이
|
||||
|
||||
### Outcomes (`OutboxOutcome`)
|
||||
|
||||
- `completed` :: 어댑터 NEW
|
||||
- `duplicate_completed` :: 어댑터 DUPLICATE_OK 또는 로컬 dedup 히트
|
||||
- `retryable_failure` :: 다음 tick 재시도 (status 는 `pending` 유지)
|
||||
- `conflict_blocked` :: 409, 자동 재시도 중단(운영자 해소)
|
||||
|
||||
### WorkItem Status
|
||||
|
||||
- pending → completed (성공/중복)
|
||||
- pending → conflict_blocked (409)
|
||||
- pending → pending (retryable, attempts++)
|
||||
|
||||
### Persistence
|
||||
|
||||
- PostgreSQL: `ledger_outbox(correlation_id PK, asset_id, order_id, execution_id, side, qty, price, fee, tax, executed_at, status, attempts, last_outcome, last_error, created_at, updated_at)` — `ON CONFLICT (correlation_id) DO NOTHING` 이 outbox dedup 게이트.
|
||||
|
||||
## `FillStatus` 확장 (BAT-006 / REQ-018)
|
||||
|
||||
- `state, filled_qty, avg_price, raw` 외에 다음 필드를 운반한다.
|
||||
- `execution_id :: str?` :: 결정적 합성(브로커별 규칙). filled 상태에서 필수.
|
||||
- `fee :: float` :: BrokerPort `calculate_fee` 결과(기본 0).
|
||||
- `tax :: float` :: 기본 0(정밀 모델 후속).
|
||||
|
||||
## Shared Constraints
|
||||
|
||||
- 도메인은 외부 의존(브로커, DB 드라이버 등)을 직접 호출하지 않는다(순수 도메인 경계).
|
||||
@@ -135,3 +215,4 @@
|
||||
- 2026-06-03 :: bootstrap-baseline 으로 초기 인터페이스 계약 baseline 생성(SlotService + SlotRepository Protocol).
|
||||
- 2026-06-03 :: BAT-002 — HTTP `/v1` API 계약(데몬, 6 엔드포인트) + 멱등/단일writer 불변식 추가(REQ-007/008/009).
|
||||
- 2026-06-04 :: BAT-004 — 브로커 집행 레이어 반영(BrokerPort/paper·KIS 어댑터, execution 루프, broker_order_id 실행큐·멱등, reconciliation) (REQ-011~015).
|
||||
- 2026-06-04 :: BAT-006 — LedgerPort/LedgerTrade/LedgerWriteResult 계약, LedgerOutbox/LedgerWriter, portfolio-hub `/v1/assets/{asset_id}/ledger/trades` 엔드포인트 + 409→`LedgerConflictError`, FillStatus.execution_id/fee/tax 확장 (REQ-017~020).
|
||||
|
||||
Reference in New Issue
Block a user