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.

200 lines
4.6 KiB
Markdown

# State Machine & Reconciliation
## 1. 목적
이 문서는 Phase 6 실행 엔진의 상태머신과 reconciliation 절차를 정의합니다.
실전 시스템에서 가장 위험한 문제는 **내부 상태와 브로커 상태가 어긋나는 것**이므로,
reconciliation은 보조 작업이 아니라 핵심 기능입니다.
## 2. 핵심 엔티티
### 2.1 Execution Session
하루의 운영 세션 단위.
필수 필드:
- `execution_session_id`
- `env`
- `trade_date`
- `mode` (`dry_run`, `paper`, `live`)
- `strategy_scope`
- `status`
- `started_at`
- `ended_at`
### 2.2 Order Plan
전략 후보를 실행 가능한 주문 계획으로 변환한 결과.
### 2.3 Order Intent
실제로 한 번 제출하려는 logical action.
예: entry, exit_half, exit_final, stop_exit, cancel_all.
### 2.4 Broker Order
브로커가 인식하는 주문.
하나의 Order Intent가 broker replace 과정에서 여러 broker order로 이어질 수 있다.
### 2.5 Position State
실제 체결 기반 포지션 상태.
## 3. 상위 상태머신
### 3.1 Candidate Execution State
```text
candidate_ready
-> planned
-> risk_checked
-> awaiting_approval
-> approved
-> entry_submitted
-> entry_working
-> entry_partially_filled
-> position_open
-> exit_pending
-> partially_exited
-> fully_closed
-> abandoned
-> error
```
### 3.2 Position Lifecycle
```text
no_position
-> opening
-> open
-> reducing
-> closed
-> orphaned
```
### 3.3 Session Lifecycle
```text
booting
-> pre_open_checks
-> active
-> soft_halt
-> hard_halt
-> closing
-> reconciliation
-> closed
-> failed
```
## 4. Event Sourcing 원칙
가능하면 상태를 직접 수정하기보다 event를 append하고 projection으로 현재 상태를 만든다.
필수 이벤트:
- candidate_loaded
- risk_decision_recorded
- approval_ticket_created
- approval_decided
- order_intent_created
- order_submitted
- order_acknowledged
- order_partially_filled
- order_filled
- order_cancel_requested
- order_cancelled
- order_replaced
- order_rejected
- position_opened
- position_reduced
- position_closed
- reconciliation_mismatch_detected
- reconciliation_resolved
- manual_operator_action
- session_halted
- session_resumed
## 5. Reconciliation 유형
### 5.1 주문 대사
비교 대상:
- 내부 open orders
- 브로커 open orders
- 최근 fill ledger
체크 항목:
- broker_order_id 누락
- client_order_id 중복
- 내부는 working인데 브로커엔 없음
- 브로커는 filled인데 내부는 accepted 상태
- cancel 요청 후 실제 잔존 여부
### 5.2 포지션 대사
비교 대상:
- 내부 position state
- 브로커 position snapshot
체크 항목:
- 수량 불일치
- 평균단가 불일치
- symbol 누락
- 브로커에만 존재하는 orphan position
### 5.3 세션 대사
- 장 종료 후 미처리 ticket 존재 여부
- 미완료 order intent 존재 여부
- kill switch 상태 복구 여부
## 6. Reconciliation 주기
- 장 시작 전: full sync
- 장중: 짧은 interval incremental sync
- submit/cancel/replace 직후: targeted sync
- 장 종료 후: final full sync
- 재시작 직후: mandatory full sync
## 7. 충돌 해결 규칙
원칙적으로 **브로커 체결 사실**을 가장 강한 truth로 본다.
다만 브로커 API 지연/일시 불일치가 있을 수 있으므로, 아래 우선순위를 따른다.
1. confirmed fill / position snapshot
2. fetch order by broker id
3. stream event
4. 내부 optimistic state
### 예시 1: submit timeout
- 내부 상태는 `submitted_pending_confirmation`
- 즉시 재제출하지 않는다.
- 먼저 client_order_id 기반 조회 또는 full reconciliation 수행
### 예시 2: cancel 요청 후 fill 도착
- fill 이벤트가 cancel보다 우선한다.
- 남은 수량만 취소되도록 재계산
### 예시 3: 프로세스 재시작
- 마지막 checkpoint 이후 미확정 intent를 모두 reconciliation queue에 올린다.
- broker 상태를 먼저 읽고 projection을 복구한 뒤에만 신규 주문 허용
## 8. Checkpoint / Recovery
다음은 checkpoint 대상이다.
- current session state
- active candidate executions
- open positions
- working orders
- latest broker cursor / stream cursor
- kill switch 상태
- approval pending 목록
복구 절차:
1. durable state load
2. broker full sync
3. mismatch resolution
4. projection rebuild
5. safe-to-trade 판단
6. 신규 주문 재개 여부 결정
## 9. 운영자 수동 개입
운영자가 브로커 화면에서 직접 주문/취소/청산한 경우를 고려해야 한다.
필수 규칙:
- manual action은 별도 event로 기록
- reconciliation 시 수동 개입 감지 시 operator note 요구
- 내부 상태는 브로커 상태로 수렴
- 수동 개입이 잦은 전략/구간은 별도 review 대상