- draft-req: REQ-066(사이징 도메인·end-to-end), REQ-067(baseline 정합) 신규 - change-req: REQ-057(CHG-03 holding→pending_buy)·REQ-061(CHG-04 사이징 intent)· REQ-062(CHG-03 부분 매도 min(주문,잔고)) — Implemented→Approved 후 재구현 - confirm-req: REQ-066/067 Approved - BAT-031 batch(index/planning/design D1~D4/implementation/verification) → release-candidate - confirm-batch-verification 승인 + confirm-req-implemented: REQ-057/061/062/066/067 → Implemented (BAT-031 verification 근거) - srs/batch index + dcy-021 discovery 생성 REQ 역참조 갱신 (issue #21 dcy-022 는 별도 작업으로 미포함) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3.2 KiB
3.2 KiB
BAT-031 Implementation
- Status: done
- Batch: BAT-031
- 일자: 2026-06-10
구현 요약
design.md D1~D4 그대로 구현. 수량 정본=브로커 잔고 재동기화로 "주문 수량 vs 보유 수량" 충돌을 별도 필드 없이 해소.
- M1 (REQ-057):
state.py_BASE_TRANSITIONS에(HOLDING, PENDING_BUY)추가 → 13 전이(증액). - M2 (REQ-066/062):
service.py_apply_transition_fields— PENDING_SELL 진입 시qty = caller as-is(None=전량 sentinel, 값=부분 주문 qty). 증액 pending(HOLDING→PENDING_BUY)은 generic 분기가 avg_price 보존(caller None)·qty=주문으로 처리(별도 분기 불요). - M3 (REQ-061):
intents.py—_admit_buy가 HOLDING 슬롯 매수를 증액으로 검출(M 캡 미적용,position_increasereason), PENDING_* 만already_active.SellIntent.qty(부분) 추가,_admit_sell가 qty 를 transit 에 전달.messaging_handlerssell 파서에qty추출. - M4 (REQ-062/066):
execution.py—_balance_map()헬퍼. dispatch 매도qty = 브로커잔고 if slot.qty is None else min(int(slot.qty), 브로커잔고)(0이면 skip+WARN)._on_filled: 매수 체결 → 보유=브로커 잔고·avg 가중평균; 매도 체결 → 브로커 잔고>0pending_sell→holding(cost basis) / 0→inactive._on_partial_cancel도 브로커 정본 resync._rollback: 매수 거부 시 브로커>0→holding(증액 실패, 기존 보유 유지) / 0→inactive. - M5 (REQ-067): data-model/runtime-flows/interface-contract/project-structure 4문서 사이징 정합.
변경 내역 (Changed Files)
- trex_core/domain/slot/state.py — holding→pending_buy 전이
- trex_core/domain/slot/service.py — PENDING_SELL qty sentinel
- trex_core/application/intents.py — 증액 admission, SellIntent.qty, partial sell
- trex_core/application/execution.py — _balance_map, 부분/전량 매도 dispatch, 매수 체결 가중평균, 브로커 정본 resync, 증액 롤백
- trex_core/application/messaging_handlers.py — sell qty 파싱
- docs: data-model/runtime-flows/interface-contract/project-structure (REQ-067)
- tests: test_state(13 전이), test_service(TestPositionSizing 3), test_execution(전량/부분 매도·증액·capacity 5신규), test_execution_cancel(브로커 정본 잔량)
테스트
- 단위 전체: 378 passed (45 skipped), ruff clean
- 통합(PG+RabbitMQ): 422 passed, 1 skipped(KIS sandbox, 환경 무관)
검증 실행 (run-the-app, 사이징 e2e)
라이브 trex_core(reset 후) + 실 RabbitMQ + paper + instance=test, M=5:
- 초기 매수 qty=10 @1000 → holding 10 @1000
- 증액 +5 @1200(holding 슬롯 매수, admitted) → holding 15 @1066.6667(가중평균)
- 부분 매도 qty=6 → holding 9 @1066.6667(cost basis 유지)
- 전량 매도(qty 미지정) → inactive(qty None)
- 데몬 로그 ERROR/Traceback 0. messaging sell qty 갭은 e2e 에서 발견·수정(부분 매도가 전량으로 가던 버그) 후 재검증 green.
Remaining Risks / Blockers
- 전략 모듈(trex-orb) 사이징 intent 발행 전환 필요 — 기존 buy/sell 와 병존(additive)이라 무중단.
- 미체결 pending 고착 처분은 본 배치 범위 밖(issue #21 별도 Discovery).