9.2 KiB
9.2 KiB
0. 문서 상태
- 상태: confirmed
- 문서 ID: dcy-041_20260729_broker-uncertainty-and-adapter-retirement
- 이슈명: Core 브로커 불확실 상태 구분과 로컬 KIS 어댑터 축소
- 작성 시각(KST): 2026-07-29 16:59:16 KST
- 마지막 갱신 시각(KST): 2026-07-29 17:54:02 KST
- 대체됨: 없음
- 선행 Discovery:
- dcy-013_20260608_kis-external-cancel-pending-sell-stuck
- dcy-022_20260610_stuck-pending-order-recovery
- dcy-039_20260727_intent-venue-end-to-end-propagation
- 후속 Discovery 참조: 없음
- GitHub 이슈: #44, #45
1. 계획 상태 요약
- 해석:
- Core에는 intent 거래소 전달, 외부 취소 감지, 결과불명 주문 복구가 일부 구현돼 있다.
- 남은 공용 공백은
AUTO거래소의 실제 제출 거래소 확정, 취소 요청 결과의 명시적 상태, 짧은 계좌 스냅샷 복구다.
- 목표:
- 공용 기능을 Core가 소유하고 로컬 KIS 호환 어댑터는 KIS 중계만 남도록 축소한다.
- 호출 실패를 실제 불일치로 오판하거나 결과불명 주문을 재전송하지 않는다.
2. 요구사항 판정 결과
- 판정: 신규 운영 후속 Discovery
- 근거:
- 선행 Discovery들은 이미 확정·구현됐지만 2026-07-28~29 실전 운영에서 취소 응답과 계좌조회 불확실 상태가 다시 확인됐다.
- 이번 변경은 기존 기능의 문구 보강이 아니라 Core와 외부 호환 어댑터의 책임 경계를 바꾸므로 독립 추적한다.
3. 문제점의 요약
현재 상태
dcy-039는 intent의KRX|NXT|SOR거래소를 슬롯과 주문·취소까지 보존한다.- 전략이 거래소를 보내지 않으면 기본 KRX이므로, 전략을 바꾸지 않고 08:00 NXT 주문을 보내는
AUTO계약은 없다. BrokerPort.cancel_order()는 참/거짓만 반환하므로 요청 접수, 명시적 거부, 응답유실을 구분하지 못한다.- KIS
get_balance()는 호출 실패를 검증된 빈 잔고와 구분해 예외로 올리지만, 마지막 정상 계좌 스냅샷의 출처·시각·만료 정책은 Core에 없다. - 로컬
nxt_adapter가 주문번호-거래소와 짧은 잔고 스냅샷을 별도 SQLite에 저장한다.
기대 상태
AUTO주문은 KIS 브로커 경계에서 KST 세션에 따라 실제 거래소를 확정하고 슬롯·취소·Core 원장에 보존한다.- 취소 요청 결과는
요청 접수,명시적 거부,결과불명으로 구분하고 최종 취소·체결은 기존 체결조회로 확정한다. - 마지막 정상 계좌 스냅샷은 계정 범위와 캡처 시각을 포함해 원자적으로 저장하고 짧은 유효시간 안에서만 사용한다.
- 신규매수와 위험축소 매도의 허용시간을 분리하고 결과불명 주문은 종목·방향 범위에서 재전송을 차단한다.
4. 이번에 정의할 변경
AUTO거래소를 실제 KRX/NXT로 확정하고 재시작 후에도 원 주문 거래소를 복구한다.- 취소 API 결과를 명시적 상태값으로 바꾸고 응답유실 시 재취소·재주문을 자동 반복하지 않는다.
- 계정별 마지막 정상 잔고 스냅샷과 방향별 만료 정책을 Core/KIS 브로커 계층에 둔다.
5. 요구사항 목록
기능 요구사항
- FR-1:
AUTO|KRX|NXT|SOR를 입력받고AUTO는 KST 세션에 따라 실제 KRX/NXT로 결정한다. 결정 불가능 시간은 KRX로 대체하지 않고 거부한다. - FR-2: 실제 제출 거래소를 슬롯과 Core 체결 전달 대기 원장에 저장하며 취소·재시작 복구에서 재사용한다.
- FR-3: 취소 요청은
requested|rejected|unknown결과를 반환한다.requested는 최종 취소가 아니며 체결조회가cancelled|filled를 확정한다. - FR-4:
unknown취소 결과와 결과불명 주문은 자동 재주문하지 않고 기존 주문 조회로만 수렴한다. - FR-5: 성공한 계좌조회 영역만 계정 해시·독립 캡처 시각과 함께 원자 저장한다. 보유수량과 주문가능금액 중 한쪽 실패가 다른 정상값을 덮지 않는다.
- FR-6: 일시적 전송 오류에만 미만료 스냅샷을 사용한다. 계정 불일치·만료·응답 오류는 차단한다.
- FR-7: 신규매수와 위험축소 매도의 스냅샷 최대 나이를 분리하며 KIS 복구 후 다음 백그라운드 조회가 정상값으로 교체한다.
비기능 요구사항
- NFR-1: 동일 intent와 동일 결과불명 주문의 중복 제출은 0건이어야 한다.
- NFR-2: 기존 KRX 명시 주문, PaperBroker, 전략 wire의 미지정 필드 호환성을 보존한다.
- NFR-3: 토큰·키·계좌번호·원본 KIS 응답은 로그·문서·테스트 산출물에 남기지 않는다.
- NFR-4: DB 마이그레이션은 멱등이고 기존 슬롯·체결 전달 대기 원장을 보존한다.
범위 경계
- In Scope:
- TREX Core의 KIS 브로커, 주문·취소 실행, 슬롯·계좌 스냅샷 영속화, 회귀·장애·재시작 테스트.
- Out of Scope:
- Portfolio Hub API·스키마 변경, 전략 자금배분, 계정관리 대시보드, 토큰 갱신, NXT 분봉 수집, 수동 보유수량 분리.
6. 리스크/가정 목록
- R-1: 취소 요청 접수를 취소 확정으로 처리하면 체결 경쟁에서 중복매수가 발생할 수 있다.
- 완화: 슬롯은 pending을 유지하고 체결조회만 최종 상태를 전이한다.
- R-2: 오래된 계좌 스냅샷이 신규매수를 허용하면 주문가능금액을 초과할 수 있다.
- 완화: 신규매수 유효시간을 짧게 두고 수량·금액 한도를 기존 전략 intent 이하로 제한한다.
- R-3:
AUTO실제 거래소가 영속화되지 않으면 재시작 후 취소가 잘못된 거래소로 갈 수 있다.- 완화: 브로커 응답 직후 슬롯 저장을 주문 접수의 완료 조건으로 둔다.
- A-1: KST 세션은 NXT 08:00
08:49:59, KRX 09:00:3015:29:59, NXT 15:30~20:00으로 운영한다. - A-2: 미확인주문 상태는 기존 슬롯의 broker_order_id와 결과불명 제출 메타데이터가 정본이다.
- 오픈 질문: 없음. 사용자가 2026-07-29 핵심 3개 범위와 순차 구현을 승인했다.
7. 초기 성공 기준
- S-1: 거래소 미지정 전략 intent가 08:00 KST에 NXT로 제출되고 재시작 후 NXT로 취소된다.
- S-2: 취소 응답유실은
unknown으로 남고 같은 주문의 자동 재취소·재매수가 발생하지 않는다. - S-3: KIS 계좌조회 전송 실패에서 미만료 동일계정 스냅샷만 사용하며 신규매수·매도 유효시간이 각각 적용된다.
- S-4: 스냅샷 만료 후 신규매수는 차단되고 보유분 매도·체결조회·원장복구는 독립적으로 검증된다.
- S-5: 단위→회귀→가상계약→가상종단간→오류주입→재시작→원장대조가 모두 통과한다.
8. REQ로 넘기기 전 확인 체크
- 기존 Core와 로컬 어댑터의 중복 책임을 코드로 확인했다.
- GitHub #44·#45의 완료 기준과 범위를 확인했다.
- 실전 반영 전 가상 검증과 원복 게이트를 고정했다.
- 사용자 결정이 필요한 오픈 질문이 없다.
9. 파일 처리 결과
- 처리 결과: 생성
- 생성 경로:
docs/discovery/dcy-041_20260729_broker-uncertainty-and-adapter-retirement.md - 참조:
trex_core/application/broker_port.pytrex_core/application/execution.pytrex_core/adapters/broker/kis.pytrex_core/application/snapshot_scheduler.pydocker-local/KIS_ADAPTER_REMOVAL_CONTRACT.md
10. 사용자 결정 필요 항목 요약
- 없음. 사용자가 핵심 범위, 기능별 브랜치, Docker 선검증, 서버 차이 검증, 실전 적용 후 어댑터 축소 순서를 승인했다.
11. Discovery Freeze
- Handoff Decision: 승인
- Handoff Rationale: Core의 기존 거래소 전달·결과불명 주문 처리와 남은 취소·계좌조회 공백을 재확인했고, 사용자 승인 범위와 충돌하는 오픈 질문이 없다.
- Ready for REQ Drafting: true
- Confirmed By: 형님
- Confirmed At (KST): 2026-07-29 17:01:50 KST
12. 구현 증거
AUTO실제 거래소 확정·주문번호 동시 저장·재시작/취소 재사용: 구현 완료.- 취소
requested|rejected|unknown영속화와 poll 전용 최종확정: 구현 완료. - 계정 해시·독립 TTL·백그라운드 단일 소유자·매수/매도 분리: 구현 완료.
- 계정 해시는 KIS endpoint·계좌·상품·app identity를 함께 묶어 실전/모의·자격증명 출처를 분리한다.
- 동일 instance advisory lock 안에서 현금 예약검사와 pending 전이를 원자 처리한다.
- timeout·운영자 취소 모두 compare-and-set 예약으로 동일 주문 재취소를 차단한다.
- KIS 현금 권위 필드:
inquire-psbl-order.output.nrcvb_buy_amt. - 수동 혼합 보유 계정:
OwnershipAwareBroker투영 뒤 스냅샷을 생성하여 전략 소유 수량만 매도 허용. - 운영 기본값: 기능 OFF, 매수 600초, 매도 3600초, 갱신 300초.
- 검증: 로컬 903 passed, 격리 Docker PostgreSQL/RabbitMQ 953 passed, 공용 가상 인증 7단계 PASS.
- 검증 문서:
docs/validation/dcy-041-core-adapter-gap-closure-20260729.md - 실전 반영: 가상 검증과 사용자 별도 승인 전까지 미적용.