[BE-03] TradingDay 애그리게이트
작업 내용 (설계 의도)
변경 사항
거래일 단위 상태를 Entity로 만든다. 당일 실현손익 누계·집행 건수·중단 여부·중단 사유를 보유하고, 일일 손실 한도 도달 판정을 Entity가 캡슐화한다.
한도는 절대 금액이 아니라 총자본 × 단계별 비율이므로, 판정 메서드가 자본과 단계를 인자로 받는다 — isDailyLossLimitReached(capital, tier). 한도 도달 시 halt(reason)으로 전이하고, 다음 거래일에는 새 행이 생성되므로 자동 해제가 별도 로직 없이 성립한다.
시간은 인자로 받지 않고 메서드 내부에서 ZonedDateTime.now()로 해결한다(no-time-parameter).
의존
- BE-01 (도메인 계약), DB-01 (스키마)
다이어그램
처리 흐름
sequenceDiagram participant Svc as AutoTradingDomainService participant Day as TradingDay Svc->>Day: recordRealizedPnl(손실액) Svc->>Day: isDailyLossLimitReached(자본, 단계) Day-->>Svc: true Svc->>Day: halt(DAILY_LOSS_LIMIT)
클래스 의존
flowchart LR Entity[TradingDay] --> Reason[TradingHaltReason] Entity --> Tier[RiskTier] Repo[TradingDayRepository] -.->|implements| Impl[TradingDayRepositoryImpl] Impl --> Table[(trading_days)]
테스트 케이스
- 당일 실현손실이 한도 미만이면
isDailyLossLimitReached()가 false를 반환한다. - T1(2%)·자본 100만원에서 누적 실현손실 2만원이면 한도 도달로 판정한다(경계값).
- T3(3%)에서 같은 2만원 손실은 한도 미달로 판정한다(단계별 차이).
- 실현이익은 누계를 줄여 한도 소진을 되돌린다.
halt()이후 중단 사유가 보존된다.- 같은
trade_date로 두 번 저장하면 UNIQUE 제약에 걸린다(TestContainers MySQL).