Files
trex-core/docs/srs/Integration/req-038_stop-loss-take-profit-kis-polling.md
T
genichinandClaude Sonnet 4.6 0082d3b5da fix(kis): REQ-038 현재가 tr_id 정정 + REL-003 확정 + dcy-008 kill-switch Discovery
## REQ-038 CHG-04/05: KIS 시세 tr_id 정정 (FHKST01010100)
- kis.py _tr_price(): TTTC8397R/VTTC8397R → FHKST01010100 (실전/모의 공용)
  배포 전 실 KIS LIVE 진단에서 구 tr_id가 rt_cd=1 "없는 서비스 코드"로 거부됨을
  확인 — stop-loss/take-profit이 LIVE에서 조용히 미발동하는 결함이었음.
  FHKST01010100으로 정정 후 get_current_price('005930')=329000(rt_cd=0) 확인.
- test_kis_price.py: AC-7 테스트 정정 (FHKST01010100 공용 검증)
- REQ-038: CHG-04/05 Change Log 추가, Requirement/AC-7/Notes 정정
- BAT-011 implementation.md: LIVE 검증 및 tr_id 정정 이력 추가
- BAT-011 verification.md: AC-7 evidence를 CHG-04 정정 버전으로 갱신
- docs/srs/index.md: CHG-04/05 Change Log 항목 추가

## REL-003: core 자율 안전 매도 release 문서 생성
- docs/releases/rel-003_20260607_core-autonomous-safety-sell.md 신규 생성
  (BAT-010 + BAT-011, app-service profile, Status: confirmed)
- docs/releases/index.md: REL-003 행 추가

## dcy-008: 비상 정지/강제 청산(kill-switch) Discovery 초안
- docs/discovery/dcy-008_20260607_emergency-stop-kill-switch.md 신규 생성
  GitHub #3 기반; SlotService.sell() 재사용, 당일 전략 제외 day-scoped
  FR 6개, NFR 3개, OQ 4개 (트리거 표면/영속 방식/수동 해제 결정 필요)
- docs/discovery/index.md: dcy-008 행 추가

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 10:17:36 +09:00

10 KiB
Raw Blame History

req-038: stop-loss·take-profit KIS 가격 polling + 트리거

  • Status: Implemented
  • Type: Integration
  • Priority: High
  • Owner: project maintainers

Intent

워치독이 만료된 슬롯에 한해 KIS API(TTTC8397R 실전 / VTTC8397R 모의)로 현재가를 주기적으로 polling하고, 현재가 <= stop_loss_price(손절) 또는 현재가 >= take_profit_price(익절) 조건 충족 시 자동 매도를 제출한다. 전략 모듈이 정상 활성 중인 슬롯에는 개입하지 않는다(dcy-007 FR-2, NFR-3, A-3).

Requirement

  • 데몬은 TREX_STOP_LOSS_POLL_INTERVAL(초) 주기로, stop_loss_price 또는 take_profit_price가 설정되고 워치독이 만료된 holding 슬롯들의 현재가를 KIS 주식현재가 시세 API(/uapi/domestic-stock/v1/quotations/inquire-price, tr_id FHKST01010100, 실전/모의 공용)로 polling해야 한다. (CHG-20260607-04: 시세 tr_id 정정 — 구 TTTC8397R/VTTC8397R는 실 KIS 에서 "없는 서비스 코드".)
  • 현재가 평가 기준값은 stck_prpr(직전 체결가) 필드를 사용한다.
  • 현재가 <= stop_loss_price 조건 충족 시 손절 매도를 제출해야 한다.
  • 현재가 >= take_profit_price 조건 충족 시 익절 매도를 제출해야 한다.
  • 두 조건은 동일 polling 루프에서 평가한다.
  • 워치독 활성(만료되지 않은) 슬롯과 임계값 미설정(None) 슬롯은 polling 대상이 아니다.
  • KIS API 호출 상한은 워치독 만료 대상 슬롯 수 × (3600 / TREX_STOP_LOSS_POLL_INTERVAL)로 산정한다. 이 상한이 KIS 쿼터를 초과할 경우 polling 간격 조정 AC를 이 REQ의 Notes에 명시하고 REQ 단계에서 상한 경고를 구현한다.
  • 자동 매도 제출은 SlotService.sell()(REQ-036)을 사용한다.

Acceptance Criteria

  1. Given holding, 워치독 만료, stop_loss_price=Decimal("50000"), take_profit_price=None인 슬롯 S가 있고 KIS polling 결과 stck_prpr=49000이면, When 가격 체크가 수행되면, Then S에 대해 SlotService.sell()이 호출된다(손절 트리거).
  2. Given holding, 워치독 만료, stop_loss_price=None, take_profit_price=Decimal("80000")인 슬롯 S가 있고 KIS polling 결과 stck_prpr=81000이면, When 가격 체크가 수행되면, Then S에 대해 sell()이 호출된다(익절 트리거).
  3. Given holding, 워치독 만료, stop_loss_price=Decimal("50000"), take_profit_price=Decimal("80000")인 슬롯 S가 있고 stck_prpr=65000이면, When 가격 체크가 수행되면, Then sell()이 호출되지 않는다(두 조건 모두 미충족).
  4. Given holding, 워치독 활성인 슬롯 S가 있을 때, When 가격 polling이 수행되면, Then S에 대한 KIS API 호출이 발생하지 않는다(워치독 보호).
  5. Given stop_loss_price=None이고 take_profit_price=None인 슬롯 S가 있을 때, When polling이 수행되면, Then S는 polling 대상에서 제외된다.
  6. Given 이미 pending_sell 상태인 슬롯 S에 조건이 충족될 때, When 가격 체크가 수행되면, Then 중복 sell() 호출이 발생하지 않는다(REQ-036 idempotency).
  7. Given broker=kis 일 때, When 가격 polling을 수행하면, Then KIS 주식현재가 시세 endpoint(/uapi/domestic-stock/v1/quotations/inquire-price)를 tr_id FHKST01010100(실전/모의 공용)로 호출하고 output.stck_prpr 를 파싱한다. 실 KIS LIVE 호출이 rt_cd=0 + stck_prpr 를 반환함을 확인한다(구 TTTC8397R 는 rt_cd=1 "없는 서비스 코드" 로 거부됨).
  8. Given TREX_STOP_LOSS_POLL_INTERVAL=30이고 워치독 만료 대상 슬롯이 N개일 때, When 정상 동작 중이면, Then 1시간당 KIS API 호출 수가 N × 120회를 넘지 않는다(NFR-3 쿼터 산정).

Impacted Area

  • Docs:
    • docs/runtime-flows.md — stop-loss·take-profit 가격 체크 흐름 추가 (REQ-042 참조)
    • docs/interface-contract.md — 현재가 polling 어댑터 계약 명시 (REQ-042 참조)
  • Modules:
    • 신규 trex_core/adapters/broker/kis_price.py 또는 kis.py 확장 — TTTC8397R/VTTC8397R 현재가 polling, stck_prpr 파싱
    • trex_core/runtime/daemon.py — stop-loss·take-profit 가격 체크를 safety-sell worker에 통합
    • trex_core/domain/slot/service.py — stop-loss·take-profit 조건 평가 메서드(또는 worker 내 인라인)
  • Tests:
    • KIS 현재가 polling 어댑터 단위 테스트 — stck_prpr 파싱 확인, 실전/모의 분기 확인
    • 가격 체크 단위 테스트(mock polling) — 손절/익절/미충족/워치독 보호 시나리오

Notes

  • KIS 현재가 polling 어댑터는 기존 trex_core/adapters/broker/kis.py에 get_current_price(symbol) 메서드로 추가하거나, 별도 모듈로 분리한다. batch planning에서 결정한다.
  • paper broker 모의 환경에서는 stub 구현(set_current_price/get_current_price)으로 현재가를 반환한다(KIS 시세 호출 없음). 실 KIS(broker=kis) 는 FHKST01010100 시세 tr 사용.
  • KIS 쿼터 초과 방지: 워치독 만료 슬롯 수가 임계값을 넘으면 polling 간격 자동 조정 또는 경고 로그를 구현한다. 구체적인 쿼터 수치는 KIS API 문서 기준으로 batch 설계에서 확정한다.
  • TREX_STOP_LOSS_POLL_INTERVAL env var는 REQ-041 참조.

Change Log

CHG-20260607-01

  • Date: 2026-06-07
  • Author: Justin Ko

Change Summary

  • dcy-007 confirmed → REQ-038 초안 생성

Intent

  • stop-loss·take-profit KIS 가격 polling + 트리거(FR-2)를 독립 Integration REQ로 정규화

Acceptance Criteria Delta

  • Added: AC-1~8 전체

Impacted Area Delta

  • Docs: runtime-flows.md, interface-contract.md (REQ-042에서 처리)
  • Modules: kis 현재가 polling 어댑터(신규/확장), daemon.py, service.py
  • Tests: polling 어댑터 단위 + 가격 체크 시나리오 단위 (mock)

Delivery Trace Delta

  • Batches: none (미할당)
  • Releases: none

Revalidation Impact

  • Reverification Needed: no
  • Existing Implementation Invalidated: no
  • Status Recommendation: keep-current
  • Follow-up Action: suggest-batch-reqs 후 batch 배정

CHG-20260607-02

  • Date: 2026-06-07
  • Author: Justin Ko

Change Summary

  • Proposed → Approved (confirm-req)

Intent

  • 승인 게이트 통과: 필수 필드·AC·Impacted Area·Change Log 완비 확인. dcy-007(confirmed) 범위 및 결정 사항과 모순 없음.

Acceptance Criteria Delta

  • (변경 없음)

Impacted Area Delta

  • (변경 없음)

Delivery Trace Delta

  • Batches: none (미할당)
  • Releases: none

Revalidation Impact

  • Reverification Needed: no
  • Existing Implementation Invalidated: no
  • Status Recommendation: keep-current
  • Follow-up Action: suggest-batch-reqs 후 batch 배정

CHG-20260607-03

  • Date: 2026-06-07
  • Author: Justin Ko

Change Summary

  • Status Approved → Implemented (confirm-req-implemented, 근거 batch BAT-011 release-candidate).

Intent

  • BAT-011 verification.md 의 AC↔evidence(KIS get_current_price TTTC8397R/VTTC8397R·stck_prpr 파싱 + 손절/익절/미충족/워치독 보호/쿼터 산정/가격 미수신 skip)로 AC-1~8 충족 → 구현 완료 동기화.

Acceptance Criteria Delta

  • (변경 없음)

Impacted Area Delta

  • (변경 없음)

Delivery Trace Delta

  • Batches: BAT-011 (release-candidate)
  • Releases: none

Revalidation Impact

  • Reverification Needed: no
  • Existing Implementation Invalidated: no
  • Status Recommendation: keep-current (Implemented)
  • Follow-up Action: draft-release 로 BAT-011 배포 편성.

CHG-20260607-04

  • Date: 2026-06-07
  • Author: Justin Ko

Change Summary

  • 현재가 시세 tr_id 정정: TTTC8397R(실전)/VTTC8397R(모의) → FHKST01010100(주식현재가 시세, 실전/모의 공용). Status Implemented → Approved (AC-7 evidence 무효).

Intent

  • 배포 전 실 KIS LIVE 진단(읽기 전용 시세 호출)에서 구 tr_id 가 rt_cd=1 "없는 서비스 코드 입니다"(OPSQ0002) 로 거부됨을 확인. 이 경우 get_current_price 가 항상 None 을 반환 → stop-loss/take-profit 가 LIVE 에서 조용히 미발동. 표준 시세 tr FHKST01010100 는 rt_cd=0 + stck_prpr=329000(005930) 정상 수신. mock/샌드박스로는 잡히지 않는 결함이라 LIVE 검증으로 포착.

Acceptance Criteria Delta

  • Updated:
    • AC-7: 시세 endpoint/tr_id 를 FHKST01010100(실전/모의 공용)로 정정. 실 KIS LIVE rt_cd=0 + stck_prpr 수신 검증 추가.
  • Added:
    • 없음
  • Removed:
    • 없음 (TTTC8397R/VTTC8397R 분기 폐기)

Impacted Area Delta

  • Docs:
    • 없음 (REQ 본문 + 후속 baseline 은 verification 단계 갱신)
  • Modules:
    • trex_core/adapters/broker/kis.py (_tr_price → FHKST01010100, live/mock 분기 제거)
  • Tests:
    • tests/adapters/broker/test_kis_price.py (AC-7 tr_id 단언 정정)

Delivery Trace Delta

  • Batches: BAT-011 (release-candidate — AC-7 재구현/재검증)
  • Releases: REL-003 (confirmed — 본 정정 반영 후 재확인 필요)

Revalidation Impact

  • Reverification Needed: yes (AC-7 한정; AC-1~6/8 은 paper/단위 evidence 유효)
  • Existing Implementation Invalidated: yes (AC-7 — 구 tr_id 코드/테스트)
  • Status Recommendation: Implemented → Approved (AC-7 재검증 전까지)
  • Follow-up Action: kis.py 수정 + LIVE 시세 재검증 + 단위 정정 → confirm-req-implemented 로 Implemented 재전환 → REL-003 재확인.

Validation Plan

  • 실 KIS LIVE get_current_price('005930') → Decimal(약 329000) 반환 확인(읽기 전용).
  • test_kis_price.py AC-7: _tr_price() == FHKST01010100 단언 + stck_prpr 파싱.
  • 단위 전체 회귀 + ruff.

CHG-20260607-05

  • Date: 2026-06-07
  • Author: Justin Ko

Change Summary

  • Status Approved → Implemented (confirm-req-implemented, CHG-04 정정 재검증 완료).

Intent

  • CHG-04 의 tr_id 정정(FHKST01010100)을 구현·재검증: kis.py _tr_price() 수정, test_kis_price.py AC-7 정정(7 passed), 단위 전체 236 passed/ruff clean, 실 KIS LIVE get_current_price('005930')=Decimal('329000')(rt_cd=0) 확인. AC-7 evidence 복구 → 전체 AC 충족.

Acceptance Criteria Delta

  • (변경 없음)

Impacted Area Delta

  • (변경 없음)

Delivery Trace Delta

  • Batches: BAT-011 (release-candidate)
  • Releases: REL-003 (confirmed — 정정 반영 후 재확인)

Revalidation Impact

  • Reverification Needed: no
  • Existing Implementation Invalidated: no
  • Status Recommendation: keep-current (Implemented)
  • Follow-up Action: REL-003 재확인 후 배포.