Files
trex-core/docs/batches/bat-031_20260610_position-sizing/implementation.md
T
genichinandClaude Opus 4.8 5ee5f7f4e2 docs(srs/batch): dcy-021 REQ + BAT-031 + Implemented 전환
- 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>
2026-06-10 18:53:53 +09:00

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_increase reason), PENDING_* 만 already_active. SellIntent.qty(부분) 추가, _admit_sell 가 qty 를 transit 에 전달. messaging_handlers sell 파서에 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 가중평균; 매도 체결 → 브로커 잔고>0 pending_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:

  1. 초기 매수 qty=10 @1000 → holding 10 @1000
  2. 증액 +5 @1200(holding 슬롯 매수, admitted) → holding 15 @1066.6667(가중평균)
  3. 부분 매도 qty=6 → holding 9 @1066.6667(cost basis 유지)
  4. 전량 매도(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).