Files
trex-core/docs/batches/bat-056_20260706_kis-broker-venue/design.md
T
genichinandClaude Fable 5 ee3dc83a93 feat(broker): KIS venue parameterization — OrderRequest.venue + EXCG_ID_DVSN_CD (REQ-117/118, BAT-056)
- OrderRequest.venue: str = "KRX" additive 추가 (기존 위치 인수 순서 불변)
- BrokerPort.cancel_order: venue: str = "KRX" 파라미터 추가
- BrokerPort.get_current_price: market: str = "J" 파라미터 추가
- KISBroker.submit_order: EXCG_ID_DVSN_CD=req.venue 항상 명시 전송
- KISBroker.cancel_order: EXCG_ID_DVSN_CD=venue 항상 명시 전송
- KISBroker.get_current_price: FID_COND_MRKT_DIV_CODE=market 파라미터화
- PaperBroker: cancel_order/get_current_price 시그니처 정합 (venue/market 수신·무시)
- poll_fill TR 유지 (TTTC8001R) — NXT 체결 포함 여부 미확인 open item (코드 주석 기록)
- tests/adapters/broker/test_venue.py: REQ-117 AC-1~5 + REQ-118 AC-1~8 신규 17개
- docs: interface-contract.md OrderRequest/BrokerPort 섹션 + change log 추가
- docs: runtime-flows.md venue 전달 경로 명시 + change log 추가

결과: 794 passed, 47 skipped (기존 777+47 대비 신규 17개 추가 전부 통과)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
2026-07-06 23:24:51 +09:00

3.8 KiB

BAT-056 Design

1. OrderRequest.venue 필드 (REQ-117)

결정

OrderRequest frozen dataclass의 마지막 위치에 venue: str = "KRX" 추가.

@dataclass(frozen=True)
class OrderRequest:
    slot_id: str
    side: str
    symbol: str
    qty: int
    limit_price: Optional[int] = None
    order_type: str = "00"
    venue: str = "KRX"          # additive (REQ-117): KRX | NXT | SOR
  • 기존 위치 인수(slot_id, side, symbol, qty, limit_price, order_type) 순서 불변.
  • venue 기본값 "KRX"로 기존 orb/tsl 미지정 호출 자동 KRX 적용.
  • "SOR" 정의하되 현재 운영 비권고 (OQ-1 잔여, REQ-117 Notes 참조).

2. cancel_order 시그니처 venue 파라미터 (REQ-118)

결정: 시그니처 venue 파라미터 추가 방식

대안 검토:

  • A안(채택): cancel_order(broker_order_id, *, side, symbol, qty, venue="KRX") — 호출자가 원주문 venue를 명시 전달. 명시적이고 기본값으로 하위 호환.
  • B안: execution context에서 venue 보존 — 더 복잡, 현재 OrderAck에 venue 저장 필요.

A안 채택 이유: 단순성, 기본값 하위 호환, BrokerPort 프로토콜에서 명시적 의미론 확립.

BrokerPort 프로토콜:

def cancel_order(self, broker_order_id: str, *, side: str, symbol: str, qty: int, venue: str = "KRX") -> bool:

KISBroker.cancel_order body에 "EXCG_ID_DVSN_CD": venue 추가. PaperBroker.cancel_order: 시그니처만 정합, venue 무시.

3. poll_fill TR 선택 — open item (REQ-118 AC-4)

현황

  • 구 TR TTTC8001R (mock: VTTC8001R): 현재 사용 중. NXT 체결 포함 여부 미확인.
  • 신 TR TTTC0081R: EXCG=ALL 또는 venue 지정으로 NXT 체결 조회 가능(KIS 개발자 센터 문서 기준).

확인 시도 결과

웹 접근 불가 환경 — KIS 개발자 센터 문서 직접 조회 불가. 코드/기존 문서 내 관련 근거 없음.

결정: 보수 구현 (기존 TR 유지)

  • 기존 TR(TTTC8001R/VTTC8001R) 유지 — KRX 경로 동작 절대 불변.
  • 코드 주석에 open item 명시.
  • verification에 open item 기록: "NXT 체결 조회는 실측 확인 필요(운영 스모크)".

향후 전환 조건 및 방법 (미구현, 운영 협의 후)

  • 조건: NXT 체결 주문 발생 후 TTTC8001R 응답에 NXT 체결 미포함 확인(실측).
  • 방법: poll_fill 파라미터 venue 추가 + venue="NXT"이면 TTTC0081R 사용.
    • mock(VTS) 대응 주의: VTS TTTC0081R 지원 여부 미확인 → mock일 때 구 TR fallback 고려.
  • 이 전환은 별도 batch로 처리한다(REQ-118 AC-4 follow-up).

4. get_current_price market 파라미터 (REQ-118 AC-5,6)

def get_current_price(self, symbol: str, market: str = "J") -> Optional[Decimal]:
  • FID_COND_MRKT_DIV_CODE → market 값 사용.
  • 기본값 "J" → 기존 safety-sell 경로 무영향.
  • "UN" 지정 시 나스닥/해외 시세 조회 가능(NXT 연장세션 활용 예정).

BrokerPort 프로토콜:

def get_current_price(self, symbol: str, market: str = "J") -> Optional[Decimal]:

5. 실측 근거 (design 인용)

  • 2026-07-06: 실전 계좌 NXT 주문(TTTC0012U + EXCG=NXT) rt_cd=0, 취소(TTTC0013U + EXCG=NXT) rt_cd=0·잔여 0건 확인.
  • 토큰 재요청 1분 rate-limit 확인. 기존 kis.py 토큰 캐시 방식 유지 — 신 TR 전환 시에도 캐시 재사용 경로 유지 필요.

6. additive 검증 전략

  • venue 미지정 submit_order: 기존 대비 EXCG_ID_DVSN_CD="KRX" 필드 추가만 다름 → fixture로 body 캡처 검사(AC-7).
  • 기존 cancel_order 호출자: keyword-only 파라미터이므로 venue 없이 호출 시 기본값 KRX 자동 적용 → 기존 테스트 회귀 없음.
  • 기존 get_current_price 호출자: 파라미터 미지정 → market="J" 자동 적용 → 기존 safety-sell 경로 무영향.