Files
trex-core/docs/batches/bat-004_20260604_broker-execution-and-outbox/design.md
T
genichinandClaude Opus 4.8 97d58318db Deliver BAT-004: broker execution + KIS adapter + durable handoff
Implement REQ-011~015 (dcy-003): the order-execution layer on top of the
BAT-002 slot-core daemon, connecting intents to real orders.
- application: BrokerPort (submit/poll_fill/cancel) + ExecutionService
  (claim -> submit -> poll -> transition -> rollback -> reconcile)
- adapters/broker: PaperBroker (deterministic async double) and KISBroker
  (KIS Open API: token, order-cash, inquire-daily-ccld, cancel; VTS sandbox
  tr_ids; live account gated behind allow_live)
- persistence: option-A execution queue (find_pending_for_dispatch FOR
  UPDATE SKIP LOCKED, mark_dispatched idempotency guard, clear_dispatch)
- runtime: background execution loop in the daemon lifespan + startup
  reconcile; config selects paper|kis

Verification (real KIS VTS 모의투자 + PostgreSQL): 92 passed, ruff clean,
domain import sweep shows zero broker/web/db deps, buy->holding /
sell->closed / reject->idle, idempotent dispatch (exactly one order),
reconcile after crash creates no duplicate order, KIS sandbox token+submit
round-trip, and a daemon E2E through the background loop. Align the four
baseline docs. BAT-004 -> release-candidate; REQ-011~015 -> Implemented.

KIS live-account go-live, partial-fill accrual, option-B outbox, connection
pooling, and the safety floor remain deferred to follow-up Discoveries.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 17:46:17 +09:00

3.3 KiB

BAT-004 Design

  • Status: confirmed
  • Batch: BAT-004

Architecture Summary

  • BAT-002 onion(domain/application/adapters/runtime) 위에 집행을 추가한다. application 에 BrokerPort(submit/cancel/poll_fill)와 execution 유스케이스, adapters/broker 에 paper/stub + KIS 어댑터, runtime 에 백그라운드 execution 루프(데몬 lifecycle 에서 기동/종료). 코어가 단일 브로커 세션(불변식 B) + 단일 슬롯 writer(불변식 A)를 모두 소유. intent API 는 pending 전이까지만, 집행은 루프가 비동기.

Changed Areas

  • Docs: runtime-flows(집행/체결/reconcile 흐름), project-structure(broker/execution 레이어), interface-contract(BrokerPort 경계), data-model(broker_order_id=실행큐/멱등) — REQ-015
  • Modules:
    • application: BrokerPort+FillStatus, execution 유스케이스(claim/dispatch/poll/transition/reconcile)
    • adapters/broker: paper(결정적 async 더블), kis(KIS Open API)
    • runtime: execution 루프(lifespan 백그라운드), config(KIS 자격증명/base URL/게이팅/폴링 주기)
  • Interfaces: BrokerPort(내부 포트) — 외부 HTTP API(/v1)는 불변(집행은 백그라운드)

Key Decisions

  1. 옵션 A 실행큐(OQ-3): pending 슬롯 + broker_order_id IS NULL 을 FOR UPDATE SKIP LOCKED 로 claim, 송신 후 broker_order_id 기록(멱등 가드). 별도 outbox 테이블 없음.
  2. 통일 비동기 체결(OQ-2): submit_order→accepted, poll_fill→filled/partial/rejected. paper 도 동기 단축 없이 같은 계약(결정적 더블), KIS 는 체결조회 폴링.
  3. 별도 execution 루프(OQ-4): 데몬 프로세스 내 백그라운드(claim→submit→poll→transition→reconcile). 단일 인스턴스=단일 writer/세션.
  4. 단일 writer(불변식 A): 집행 루프도 슬롯 전이는 SlotService(advisory lock)로만. 불변식 B: 주문/취소는 BrokerPort 단일 세션만.
  5. KIS 안전(R-3): 기본 모의투자, 실계좌는 config 게이팅. 자격증명 .env(REQ-010 패턴). 도메인 순수성(NFR-2): broker/HTTP 의존은 adapters/runtime 에만.

Edge Cases

  • 송신 후 broker_order_id 기록 전 크래시 → reconciliation 으로 브로커 상태 대조(중복 주문 방지).
  • 부분체결 → 슬라이스는 완전체결 기준 전이(부분체결 누적/분할주문 본격화는 옵션 B 승격 후속).
  • KIS 토큰 만료/레이트리밋 → 어댑터 내 갱신/백오프, 실패 시 슬롯 전이 안 함(다음 틱 재시도).
  • 거부/취소 → pending_buy→idle 롤백(점유 초기화), pending_sell→holding 복귀(매도 거부).
  • KIS 자격증명 미가용 → 통합테스트 skip, paper 경로는 완전 동작.

Architecture Impact

  • both (project-structure + runtime-flows). interface-contract(BrokerPort)·data-model(broker_order_id 의미) 도 갱신.

Reference Doc Update Plan

  • runtime-flows.md: 집행 루프(claim→submit→poll→transition)·reconcile·KIS 흐름 추가(REQ-015).
  • project-structure.md: application(BrokerPort/execution)·adapters/broker(paper,kis)·runtime(execution 루프) 레이어 반영.
  • interface-contract.md: BrokerPort 내부 포트 계약(submit/cancel/poll_fill) + KIS 어댑터 노트.
  • data-model.md: broker_order_id 를 실행큐 claim 술어 + 멱등 가드로 쓰는 의미 명시.