[BE-02] AutoTradingPolicy 애그리게이트
작업 내용 (설계 의도)
변경 사항
자동매매 정책(싱글톤 1행)을 Rich Domain Entity로 만들고 영속화한다. 실행 모드·킬 스위치·사다리 단계·운용 자본을 보유하며, 집행 가부 판단을 이 Entity가 캡슐화한다. 호출부가 policy.executionMode == PAPER 식으로 상태를 비교하지 않게 canPlaceNewOrder()·selectExecutor() 질의 메서드를 노출한다.
기능 토글을 @ConditionalOnProperty가 아니라 이 행의 값 조회로 처리하는 것이 핵심이다 — 재기동 없이 모드 전환·킬 스위치·롤백이 된다. 근거: ADR-001.
load()는 행이 없으면 기본값(PAPER·T1·킬스위치 off·자본 100만원)으로 생성해 반환한다.
롤백: 정책 행 값을 이전 값으로 되돌리면 즉시 반영된다(배포 불필요).
의존
- BE-01 (도메인 계약), DB-01 (스키마)
다이어그램
처리 흐름
sequenceDiagram participant Svc as 호출 DomainService participant Repo as AutoTradingPolicyRepository participant Entity as AutoTradingPolicy Svc->>Repo: load() Repo-->>Svc: AutoTradingPolicy Svc->>Entity: canPlaceNewOrder() Entity-->>Svc: true / false
클래스 의존
flowchart LR Entity[AutoTradingPolicy] --> Mode[ExecutionMode] Entity --> Tier[RiskTier] Repo[AutoTradingPolicyRepository] -.->|implements| Impl[AutoTradingPolicyRepositoryImpl] Impl --> Table[(auto_trading_policy)]
테스트 케이스
- 행이 없을 때
load()가 기본값(PAPER·T1·킬스위치 off)으로 생성해 반환한다. - 킬 스위치가 켜지면
canPlaceNewOrder()가 false를 반환한다. promoteTier()가 T1을 T2로 올리고 전환 시각을 기록한다.demoteTier()가 T2를 T1로 내린다.- 최하 단계 T1에서
demoteTier()를 호출해도 T1을 유지한다(경계값). - 저장 후 재조회 시 모드·단계·킬스위치가 보존된다(TestContainers MySQL).