매도(sell) 주문이 현재가가 아닌 매수가(entry_price) 지정가로 나가던 버그(issue #10) 정정. 슬롯의 매수 전용 entry_price 를 side 무관 "현재 pending 주문 지정가" limit_price 로 내부 rename 하고, pending 이탈(→holding/→closed) 시 clear 해 매수 지정가가 매도로 누수되는 경로를 구조적으로 제거. 거버넌스: 전부 change-req (신규 REQ 없음, dcy-012 OQ-3). - REQ-002: Slot entry_price→limit_price rename + clear-on-exit 생애주기 - REQ-006: daily_slot 컬럼 rename 마이그레이션 006 (idempotent) + persistence 매핑 - REQ-013: _dispatch 가 slot.limit_price 단일 필드로 가격/주문유형 결정 - REQ-007: SellIntent/sell payload optional limit_price + _admit_sell 운반 - REQ-036: SlotService.sell optional 가격 → 자율 매도(safety-sell/kill-switch) 시장가 - REQ-003: 컬럼 계약/드리프트 가드 limit_price 반영 - REQ-015: runtime-flows/interface-contract/data-model 정합 매도 정책(OQ-1 하이브리드): 가격 지정→지정가("00"), 미지정→시장가("01"). 자율 매도는 가격 미전달 → 항상 시장가 (손절 미체결 pending_sell 갇힘 방지, issue #9 연계). 검증: 단위 286 passed/32 skipped, 인프라 게이트(PG+RabbitMQ) 318 passed, ruff clean. 신규 test_sell_pricing(recording broker)로 지정가 매수 슬롯의 매도가 매수가 재사용 안 함을 직접 검증. BAT-016 release-candidate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
28 KiB
0. 문서 상태
이 문서의 현재 상태와 식별 정보를 기록한다. 문서 추적과 승인 흐름에 필요한 최소 메타데이터를 적는다.
- 상태: confirmed
- 문서 ID: dcy-012_20260608_sell-order-pricing-entry-price-bug
- 이슈명: 매도 주문이 현재가가 아닌 entry_price(매수가) 지정가로 나가는 버그 — sell dispatch 가격 정책 부재
- 작성 시각(KST): 2026-06-08 12:30 KST
- 마지막 갱신 시각(KST): 2026-06-08 15:40 KST
- 대체됨: 없음
- 후속 Discovery 참조: 없음
- 생성된 REQ 참조: REQ-013/007/036/002/006/003/015 (전부 change-req, 신규 REQ 없음 — OQ-3). REQ-007=CHG-20260608-02, 그 외=CHG-20260608-01. delivery: BAT-016
1. 계획 상태 요약
현재 Discovery가 어떤 배경에서 작성되고 있는지, 연계 문서가 있는지, 지금 시점의 해석이 무엇인지 짧게 요약한다.
- 연계 문서 현황:
- 관련 점수 파일: 미생성
- 관련 TODO/메모: GitHub issue #10 (fourblocks2020/trex-core), 관련 issue #9(pending_sell 갇힘)
- 해석:
- 매도(sell) 주문 집행 경로(
_dispatch)가 buy/sell 구분 없이slot.entry_price(매수가)를 지정가로 사용해, 매도가 현재 시장가가 아닌 매수가에 걸린 지정가 주문으로 나가는 정합성 버그를 정식 SDLC 주기로 착수한다. - 이번 Discovery에서는 sell dispatch 의 가격 결정 정책(시장가 vs 현재가 지정가 vs 인텐트 전달 가격)을 판정하고, safety-sell(자율 매도)과 RPC 재량 매도에 어떤 정책을 적용할지 범위를 정한다. 이미 Implemented·released(REL-001/003) 된 집행 경로(dcy-003 broker execution) 변경이고, 매도 지정가 운반을 위해 슬롯
entry_price를 side 무관limit_price로 내부 rename(Option A) 하므로, 거버넌스는 OQ-3 결정에 따라 기존 REQ(REQ-013/007/036/002/006/003/015)change-req로 처리하고 신규 REQ 는 생성하지 않는다.
- 매도(sell) 주문 집행 경로(
2. 요구사항 판정 결과
이번 요청이 기존 요구사항과 비교해 신규인지, 유사한지, 중복인지 판단하고 그 근거를 남긴다.
- 판정: 신규
- 근거
- 기존 Discovery(dcy-001~dcy-011) 중 sell dispatch 의 주문 가격 결정 정책을 다룬 문서는 없다. dcy-003(broker execution + outbox)은
_dispatch/주문 제출 경로를 도입했지만 buy/sell 가격 분기를 정의하지 않았고, dcy-007(safety-sell)은 손절/익절 트리거 조건과get_current_price평가를 다루되 집행 시 매도 주문 가격을 재정의하지 않았다. dcy-010(영속 거부 backoff)은 거부 재시도만 다룬다. - 변경이 이미 Implemented·released 된 집행 경로(
_dispatch)의 주문 가격/주문유형(지정가 vs 시장가) 의미를 바꾸고, 매도 인텐트 계약(SellIntent)에 optional 가격 필드를 추가하므로, 기존 Discovery 미세 조정이 아니라 독립 주기로 추적하는 것이 명확하다.
- 기존 Discovery(dcy-001~dcy-011) 중 sell dispatch 의 주문 가격 결정 정책을 다룬 문서는 없다. dcy-003(broker execution + outbox)은
3. 문제점의 요약
문제의 현재 상태, 기대 상태, 관련 이해관계자, 제약사항을 정리한다. Discovery의 핵심 맥락을 가장 먼저 이해할 수 있어야 한다.
- 현재 상태
trex_core/application/execution.py의_dispatch(execution.py:84~)는side = "buy" if PENDING_BUY else "sell"로 side 를 구하지만, 바로 다음limit = int(slot.entry_price) if slot.entry_price else None(execution.py:91)에서 side 를 무시하고 buy/sell 공통으로entry_price(매수가)를 지정가로 쓴다.order_type은"00"(지정가) if limit is not None else "01"(시장가)(execution.py:99)로 결정되므로, 매도도 매수가에 걸린 지정가 주문으로 나간다.- 버그의 발현은 슬롯의 매수 유형에 의존한다.
entry_price는 지정가 매수일 때만 채워지고 시장가 매수에서는 NULL 로 남으며(체결가는avg_price에만 기록, 매수 체결 시entry_price미갱신), 매수 후에는_dispatch의 limit 계산이 유일한 행위적 소비처다. 따라서 (a) 지정가 매수로 진입한 슬롯은 매도 시entry_price(매수가)로 지정가 매도가 나가 버그가 발현되고, (b) 시장가 매수로 진입한 슬롯은entry_price=NULL → limit=None → order_type="01"로 우연히 시장가 매도가 나가 정상 동작한다. 즉 issue #10 은 지정가 매수 슬롯에서 재현된다. trex_core/application/intents.py의SellIntent(intents.py:68~)는intent_id/slot_id/reason/sell_strategy_id/extra만 가지며 가격 필드가 없다._admit_sell(intents.py:193~)은HOLDING → PENDING_SELL상태 전이만 수행하고 가격 파라미터를 넘기지 않아, 슬롯의entry_price는 매수 때 값 그대로 유지된다.trex_core/application/broker_port.py의get_current_price(symbol)(broker_port.py:94)는 존재하지만_dispatch에서 호출되지 않는다. 현재 이 메서드는 safety-sell 워커의 손절/익절 평가에서만 쓰인다(trex_core/application/safety_sell.py:182).trex_core/domain/slot/models.py의 Slot 은avg_price(매수 체결가, models.py:27)·entry_price(매수 지정가, models.py:28)만 가지며 매도 시점 시장가를 담을 필드가 없다.docs/interface-contract.md(92행)의 sell payload 계약은{intent_type:"sell", intent_id, slot_id, reason, sell_strategy_id}로, 가격 필드가 없다(현 코드와 일치).- baseline 문서(
docs/project-structure.md,docs/runtime-flows.md)는 존재하며 최신이다. sell 집행은 기존 runtime flow(주문 dispatch)에 포함돼 있고, 이번 변경은 그 흐름의 매도 가격 결정 단계를 정정한다.
- 기대 상태
- 매도(
pending_sell) 집행 시 매수 지정가가 아니라 OQ-1 하이브리드 정책에 맞는 가격으로 주문이 나간다 — 인텐트가 가격을 지정하면 그 지정가, 미지정이면 시장가. (현재가 자동 조회 지정가는 미채택.) - 손절(stop-loss) 상황에서는 가격 미전달로 시장가 매도가 나가 의도대로 체결되어, 미체결 매도가
pending_sell에 갇히는 문제(issue #9)의 직접 원인이 제거된다.
- 매도(
- 이해관계자
- 문서 작성자(AI agent) — Discovery/REQ/Batch 산출물 작성
- 리뷰어/승인자 — 매도 가격 정책 및 집행 경로 변경 승인
- 운영 담당자 — released 집행 경로 변경에 따른 실거래 영향 관리
- 전략 모듈 개발자 — 재량 매도(RPC) 인텐트 호출부 변경 가능성
- 제약사항
- 이미 released(REL-001/003) 된 집행 경로 변경이므로 ad-hoc 수정이 아니라 정식 SDLC(change-req 또는 신규 REQ) 경유가 필요하다.
- KIS 주문 계약상
ORD_DVSN(00 지정가 / 01 시장가)과ORD_UNPR의미가 정해져 있어, 매도 가격 유무가 곧 주문유형·가격 필드 매핑을 결정한다.
주요 사용자 시나리오
사용자 또는 운영자가 실제로 어떤 상황에서 이 변경을 필요로 하는지 대표 시나리오를 적는다.
- safety-sell 워커가 손절 조건(현재가 < stop_loss_price)으로 매도를 트리거했는데, 집행이 매수가 지정가로 나가 체결되지 않고 슬롯이
pending_sell에 갇힌다 → 정책에 맞는 가격으로 즉시 체결되어야 한다. - 전략 모듈이 RabbitMQ 로 재량 매도(sell intent)를 보내면, 현재 시장가 기반으로 매도가 집행되어 의도한 청산이 이뤄진다.
- 현재가가 매수가보다 높은 상황에서 매도 시, 매수가에 걸린 불리한 지정가가 아니라 시장가(또는 인텐트가 지정한 가격)로 체결되어 손실 없이 청산된다.
4. 이번에 정의할 변경
이번 Discovery에서 다루는 핵심 변경 항목을 목록으로 적는다. 기능, 구조, 규칙 변경을 함께 포함해도 된다.
- 슬롯의 매수 전용
entry_price를 side 무관 "현재 pending 주문 지정가" 단일 필드(내부 rename:limit_price) 로 재정의한다. pending 진입 시(매수: buy intent 지정가 / 매도: sell intent optional 가격) set 하고, pending 이탈(→HOLDING, →CLOSED) 시 None 으로 clear 한다(매수 지정가의 매도 누수 = #10 근본 원인을 구조적으로 차단). 감사 이력은 기존처럼 transition_log 가 보존한다. _dispatch는 side 분기로 가격을 고르지 않고slot.limit_price하나만 읽는다 — 값이 있으면 지정가(order_type="00"), 없으면 시장가(order_type="01")(OQ-1 하이브리드).SellIntent/sell payload 에 optional 매도 가격 필드를 추가하고,_admit_sell(및SlotService.selloptional 파라미터)이 그 가격을 슬롯limit_price로 운반한다. safety-sell/kill-switch 는 가격 미전달 → 시장가.- 인터페이스 계약 문서(
docs/interface-contract.md)와 sell 집행 runtime flow 기술을 새 정책에 맞춰 갱신한다. (단, buy/sell payload 의 외부 필드명entry_pricerename 은 dcy-012 범위 밖 — REQ-007/dcy-011 과 조율; 본 주기는 내부 슬롯 컬럼/도메인 필드 rename 까지.)
영향 범위
변경이 미칠 코드/문서/운영 범위를 명시해 REQ 정제와 batch planning에서 추정 누락을 줄인다.
- 코드 영향:
trex_core/domain/slot/models.py— 슬롯 필드entry_price→limit_price(side 무관 "현재 pending 주문 지정가") 내부 renametrex_core/domain/slot/service.py—transit_slot/_apply_transition_fields에서 →HOLDING·→CLOSED 시limit_price를 None 으로 clear(현 →IDLE 리셋 분기 패턴 재사용),SlotService.sell에 optional 매도 지정가 파라미터 추가(safety-sell/kill-switch 미전달 → 시장가), 매수 경로는 buy 지정가를limit_price로 settrex_core/application/execution.py—_dispatch가slot.limit_price단일 필드만 읽어 가격/주문유형 결정(side 분기 제거, 핵심 버그 지점)trex_core/application/intents.py—SellIntentoptional 매도 가격 필드,_admit_sell이 가격을 슬롯limit_price로 운반.BuyIntent/_admit_buy의 매수 지정가도limit_price로 매핑trex_core/application/messaging_handlers.py— 외부 payload 필드명(entry_price)과 내부limit_price의 경계 매핑(외부 필드명 rename 은 본 주기 밖)trex_core/adapters/persistence/postgresql.py,trex_core/adapters/persistence/sql/— 슬롯 컬럼entry_price→limit_pricerename 마이그레이션 + 매핑 갱신trex_core/adapters/broker/kis.py—submit_order의ORD_DVSN/ORD_UNPR매핑은 OrderRequest 변경에 따라 자동 반영(직접 수정 최소)
- 문서 영향:
docs/interface-contract.md— sell payload 매도 가격 필드 추가 및 주문유형 매핑 갱신docs/runtime-flows.md— sell 집행 흐름의 가격 결정 단계 정정 + limit_price 생애주기(set/clear)docs/data-model.md— 슬롯entry_price→limit_price컬럼 의미/이름 갱신
- 운영 영향:
- released 집행 경로의 매도 동작 변경 + 슬롯 컬럼 rename 마이그레이션 → 실거래 매도 체결 방식 변화 및 스키마 변경, 배포 전 검증·마이그레이션 절차 필요
5. 요구사항 목록
실제로 구현과 검증으로 이어질 요구사항을 기능/비기능으로 나누어 정리하고, 범위 경계를 명확히 적는다.
기능 요구사항
- FR-1: 슬롯의 매수 전용
entry_price를 side 무관 단일 지정가 필드limit_price(내부 rename)로 재정의한다.limit_price는 pending 진입 시 해당 주문(매수/매도)의 지정가로 set 되고, pending 이탈(→HOLDING, →CLOSED) 시 None 으로 clear 되어 매수 지정가가 매도로 누수되지 않는다. - FR-2:
_dispatch는 side 분기 없이slot.limit_price만 읽어 주문유형/가격을 결정한다 — 값이 있으면order_type="00"(지정가, 그 가격), 없으면order_type="01"(시장가). 매수가(과거 entry_price 의미)를 매도 지정가로 재사용하지 않는다. - FR-3:
SellIntent및 sell payload 계약에 optional 매도 가격 필드를 추가하고,_admit_sell(및SlotService.selloptional 파라미터)이 이를 슬롯limit_price로 전달한다. 매수 경로는 buy 지정가를 동일limit_price로 set 한다. - FR-4: safety-sell·kill-switch(자율 매도)는 가격 미전달로 시장가, RPC 재량 매도는 가격 지정 시 지정가로 동작한다 — 단일 메커니즘(가격 유무 분기)을 모든 매도에 일관 적용한다(OQ-2).
- FR-5:
docs/interface-contract.md·docs/runtime-flows.md·docs/data-model.md를 확정된 매도 가격 정책과limit_price생애주기(set/clear)·컬럼 rename 에 맞춰 갱신한다.
비기능 요구사항
성능, 운영성, 일관성, 자동화 안정성 등 기능 외 요구사항을 적는다.
- NFR-1: 체결성 — 매도 트리거(특히 손절)는 가격 미전달로 시장가가 되어 의도대로 즉시 체결되고, 미체결로
pending_sell에 갇히는 케이스(issue #9 연계)를 유발하지 않아야 한다. - NFR-2: 가격 안전성 — 매도가 매수 지정가에 걸려 불리하게 체결되거나 영원히 미체결되는 정합성 오류가 재발하지 않아야 한다.
limit_price의 clear-on-exit 로 매수 지정가가 매도 주문에 잔존하지 않아야 한다. - NFR-3: 계약 호환 — sell payload 의 매도 가격 필드는 optional 이어야 하며, 미지정(기존 호출 형태)은 시장가로 안전하게 동작해 기존 재량 매도 호출을 깨지 않아야 한다. 외부 payload/read 필드명(
entry_price)은 본 주기에서 rename 하지 않아 기존 계약 호환을 유지한다.
범위 경계
이번 반복에서 반드시 포함할 범위와 명시적으로 제외할 범위를 구분한다.
- In Scope
- 슬롯
entry_price→limit_price내부 rename(도메인 모델/DB 컬럼/persistence) + pending 이탈 시 clear 생애주기 _dispatch가slot.limit_price단일 필드로 가격/주문유형 결정(side 분기 제거)SellIntent/sell payload optional 가격 필드 + 슬롯limit_price운반(_admit_sell/SlotService.sell)- 인터페이스/런타임/데이터모델 문서 갱신, 슬롯 컬럼 rename 마이그레이션
- 슬롯
- Out of Scope
- buy 주문 가격 의미 변경(매수 지정가는 그대로
limit_price로 set — 동작 동일, 저장 위치명만 통일) - 외부 buy/sell payload·slot read 의 필드명(
entry_price) rename — REQ-007/dcy-011 과 조율할 별도 계약 변경 - issue #9(KIS 외부 취소 시 pending_sell 갇힘) 자체의 복구 로직 — 본 버그는 #9 의 한 원인을 제거하나, #9 의 별도 복구는 후속 이슈로 분리
- dispatch 시 현재가 자동 조회(
get_current_price) 기반 지정가 — OQ-1 에서 미채택(급락 손절 시 재차 미체결 위험)
- buy 주문 가격 의미 변경(매수 지정가는 그대로
6. 리스크/가정 목록
불확실성과 전제 조건을 분리해서 적는다. 리스크는 영향과 완화 방안을, 가정은 현재 판단의 전제를 기록한다.
리스크
- R-1 (High): released 집행 경로의 매도 동작을 바꾸므로, 정책 선택이 잘못되면 실거래 매도가 의도와 다르게 체결될 수 있다.
- 완화 방안: paper-broker/스텁으로 시나리오(손절/익절/현재가>매수가/현재가<매수가) 검증 후 배포하고, change-req 로 REQ-013/007/036/002/006/003/015 변경 이력을 남긴다.
- R-2 (Medium): 재량 매도가 지정가로 들어오면, 시장가가 그 지정가에 닿지 않을 때 미체결로
pending_sell에 머물 수 있다(지정가의 본질적 특성).- 완화 방안: 지정가 미체결 처리(취소/재시도/타임아웃)는 기존 dispatch 폴/롤백 경로와 issue #9 복구 범위에서 다루고, 본 주기는 가격 결정 분기에 집중한다. 운영자는 재량 매도 지정가의 미체결 리스크를 인지한다.
- R-3 (Low, OQ-2 결정으로 해소): reason 별 코드 차등을 두지 않고 가격 유무로 분기하므로, safety-sell 은 가격 미전달로 항상 시장가가 되어 손절 체결성이 보장되고 재량 매도만 선택적으로 지정가를 쓴다.
- 완화 방안:
SlotService.sell의 가격 파라미터 기본값을 None(시장가)으로 두어 자율 매도 경로가 실수로 지정가를 받지 않도록 한다.
- 완화 방안:
- R-4 (Medium):
entry_price → limit_price슬롯 컬럼 rename 과 clear-on-exit 도입은 도메인/persistence/마이그레이션을 건드려, 누락 시 매수 지정가 복원이나 영속 매핑이 깨질 수 있다.- 완화 방안: 컬럼 rename 마이그레이션과 전이별 set/clear(특히 →HOLDING·→CLOSED clear, →PENDING set)를 단위 테스트로 검증하고, 외부 payload/read 필드명은 그대로 유지(경계 매핑)해 계약 호환을 보존한다.
가정
아직 확정되지 않았지만 현재 문서 작성의 기반이 되는 전제를 적는다.
- A-1: dcy-011(BAT-015) 이 Implemented 되어 매수 시
symbol이 항상 서버 resolve 로 슬롯에 채워지므로, 매도 dispatch 의 KIS 주문에 쓸slot.symbol이 신뢰성 있게 존재한다(가정 충족 확인됨). - A-2: safety-sell(safety_sell.py:98)·kill-switch(killswitch.py:61)는
SlotService.sell(slot_id, actor, reason)로 가격을 전달하지 않으므로, 가격 파라미터를 optional(default None)로 추가해도 자율 매도 경로는 자동으로 시장가가 된다. - A-3: 매수 주문 가격 의미는 그대로 유지된다 — buy 지정가는 동일
limit_price로 set 되어 매수 동작은 변하지 않고, 슬롯 상태 전이 규칙(허용 전이 집합)도 유지된다. 변경은 가격 필드의 의미 통일(side 무관)과 pending 이탈 시 clear 추가뿐이다. - A-4: KIS 시장가 매도(
ORD_DVSN="01")가 paper 및 실계좌에서 정상 수용된다(DATA 로 확인).
오픈 질문
답을 아직 모르는 항목을 적는다. 추정으로 덮지 말고 REQ 초안 작성 이전에 확인할 질문으로 남긴다.
- OQ-1: 매도 가격 정책 — (1) 시장가 매도, (2) 현재가 기반 지정가, (3) 인텐트 전달 가격 중 무엇을 채택하는가(단일 또는 조합)?
- 상태: Answered (2026-06-08, 사용자 결정 — 하이브리드: 인텐트가 가격을 지정하면 지정가, 미지정이면 시장가)
- 결정:
SellIntent/sell payload 에 optional 매도 가격 필드를 둔다. 가격이 있으면order_type="00"(지정가)로 그 가격에, 없으면order_type="01"(시장가)로 매도한다. 매수가(entry_price)는 매도 가격으로 절대 사용하지 않는다. dispatch 에서get_current_price조회는 하지 않는다(옵션 2 미채택). - 반영 위치: FR-1/FR-2/FR-3, 4. 변경 항목, 영향 범위
- OQ-2: 정책 적용 범위 — safety-sell(손절/익절/긴급)과 RPC 재량 매도에 동일 정책을 적용하는가, reason 별 차등(예: 손절=시장가, 재량=지정가)을 두는가?
- 상태: Answered (2026-06-08, 사용자 결정 — 가격 유무로 분기, reason 별 코드 차등 없음)
- 결정: 단일 메커니즘(가격 유무 분기)을 모든 매도에 적용한다. safety-sell/kill-switch 는
SlotService.sell(slot_id, actor, reason)로 가격을 전달하지 않으므로 자동으로 시장가가 되어 체결성이 보장된다. 재량 매도(RPC)만 가격을 optional 로 실어 지정가 통제를 쓸 수 있다. - 반영 위치: FR-4, A-2, R-3
- OQ-3: 거버넌스 경로 — 본 변경을 기존 REQ(dcy-003 집행 계열, sell 인텐트 계약 REQ)의 change-req 로 처리할지, 신규 REQ 로 추적할지?
- 상태: Answered (2026-06-08, 사용자 결정 — change-req 우선)
- 결정: 기존 Implemented REQ 본문 수정(change-req)으로 처리한다. change-req 대상 — REQ-013(주문 집행 루프:
_dispatch가slot.limit_price단일 필드로 결정), REQ-007(intent 제출 API: sell payload optional 매도 가격 필드), REQ-036(자동 매도 내부 경로:SlotService.selloptional 가격 파라미터), REQ-002(slot 순수 도메인:entry_price→limit_pricerename + pending 이탈 clear 전이 의미), REQ-006(PostgreSQL 영속화+스키마: 컬럼 rename 마이그레이션), REQ-003(컬럼 계약 가드 테스트: 컬럼명 변경 반영), REQ-015(브로커/집행 baseline 문서 정합). 하이브리드+rename 모두 기존 REQ 범위 안에서 표현 가능하므로 신규 REQ 는 생성하지 않는다. (Option A 의 rename 으로 change-req 대상이 slot 도메인/persistence 까지 넓어짐 — 비용은 거버넌스 footprint 증가, 이득은 매수 지정가의 매도 누수 구조적 차단.) - 반영 위치: 1. 거버넌스 해석, R-1 완화 방안, 8. 확인 체크
오픈 질문 처리 기준
Open: 아직 답이 없고 다음 단계 진행에 영향이 있는 상태다. 문서에 유지한다.Answered: 답이 확정된 상태다. 관련 본문/요구사항에 반영한 뒤 오픈 질문 목록에서는 제거하거나 resolved 기록으로 이동한다.Deferred: 지금 단계에서 결정하지 않고 다음 단계 또는 후속 이슈로 넘기는 상태다. 넘길 대상과 이유를 반드시 적는다.Dropped: 더 이상 유효하지 않은 질문이다. 삭제 사유를 짧게 남기고 목록에서 제거한다.
7. 초기 성공 기준
이 변경이 성공했다고 판단할 기준을 측정 가능하게 정의한다. 가능하면 데이터 출처까지 연결한다.
- S-1: 매도 dispatch 가 매수 지정가를 재사용하지 않음을 코드/테스트로 보장한다 —
limit_price가 pending 이탈 시 clear 되어, 가격 미전달 매도는order_type="01"(시장가), 가격 전달 매도는order_type="00"(해당 지정가)로 발행. - S-2: safety-sell 손절 트리거 시나리오(가격 미전달)에서 매도가 시장가로 정상 체결되어
pending_sell갇힘이 발생하지 않는다. - S-3:
entry_price → limit_price컬럼 rename 마이그레이션 후 기존 슬롯 데이터가 보존되고,limit_price생애주기(→PENDING set / →HOLDING·→CLOSED clear)가 의도대로 동작한다. - S-4: 변경된 매도 가격 정책·rename 이
docs/interface-contract.md·docs/runtime-flows.md·docs/data-model.md에 반영되고, 코드(execution.py, intents.py, slot service/models, persistence)와 문서가 일치한다.
측정 방식 및 데이터 출처
각 성공 기준을 어떻게 측정할지와 어떤 데이터나 문서를 근거로 쓸지 적는다.
- S-1 측정 방식: 단위/통합 테스트(가격 미전달→시장가, 가격 전달→지정가, entry_price 미사용 케이스) 통과 / 데이터 출처:
_dispatch테스트, paper-broker 주문 기록(OrderRequest)- 검증 필수 조건: 버그는
entry_price가 채워진 지정가 매수 슬롯의 매도에서만 재현되므로, 검증 시나리오는 반드시 지정가 매수(entry_price 채워짐)로 진입한 슬롯의 매도 케이스를 포함해야 한다. 시장가 매수(entry_price=NULL) 슬롯만 테스트하면 수정 전후 모두 시장가 매도가 나가 버그를 검출하지 못한다. 권장 케이스 — (a) 지정가 매수 슬롯 + 가격 미전달 매도 → 시장가(entry_price 미사용 증명), (b) 지정가 매수 슬롯 + 가격 전달 매도 → 그 지정가, (c) 시장가 매수 슬롯 매도 → 시장가(회귀 안전성).
- 검증 필수 조건: 버그는
- S-2 측정 방식: safety-sell 손절 시나리오 e2e 검증 후 슬롯 상태가 closed 로 전이 / 데이터 출처: 슬롯 상태 스냅샷, 주문/체결 로그
- S-3 측정 방식: 마이그레이션 실행 후 슬롯 행 보존 확인 + 전이별 set/clear 단위 테스트(→PENDING set, →HOLDING·→CLOSED clear) 통과 / 데이터 출처: 마이그레이션 SQL,
transit_slot테스트, persistence 라운드트립 - S-4 측정 방식: 코드-문서 정합 리뷰(diff 대조) / 데이터 출처:
docs/interface-contract.md,docs/runtime-flows.md,docs/data-model.md, 변경 코드 diff
8. REQ로 넘기기 전 확인 체크
REQ 초안 작성 단계로 넘기기 전에 무엇이 확정되어야 하는지 확인한다. 미완료 항목은 후속 결정이 필요함을 뜻한다.
- 범위(In Scope/Out of Scope) 확정
- 기준: 매도 가격 정책(OQ-1 하이브리드)·적용 범위(OQ-2 가격 유무 분기)·거버넌스(OQ-3) 모두 확정됨
- 성공 지표의 측정 방식/데이터 출처 확정
- 기준: S-1~S-4 의 테스트/검증 출처가 실제 실행 가능한 형태로 지정됨
- High 영향 리스크 우선순위 및 해소 책임자 지정
- 기준: R-1(실거래 매도 동작 변경)·R-4(컬럼 rename/마이그레이션)의 change-req 대상(REQ-013/007/036/002/006/003/015)이 OQ-3 으로 확정됨. 해소 실무 책임자 배정은 REQ/batch planning 단계로 넘김(비차단).
- 모든 오픈 질문(OQ)
Open상태 없음 확인- 기준: OQ-1~OQ-3 모두
Answered,Open0개
- 기준: OQ-1~OQ-3 모두
- Freeze 확정 담당자(CONFIRMED_BY) 지정
- 기준: Confirmed By = Justin (사람 승인자 지정 완료)
9. 파일 처리 결과
이 Discovery 문서 생성/갱신 결과와 참조 문서를 기록한다. 이후 추적과 리뷰 시 근거로 사용한다.
- 처리 결과: 생성
- 생성 경로: docs/discovery/dcy-012_20260608_sell-order-pricing-entry-price-bug.md
- 참조 문서:
- GitHub issue #10 (fourblocks2020/trex-core) — 매도가 entry_price 지정가로 나가는 버그
- docs/discovery/dcy-003_20260604_broker-execution-and-outbox.md —
_dispatch/주문 제출 경로 도입 근거 - docs/discovery/dcy-007_20260606_core-autonomous-safety-sell.md — safety-sell 트리거·
get_current_price평가 - docs/discovery/dcy-011_20260608_buy-intent-portfolio-id-required-symbol-resolve.md — slot.symbol 서버 resolve 보장(가정 A-1)
- trex_core/application/execution.py:84-104 —
_dispatch매도 가격 버그 지점(limit 줄 91)
10. 사용자 결정 필요 항목 요약
사용자나 승인자가 결정해야 하는 항목만 모아 정리한다. 결정, 확인, 데이터 요청을 구분해서 적는다.
DECIDE
- (없음 — OQ-1/OQ-2 확정으로 매도 가격 정책 해소)
결정 완료(2026-06-08): OQ-1 매도 가격 정책 = 하이브리드(가격 지정 시 지정가, 미지정 시 시장가) / OQ-2 적용 범위 = 가격 유무 분기 단일 메커니즘(reason 별 차등 없음).
CONFIRM
- 없음 — 거버넌스 경로는 OQ-3 으로 확정됨(REQ-013/007/036/002/006/003/015 change-req, 신규 REQ 없음).
DATA
- (비차단) KIS 시장가 매도(
ORD_DVSN="01")의 paper/실계좌 수용 및 체결 특성 — REQ/delivery 단계의 acceptance/verification 에서 계측·확인할 운영 데이터(A-4). Discovery 본문만으로 FR/NFR·범위·성공 기준이 REQ 초안으로 충분하므로 confirm 차단 사유가 아니다.
11. Discovery Freeze
REQ 초안 작성 인계 시점의 확정 플래그와 섹션 참조만 기록한다. 내용 재작성 없이 원본 섹션을 링크로 대신한다.
섹션 참조
- 범위: # 5. 요구사항 목록 > 범위 경계
- 리스크/오픈 질문: # 6. 리스크/가정 목록
- 성공 기준: # 7. 초기 성공 기준
- 인계 전 확인: # 8. REQ로 넘기기 전 확인 체크
- 사용자 결정 필요: # 10. 사용자 결정 필요 항목 요약
Freeze 플래그
- Handoff Decision: 승인
- Handoff Rationale: confirm-discovery 완료. Option A(슬롯
entry_price→limit_price내부 rename + clear-on-exit) 설계 반영. 오픈 질문 OQ-1~OQ-3 모두 Answered (매도 가격=하이브리드: 가격 지정 시 지정가/미지정 시 시장가 / 가격 유무 분기, reason 차등 없음 / 거버넌스=REQ-013/007/036/002/006/003/015 change-req, 신규 REQ 없음). C 유형 플레이스홀더 0개, 저장소 사실관계 일치(줄번호 정정 포함). DATA(KIS 시장가 매도)는 REQ/delivery 단계 계측 비차단. REQ 초안 작성 인계 가능. - Ready for REQ Drafting: true
- Confirmed By: Justin
- Confirmed At (KST): 2026-06-08 14:50 KST