P4 실행 자동화

의존: P3 (리스크 게이트). 구현 위치: BE. 주문 경로: 기존 토스 order 도메인 재사용 (ADR-003). 범위: 신호 + 수동 승인 (ADR-005). 실행: 페이퍼트레이딩 선행, 승인 집행은 paper/live 모드 분기 (ADR-006). 기본 paper.

재사용 (신규 작성 금지)

  • TossOrderGatewayImpl, OrderDomainService#placeOrder, OrderStatus 전이, PlaceOrderUseCase, OrderApiController — 이미 토스 매수·매도·정정·취소 동작 중. 그대로 호출만 한다.

[WEALTH-P4-01] OrderProposal 도메인 + 스키마

작업 내용 (설계 의도)

신호+리스크 게이트를 통과한 주문을 “제안”으로 보관하는 OrderProposal을 Rich Domain Entity로 만든다. 상태 PROPOSED → APPROVED/REJECTED 전이를 Enum canTransitTo()로 캡슐화한다. order_proposals 테이블을 신규 추가한다(orders는 기존 재사용, 변경 없음).

롤백: 마이그레이션 실패 시 역방향 DDL로 order_proposals 제거. 기존 주문 경로 영향 없음.

다이어그램

클래스 의존

flowchart LR
    Proposal[OrderProposal] --> Repo[OrderProposalRepository]
    Repo -.->|implements| Impl[OrderProposalRepositoryImpl]
    Impl --> Table[(order_proposals)]

테스트 케이스

  • PROPOSED→APPROVED, PROPOSED→REJECTED 전이는 허용된다.
  • APPROVED/REJECTED는 종료 상태로 어떤 전이도 거부된다(상태 보호).
  • 수량 0·음수 제안은 생성 시 거부된다(엣지 케이스).
  • TestContainers MySQL에 저장 후 상태별 조회된다.

[WEALTH-P4-02] ProposeOrderUseCase — 신호→제안 생성

작업 내용 (설계 의도)

신호(추천/시그널) + PositionSizer 결과를 받아 RiskGate(P3)를 통과한 건만 OrderProposal로 생성한다. 게이트 미통과 건은 제안하지 않는다. 제안 출처 신호를 함께 기록한다.

다이어그램

처리 흐름

sequenceDiagram
    participant UC as ProposeOrderUseCase
    participant Sizer as PositionSizer
    participant Gate as RiskGate
    participant Repo as OrderProposalRepository
    UC->>Sizer: size(signal, capital)
    UC->>Gate: validate(sizedOrder)
    Gate-->>UC: 통과
    UC->>Repo: save(proposal)

테스트 케이스

  • 리스크 게이트 통과 신호는 제안으로 생성된다(해피 패스).
  • 게이트 미통과 신호는 제안이 생성되지 않는다(상태 보호).
  • 동일 신호 중복 입력 시 멱등하게 1건만 제안된다(엣지 케이스).

[WEALTH-P4-03] 페이퍼 집행 — paper_fills + PaperExecutor

작업 내용 (설계 의도)

paper 모드 집행 경로를 만든다. 토스 호출 없이 제안가로 모의 체결을 paper_fills에 기록하고 가상 포지션·손익을 추적한다. 페이퍼 손익이 P2 백테스트 엣지와 같은 방향인지 관측할 수 있게 한다.

롤백: 마이그레이션 실패 시 역방향 DDL로 paper_fills 제거. 실거래 영향 없음.

다이어그램

클래스 의존

flowchart LR
    Executor[PaperExecutor] --> Repo[PaperFillRepository]
    Repo -.->|implements| Impl[PaperFillRepositoryImpl]
    Impl --> Table[(paper_fills)]

테스트 케이스

  • paper 모드 승인 시 토스 호출 없이 paper_fills에 모의 체결이 기록된다.
  • 매수·매도 모의 체결로 가상 포지션 수량·평단이 갱신된다.
  • 가상 포지션의 평가손익이 현재가 기준으로 산출된다.
  • 동일 제안 중복 집행은 멱등하게 1건만 기록된다(엣지 케이스).

[WEALTH-P4-04] ApproveOrderProposalUseCase — 모드 분기 집행

작업 내용 (설계 의도)

사용자가 제안을 승인하면 APPROVED로 전이하고, 실행 모드에 따라 분기한다: paper면 PaperExecutor로 모의 체결, live면 **기존 PlaceOrderUseCase**로 토스 실주문. 거부 시 REJECTED 전이·집행 없음. live 전환은 별도 게이트(엣지·페이퍼 성과·자본 규모 확정) 통과 시에만. 기본 모드는 paper.

롤백: 모드 플래그를 paper로 되돌리면 실주문 즉시 중단. 기존 수동 주문 경로는 그대로 유지.

다이어그램

처리 흐름

sequenceDiagram
    participant UC as ApproveOrderProposalUseCase
    participant Repo as OrderProposalRepository
    participant Paper as PaperExecutor
    participant Place as PlaceOrderUseCase 기존
    UC->>Repo: transit(APPROVED)
    alt mode=paper
        UC->>Paper: fill(proposal)
    else mode=live
        UC->>Place: execute(toCommand)
    end

테스트 케이스

  • paper 모드 승인은 PaperExecutor로 모의 체결되고 토스를 호출하지 않는다(기본 동작).
  • live 모드 승인은 기존 PlaceOrderUseCase로 토스 집행된다(해피 패스).
  • 제안 거부 시 REJECTED 전이·집행 없음.
  • 이미 종료된 제안 재승인은 거부된다(상태 보호).
  • live 모드인데 전환 게이트 미통과 시 실주문이 차단된다(상태 보호).
  • 토스 주문 4xx/5xx 시 집행 실패·예외 전파(live).

[WEALTH-P4-05] 제안 조회·승인 FE 화면 (선택)

작업 내용 (설계 의도)

PROPOSED 제안 목록을 보여주고 승인/거부 버튼을 제공하는 FE 화면. 승인 시 P4-04 엔드포인트 호출. 현재 실행 모드(paper/live)를 함께 표시한다. BFF 경유 컨벤션 준수.

테스트 케이스

  • 제안 목록이 출처 신호·수량·가격과 함께 표시된다.
  • 승인 버튼이 집행 엔드포인트를 호출하고 결과를 표시한다.
  • 거부 시 목록에서 제외된다.