[BE-21] 마감 OCO 유효성 점검
이 티켓은 BE-29 로 흡수됐다 — 조회 API 연결이 전제이므로 착수하지 않는다 (
Tickets/BE-29-조건부주문-조회-취소연결.md).
작업 내용 (설계 의도)
변경 사항
PRD “마감 점검”의 두 번째 항목 — 보유 포지션 전량에 유효한 OCO 주문이 걸려 있는지 확인 — 이 어느 티켓에도 없다(wave 3 리뷰에서 발견). 현재 마감 점검은 체결 대조(BE-12)만 한다.
이 점검이 필요한 이유는 OCO가 조용히 사라질 수 있기 때문이다:
- 토스가 등록 시 만료일을 받는다. 만료되면 포지션은 남고 손절만 사라진다(BE-08 리뷰 p3-5).
TradingPosition.attachOcoOrder()가 기존ocoOrderId를 조건 없이 덮어쓰고, 포지션 종료 후에도 값이 남는다 — 브로커에 살아 있는 조건부 주문이 고아가 될 수 있다(BE-05 리뷰 p4).- OCO 등록 직후 성공했더라도 사용자가 토스 앱에서 직접 취소할 수 있다.
ADR-004는 “손절 없는 포지션을 보유하지 않는다”를 규칙으로 두는데, 등록 시점에만 보장하고 이후를 확인하지 않으면 그 규칙이 시간이 지나며 깨진다. “방어되고 있다는 착각”이 정확히 이 형태로 생긴다.
열린 포지션마다 oco_order_id로 토스 조건부 주문을 조회해 상태를 확인하고, 없거나 취소·만료 상태면 알림을 낸다. LIVE 모드에서만 수행한다(PAPER는 브로커 위임이 없다).
자동 재등록은 이 티켓 범위가 아니다 — 마감 후 장이 닫힌 상태라 재등록해도 다음 개장까지 발동하지 않고, 무엇보다 “왜 사라졌는지” 모르는 채 다시 거는 것이 위험하다. 먼저 관측하고 빈도를 본 뒤 판단한다.
롤백: 점검 스케줄 비활성화. 읽기 전용이라 되돌리기가 안전하다.
의존
- BE-05 (포지션), BE-08 (조건부주문 어댑터), BE-12 (마감 정산)
다이어그램
처리 흐름
sequenceDiagram participant Sch as 마감 스케줄러 participant UC as VerifyPositionProtectionUseCase participant Repo as TradingPositionRepository participant Gw as ConditionalOrderGateway participant Alert as AutoTradingAlertGateway Sch->>UC: execute(tradeDate) UC->>Repo: findAllOpen(LIVE) Repo-->>UC: 열린 포지션 목록 UC->>Gw: 조건부 주문 상태 조회 Gw-->>UC: 취소됨 UC->>Alert: 보호 없는 포지션 경고
클래스 의존
flowchart LR UC[VerifyPositionProtectionUseCase] --> Svc[PositionProtectionDomainService] Svc --> PosRepo[TradingPositionRepository] Svc --> Oco[ConditionalOrderGateway] Svc --> Alert[AutoTradingAlertGateway]
테스트 케이스
- 열린 포지션 전부에 유효한 OCO가 있으면 알림이 나가지 않는다.
oco_order_id가 NULL인 열린 LIVE 포지션이 있으면 경고 알림이 나간다.- 조건부 주문이 취소·만료 상태면 경고 알림이 나간다.
- PAPER 포지션은 점검 대상이 아니다(브로커 위임 없음).
- 종료된 포지션은 점검 대상이 아니다.
- 조건부 주문 조회가 실패해도 다른 포지션 점검이 계속된다(부분 실패 격리).