feat(rel-006): dcy-022/023 + BAT-032~034 — 실행 정책·qty 검증·allocated_capital 제거 통합
BAT-032 (dcy-022): timeout_sec/slippage_pct 실행 정책, 미체결 자동 취소, 보호 지정가, `trex-core cancel` 백스톱. 마이그레이션 012. BAT-033: `trex-core enter --qty` 필수 검증 — 미지정 시 RPC 전 즉시 오류. BAT-034 (dcy-023): allocated_capital 죽은 필드 전 경로 제거 (domain·intent· persistence·snapshot·CLI). 마이그레이션 013(비가역 DROP). 외부 발신자 unknown key 무시 수신 의미론 적용. REL-006 confirmed: BAT-026~034 통합 릴리즈, pre-release smoke 증거 포함. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
# BAT-032 Implementation
|
||||
|
||||
- Status: done
|
||||
- Batch: BAT-032
|
||||
|
||||
## M1 — 실행 정책 계약·파싱·슬롯 저장 (REQ-068, REQ-061 CHG-05)
|
||||
|
||||
**변경 파일**
|
||||
|
||||
| 파일 | 내용 |
|
||||
|---|---|
|
||||
| `trex_core/domain/slot/models.py` | `Slot` dataclass 에 `timeout_sec: Optional[int]`, `slippage_pct: Optional[float]` 추가. `EXPECTED_SLOT_FIELDS` 갱신. |
|
||||
| `trex_core/adapters/persistence/sql/012_add_execution_policy_fields.sql` | `ALTER TABLE daily_slot ADD COLUMN IF NOT EXISTS timeout_sec INTEGER; … slippage_pct FLOAT;` |
|
||||
| `trex_core/domain/slot/service.py` | `transit_slot`·`_apply_transition_fields` kwargs 확장. PENDING_* 진입 시 set, HOLDING/INACTIVE/ERROR 진입 시 clear (limit_price 동일 생애주기). |
|
||||
| `trex_core/adapters/persistence/postgresql.py` | `_SLOT_COLUMNS`에 col 19·20 추가. `update_slot` SQL 갱신. `_row_to_slot` 인덱스 추가. |
|
||||
| `trex_core/application/intents.py` | `BuyIntent`·`SellIntent` 에 `timeout_sec`·`slippage_pct` 추가. `IntentService.__init__` 에 `default_order_timeout_sec`. `_admit_buy`·`_admit_sell` 에서 effective_timeout 해석. |
|
||||
| `trex_core/application/messaging_handlers.py` | buy/sell 핸들러에서 `_opt_int`·`_opt_float` 파싱 추가. |
|
||||
| `trex_core/runtime/config.py` | `DaemonInstanceConfig.default_order_timeout_sec`. |
|
||||
| `trex_core/runtime/daemon.py` | `IntentService` wiring 에 `default_order_timeout_sec` 전달. |
|
||||
|
||||
## M2 — slippage 보호 지정가 dispatch (REQ-070, REQ-013 CHG-03 partial)
|
||||
|
||||
**변경 파일**
|
||||
|
||||
| 파일 | 내용 |
|
||||
|---|---|
|
||||
| `trex_core/application/execution.py` | `_dispatch`: limit 계산 후 slippage 블록 추가. buy: `ceil(limit*(1+pct/100))`, sell: `floor(limit*(1-pct/100))`. `import math` 추가. |
|
||||
|
||||
## M3 — timeout 집행 + race 처리 (REQ-069, REQ-013 CHG-03 partial)
|
||||
|
||||
**변경 파일**
|
||||
|
||||
| 파일 | 내용 |
|
||||
|---|---|
|
||||
| `trex_core/application/execution.py` | `ExecutionResult.timeout_cancelled` 추가. `_poll` else branch에 `_try_timeout_cancel` 추가. `_try_timeout_cancel` 구현: `slot.updated_at` proxy로 경과 체크 → `cancel_order` best-effort → `r.timeout_cancelled += 1`. |
|
||||
|
||||
## M4 — 운영자 cancel 백스톱 (REQ-071)
|
||||
|
||||
**변경 파일**
|
||||
|
||||
| 파일 | 내용 |
|
||||
|---|---|
|
||||
| `trex_core/application/execution.py` | `cancel_pending_slot(slot_id)` 메서드: PENDING_* slot → `cancel_order` 송신 → "ok"/"not_pending"/"slot_not_found"/"not_dispatched"/"cancel_failed" 반환. 슬롯 전이 없음 (단일 writer 보존). |
|
||||
| `trex_core/application/messaging_handlers.py` | `make_control_rpc_handler` 에 `cancel_pending_fn` 파라미터. `cancel_pending` 액션 라우팅. `_handle_cancel_pending` 구현. |
|
||||
| `trex_core/runtime/cli.py` | `cancel <slot_id>` 서브커맨드. `_cmd_cancel`. `_add_intent_guards` (--yes/--dry-run/--live). control RPC 경유. |
|
||||
| `trex_core/runtime/daemon.py` | `make_control_rpc_handler(cancel_pending_fn=self.execution.cancel_pending_slot)` 배선. |
|
||||
|
||||
## M5 — baseline 문서 정합 (REQ-072)
|
||||
|
||||
**변경 파일**
|
||||
|
||||
| 파일 | 내용 |
|
||||
|---|---|
|
||||
| `docs/interface-contract.md` | buy/sell payload에 `timeout_sec`·`slippage_pct` 필드 기술. 하위 호환 주석 추가. cancel CLI 참조. |
|
||||
| `docs/runtime-flows.md` | dispatch 스텝: slippage 지정가 주석. poll 스텝: timeout 자동 취소 흐름. 실행 정책 생애주기. "운영자 cancel 백스톱" 섹션 추가. |
|
||||
|
||||
## 설계 결정 근거 (design.md 요약)
|
||||
|
||||
- **D1**: `timeout_sec`/`slippage_pct` 를 slot 컬럼으로 저장 — `limit_price` 와 동일 생애주기(PENDING 진입 시 set, 탈출 시 clear).
|
||||
- **D2**: `slot.updated_at` 을 dispatch 시각 proxy로 사용 — 기존 stale watchdog(REQ-014)과 동일 방법, 별도 컬럼 불필요.
|
||||
- **D3**: `cancel_order` 송신만, 즉시 롤백 없음 — cancel-fill race 안전. 다음 poll의 `is_terminal_reject`/`is_partial_cancel` 경로 재사용.
|
||||
- **D4**: cancel CLI → control RPC → `ExecutionService.cancel_pending_slot` — 단일 writer 불변식(A) 보존.
|
||||
Reference in New Issue
Block a user