[BE-07] RiskGate

작업 내용 (설계 의도)

변경 사항

모든 주문이 반드시 통과하는 단일 관문을 만든다. 게이트를 우회하는 집행 경로를 만들지 않는 것이 이 티켓의 존재 이유다 — QuantConnect가 리스크 관리를 전략과 분리된 계층으로 두는 것과 같은 구조(TDD “Architecture Benchmarking”).

외부 의존이 없는 순수 컴포넌트로 만든다. 입력은 (candidate, policy, tradingDay, openPositions), 출력은 RiskDecision(통과 또는 거부 사유).

판정 항목:

항목거부 조건
킬 스위치켜져 있으면 전건 거부
일일 손실 한도당일 중단 상태면 전건 거부
종목당 투입 상한산출 금액이 총자본 × 단계 비율 초과
총 노출 상한신규 포함 노출이 상한 초과
동시 보유 종목 수단계별 상한 초과
1주 미달PositionSizer가 0주를 반환
중복 진입같은 종목에 이미 열린 포지션 존재

거부 사유는 OrderProposal에 기록돼 감사 로그가 된다.

의존

  • BE-01 (도메인 계약)

다이어그램

처리 흐름

sequenceDiagram
    participant Svc as AutoTradingDomainService
    participant Gate as RiskGate
    Svc->>Gate: evaluate(candidate, policy, day, positions)
    Gate-->>Svc: RiskDecision(거부, 사유=보유수 초과)

클래스 의존

flowchart LR
    Gate[RiskGate] --> Policy[AutoTradingPolicy]
    Gate --> Day[TradingDay]
    Gate --> Pos[TradingPosition]
    Gate --> Sizer[PositionSizer]
    Gate --> Decision[RiskDecision]

테스트 케이스

  • 모든 조건을 만족하면 통과 판정을 낸다.
  • 킬 스위치가 켜져 있으면 다른 조건과 무관하게 거부한다.
  • 당일 손실 한도 도달 상태면 거부한다.
  • 보유 종목 수가 단계 상한과 같으면 신규 진입을 거부한다(경계값).
  • 1주 가격이 종목당 상한을 넘으면 거부하고 사유가 1주 미달로 기록된다.
  • 이미 열린 포지션이 있는 종목은 중복 진입으로 거부한다.
  • 거부 시 반환된 RiskDecision에 사유가 담긴다.