You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5.7 KiB

Broker Integration & Order Lifecycle

1. 목적

이 문서는 브로커 연동 레이어와 주문 생명주기 규칙을 정의합니다. Phase 6에서는 최소 1개 브로커 reference 구현이 필요하며, 기본 reference는 Alpaca paper 입니다. 그러나 상위 코드가 특정 브로커 SDK에 직접 결합되면 안 되므로, 내부적으로는 broker abstraction layer를 사용합니다.

2. Broker Adapter 인터페이스

모든 adapter는 아래 메서드를 제공해야 합니다.

class BrokerAdapter(Protocol):
    def get_health(self) -> BrokerHealth: ...
    def get_account(self) -> BrokerAccountSnapshot: ...
    def get_positions(self) -> list[BrokerPositionSnapshot]: ...
    def get_open_orders(self) -> list[BrokerOrderSnapshot]: ...
    def submit_order(self, order: PlannedOrder) -> SubmitResult: ...
    def cancel_order(self, broker_order_id: str) -> CancelResult: ...
    def replace_order(self, broker_order_id: str, patch: ReplacePatch) -> ReplaceResult: ...
    def fetch_order(self, broker_order_id: str) -> BrokerOrderSnapshot: ...
    def fetch_fills(self, since: datetime) -> list[BrokerFill]: ...
    def stream_events(self, on_event: Callable[[RawBrokerEvent], None]) -> None: ...

금지사항

  • adapter 바깥에서 브로커 SDK raw object를 직접 참조하지 않는다.
  • business logic이 브로커별 order status string에 의존하지 않는다.
  • adapter 내부에서 전략 점수나 리스크 결정을 하지 않는다.

3. Canonical Order Types

Phase 6 v1에서 허용하는 주문 타입은 아래로 제한한다.

  • market
  • limit
  • stop
  • stop_limit
  • market_on_open (브로커 지원 시)
  • market_on_close (브로커 지원 시)

v1에서는 다음을 금지한다.

  • 복합 브래킷 주문에 전략 로직을 위임하는 방식
  • 옵션/멀티레그 주문
  • 알고리즘 주문(TWAP/VWAP 등)
  • after-hours 진입 전략 주문

4. Client Order ID 규칙

내부 시스템은 반드시 deterministic client_order_id를 생성해야 한다. 형식 예시:

{env}-{strategy_id}-{trade_date}-{symbol}-{leg}-{attempt}

예시:

paper-corelong-2026-03-12-NVDA-entry-01
paper-corelong-2026-03-12-NVDA-exit-half-01

규칙:

  • 같은 logical order를 재전송할 때는 같은 id를 재사용할지, 새 시퀀스를 부여할지 명확히 해야 한다.
  • submit timeout 후 실제로 브로커가 주문을 받았는지 불명확할 경우, 무조건 새 주문을 보내지 말고 먼저 fetch by client id 또는 reconciliation을 수행한다.

5. PlannedOrder 구조

PlannedOrder는 최소 아래 필드를 가져야 한다.

  • order_plan_id
  • candidate_id
  • symbol
  • side
  • qty
  • notional (optional)
  • order_type
  • time_in_force
  • limit_price (optional)
  • stop_price (optional)
  • submission_window_start
  • submission_window_end
  • expiry_policy
  • broker_route_hint (optional)
  • reason_code
  • risk_snapshot_id

6. Order Lifecycle

6.1 내부 상태

planned
-> approved
-> submitted
-> accepted
-> partially_filled
-> filled
-> cancel_requested
-> cancelled
-> replace_requested
-> replaced
-> rejected
-> expired
-> busted

6.2 전이 규칙

  • planned -> approved : approval mode에서 승인 완료 또는 auto mode에서 risk guard 통과
  • approved -> submitted : broker adapter submit 성공
  • submitted -> accepted : broker가 ack 반환
  • accepted -> partially_filled : 부분체결 event 수신
  • partially_filled -> filled : 남은 수량이 0
  • accepted -> cancel_requested : TTL 만료 / 운영자 cancel / risk halt
  • accepted -> rejected : broker reject
  • accepted -> expired : broker day order expired
  • partially_filled -> cancel_requested : 잔량 취소 요청
  • replace_requested -> replaced : 새 broker order 또는 수정 반영 확인

7. Entry / Exit 주문 정책

7.1 Entry

v1 entry는 아래 정책만 허용한다.

  • 다음 시초가 근처 market/limit 진입
  • 장중 제한된 window 안의 limit 진입
  • stop-limit 진입은 paper에서 충분히 검증된 전략에만 허용

7.2 Stop Exit

  • 하드 stop을 브로커에 즉시 상주시키는지, 내부 synthetic stop으로 운용하는지 전략별로 고정한다.
  • v1에서는 gap risk를 고려해 synthetic stop + session-based exit를 기본으로 한다.
  • 단, 연결 장애가 잦은 환경에서는 broker-native stop을 허용할 수 있다.

7.3 Time Exit

  • planned_time_exit 시각 또는 session close 기준으로 자동 청산 계획을 생성한다.
  • time exit는 별도의 logical order leg로 기록한다.

8. Partial Fill 처리

partial fill은 예외가 아니라 정상 흐름이다.

정책:

  • 평균 체결가를 지속 업데이트한다.
  • 남은 수량이 min_fill_threshold 미만이면 즉시 취소/시장가 전환 여부를 전략별로 결정한다.
  • exit 주문은 filled qty를 기준으로만 생성한다.
  • stop/target leg는 filled qty와 정합해야 한다.

9. Cancel / Replace 정책

v1 원칙:

  • replace는 실제로 필요한 경우에만 사용한다.
  • submit 직후 수 초 내 교체를 반복하는 logic은 금지한다.
  • 취소와 교체가 동시에 걸릴 수 있으므로, reconciliation 전 finality를 가정하지 않는다.

10. 브로커 event canonicalization

브로커 raw event는 아래 canonical event로 변환한다.

  • order_submitted
  • order_accepted
  • order_rejected
  • order_partially_filled
  • order_filled
  • order_cancel_requested
  • order_cancelled
  • order_replaced
  • order_expired
  • trade_bust
  • heartbeat_lost
  • heartbeat_restored

모든 event는 event_id, event_time, source, broker_order_id, client_order_id, payload_hash를 포함해야 한다.