[BE-11] AutoTradingDomainService
작업 내용 (설계 의도)
변경 사항
사이클 전체를 조율하는 도메인 서비스를 만든다. 입력은 application이 매핑해 넘긴 List<TradeCandidate>, 출력은 List<OrderProposal>이다.
흐름: 정책 로드 → 거래일 로드 → 열린 포지션 조회 → 후보별 RiskGate 판정 → 통과분 사이징 → 임계 비교로 자동/승인 분기 → 자동분 집행 → 체결·포지션·거래일 갱신 → 알림.
핵심 규칙 셋:
- 게이트를 우회하는 경로를 만들지 않는다. 집행은 반드시
RiskGate통과 후에만 일어난다. - 거부된 후보도
OrderProposal로 전량 저장한다 — 감사 로그를 겸한다. - 집행 직전
policy.canPlaceNewOrder()를 트랜잭션 안에서 재확인한다 — 킬 스위치 경합 방어.
List<TradeExecutor>를 주입받아 정책 모드에 맞는 구현을 선택한다.
의존
- BE-02, BE-03, BE-04, BE-05, BE-07, BE-09 (TradeExecutor 는 interface 의존이라 병렬 가능)
다이어그램
처리 흐름
sequenceDiagram participant Svc as AutoTradingDomainService participant Gate as RiskGate participant Exec as TradeExecutor participant Repo as OrderProposalRepository Svc->>Gate: evaluate(candidate, ...) Gate-->>Svc: 통과 Svc->>Svc: canPlaceNewOrder() 재확인 Svc->>Exec: buy(proposal, marketPrice) Exec-->>Svc: TradingFill Svc->>Repo: saveAll(제안 전량)
클래스 의존
flowchart LR Svc[AutoTradingDomainService] --> Gate[RiskGate] Svc --> Exec[TradeExecutor] Svc --> Policy[AutoTradingPolicyRepository] Svc --> Day[TradingDayRepository] Svc --> Prop[OrderProposalRepository] Svc --> Pos[TradingPositionRepository] Svc --> Alert[AutoTradingAlertGateway]
테스트 케이스
- 게이트를 통과한 후보가 임계 이하면 승인 없이 집행된다.
- 임계를 초과하면 집행하지 않고
PENDING제안만 만든다. - 게이트가 거부한 후보도
REJECTED_BY_RISK제안으로 저장된다(감사 로그). - 정책 모드가
PAPER면PaperTradeExecutor가 선택된다. - 집행 직전 킬 스위치가 켜지면 그 사이클의 집행이 중단된다(경합 방어).
- 당일 손실 한도에 도달하면 이후 후보를 전건 거부한다.
- 체결 후 거래일 실현손익과 집행 건수가 갱신된다.