feat(execution): reconcile timed-out orders safely
This commit is contained in:
+5
-2
@@ -50,8 +50,11 @@
|
||||
- allocated_capital :: numeric? :: 배정 자본
|
||||
- order_id / broker_order_id :: str? :: 주문 식별자(자유 주석 / 브로커 핸들)
|
||||
- venue :: TEXT NOT NULL DEFAULT 'KRX' :: 현재 주문 거래소 구분(AUTO/KRX/NXT/SOR). intent 단계의 AUTO는 KIS 제출 시 실제 KRX/NXT로 교체되며 주문번호와 원자 저장한다. pending 주문·취소까지 보존하고 HOLDING 진입 시 다음 자율주문의 AUTO, INACTIVE 진입 시 KRX로 초기화한다.
|
||||
- cancel_state :: TEXT? :: 취소 요청의 즉시 결과(requested/rejected/unknown). 최종 취소 상태가 아니며 같은 주문의 자동 재취소를 막는다.
|
||||
- cancel_requested_at :: TIMESTAMPTZ? :: 취소 요청 결과를 저장한 시각. 주문 종료·dispatch clear 때 함께 제거한다.
|
||||
- cancel_state :: TEXT? :: 취소 요청의 즉시 결과(requested/rejected/unknown). 최종 취소 상태가 아니다. requested는 재시도하지 않고, rejected/unknown만 authoritative open-row 확인과 bounded backoff 뒤 재시도할 수 있다.
|
||||
- cancel_requested_at :: TIMESTAMPTZ? :: 마지막 취소 시도 예약 시각. 주문 종료·dispatch clear 때 함께 제거한다.
|
||||
- order_submitted_at :: TIMESTAMPTZ? :: timeout deadline의 immutable 주문 제출 기준점. poll/cancel bookkeeping 및 daemon 재시작에서 보존하고 terminal dispatch clear 때 제거한다.
|
||||
- order_date :: TEXT? :: 원주문 KST 날짜(`YYYYMMDD`). 날짜 rollover 뒤 KIS 일별주문체결조회가 현재 날짜가 아닌 원주문 날짜를 사용하도록 보존한다.
|
||||
- cancel_attempts :: INTEGER NOT NULL DEFAULT 0 :: 원자적으로 예약된 취소 시도 횟수. 새 dispatch에서 0, terminal dispatch clear에서 0으로 초기화한다.
|
||||
- strategy_id / sell_strategy_id :: str? :: 진입/청산 전략 식별
|
||||
- portfolio_id :: str? :: 포트폴리오 식별
|
||||
- forced_close_at :: datetime? :: 강제 청산 마감선
|
||||
|
||||
@@ -447,8 +447,8 @@ cancel_order(broker_order_id: str, *, side: str, symbol: str, qty: int, venue: s
|
||||
|
||||
- `venue`: 원주문 venue. 취소 시 원주문과 동일한 `EXCG_ID_DVSN_CD`를 사용해야 한다. 기본값 `"KRX"`로 기존 호출자 하위 호환.
|
||||
- `CancelOutcome.state`: `requested`(요청 접수), `rejected`(명시적 거부), `unknown`(응답유실·전송 실패). `requested`도 최종 취소가 아니며 `poll_fill()`의 `cancelled|filled`만 주문의 최종 상태를 확정한다.
|
||||
- Core는 외부 취소 호출 전에 `unknown`을 먼저 영속화하고 응답 뒤 실제 즉시 결과로 교체한다. 따라서 요청과 저장 사이에 프로세스가 종료돼도 자동 timeout 취소는 같은 주문을 재전송하지 않고, 재시작 뒤 체결조회로만 수렴한다.
|
||||
- timeout과 운영자 취소 모두 `cancel_state IS NULL` 비교·설정에 성공한 한 호출만 외부 요청을 보낸다. 이후 반복 요청은 `cancel_already_recorded`로 응답하고 poll만 계속한다.
|
||||
- Core는 외부 취소 호출 전에 `unknown`과 시도 횟수를 원자적으로 영속화하고 응답 뒤 실제 즉시 결과로 교체한다. 따라서 요청과 저장 사이에 프로세스가 종료돼도 재시작 시 먼저 체결조회를 수행한다.
|
||||
- `requested`는 재시도하지 않는다. `rejected|unknown`은 후속 `poll_fill()`이 원주문을 open으로 확인하고 bounded backoff·최대 시도 조건을 만족한 경우에만 재시도한다. row 미가시성·missing·accepted만으로 blind retry하지 않는다. 운영자 반복 요청은 기존 `cancel_already_recorded` 경계를 유지한다.
|
||||
|
||||
### get_current_price
|
||||
|
||||
@@ -466,6 +466,10 @@ get_current_price(symbol: str, market: str = "J") -> Optional[Decimal]
|
||||
- `poll_fill`: KIS 신형 일별주문체결조회 실전 `TTTC0081R`, 모의
|
||||
`VTTC0081R`을 사용하고 `EXCG_ID_DVSN_CD=ALL`을 전달한다. 일반 주문번호
|
||||
조회와 결과불명 주문 탐색이 같은 계약으로 KRX·NXT 체결을 확인한다.
|
||||
일반 주문은 영속화된 `order_date`(`YYYYMMDD`)를 조회일로 사용하며,
|
||||
row가 없으면 bounded 제출 직후 visibility grace 이후 `unknown`으로
|
||||
fail-closed 한다. `order_submitted_at`/`order_date`를 알 수 없는 legacy
|
||||
pending row는 mutable `updated_at`로 추정하지 않고 CRITICAL alarm과 pending을 유지한다.
|
||||
|
||||
## `FillStatus` 확장 (BAT-006 / REQ-018)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user