Files
trex-core/docs/releases/rel-003_20260607_core-autonomous-safety-sell.md
T
genichinandClaude Opus 4.8 6fda381f62 docs(release): REL-003 — LIVE SL/TP e2e 검증 + 영속 거부 재시도 백오프 환류
실 KIS LIVE SL/TP e2e: 실 시세(FHKST01010100, 329000) → stop_loss 트리거
→ 실 KIS 매도 제출 → "장운영일자가 주문일과 상이합니다"(휴장) 거부 → 안전 롤백
end-to-end 확인. forced_close/장마감/update_thresholds 는 paper daemon e2e 통과.

발견(Change Request Input 기록): 영속 거부 상황에서 safety-sell 이 poll
interval 마다 거부 주문을 무한 재제출 → 재시도 백오프/쿨다운 후속 후보.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 10:43:36 +09:00

8.2 KiB

REL-003: core 자율 안전 매도 (watchdog + 가격 임계값 + forced_close / stop-loss·take-profit / 장 마감 청산 + update_thresholds RPC)

  • Status: confirmed
  • Profile: app-service
  • Included Batch: BAT-010, BAT-011

Scope

  • Included:
    • BAT-010 (REQ-034, REQ-035, REQ-036, REQ-041): safety-sell 기반 인프라 — per-slot 워치독 store(snapshot RPC 가 holding 슬롯 last_seen_at 갱신), 슬롯 stop_loss_price/take_profit_price 도메인 필드 + 004_add_price_thresholds.sql additive 마이그레이션, SlotService.sell() 자율 매도 내부 경로(idempotent), safety-sell env 5종 파싱.
    • BAT-011 (REQ-037, REQ-038, REQ-039, REQ-040, REQ-042): safety-sell 트리거 레이어 — trex-safety-sell worker(7번째 스레드), forced_close_at 만기 자동 매도(REQ-037), stop-loss·take-profit KIS 현재가 polling(TTTC8397R/VTTC8397R, stck_prpr) + 트리거(REQ-038), 장 마감 강제 청산(TREX_MARKET_CLOSE_LIQUIDATION_TIME, REQ-039), update_thresholds intent RPC 액션(REQ-040), baseline 3문서 정합(REQ-042).
  • Excluded:
    • REQ-030 AC-2/AC-3 (옵션 D): portfolio-hub#8 배포 대기로 status Approved 유지 — 본 release 범위 밖(REL-001 Excluded 와 동일 이월).
    • 가격 임계값 논리 유효성 검증(take_profit > stop_loss 등): dcy-007/REQ-035 범위 밖.
    • KIS 쿼터 초과 시 polling 간격 동적 조정: 본 release 는 상한 산정 + 경고 로그까지(REQ-038 AC-8). 동적 조정은 후속 후보.
    • 전략 모듈(orb-v1) 자체: 별도 Discovery/배포.

Rollout Plan

  1. 사전 점검: PostgreSQL / RabbitMQ 도달성 확인. .env 의 broker 설정(TREX_BROKER, kis 시 TREX_KIS_* + TREX_KIS_ALLOW_LIVE) 확인. safety-sell env(아래)는 모두 optional — 미설정 시 기본값.
  2. DB 마이그레이션 적용: 004_add_price_thresholds.sql(additive, ADD COLUMN IF NOT EXISTS). 데몬 boot apply_migrations 가 자동 적용하나 사전 적용 권장.
  3. 배포 대상 commit SHA(a30efa8 이상) 설치 후 데몬 재기동 → 7 워커 스레드(execution / ledger / intent-rpc / snapshot-rpc / pause-rpc / snapshot-scheduler / trex-safety-sell) 기동 확인.
  4. safety-sell 튜닝 env(전부 optional):
    • TREX_WATCHDOG_TIMEOUT(기본 120s), TREX_WATCHDOG_GRACE_PERIOD(기본 60s) — 워치독 만료/부팅 grace.
    • TREX_FORCED_CLOSE_CHECK_INTERVAL(기본 60s), TREX_STOP_LOSS_POLL_INTERVAL(기본 30s) — worker 캐던스.
    • TREX_MARKET_CLOSE_LIQUIDATION_TIME(HH:MM KST, 기본 미설정 = 장 마감 청산 OFF).
  5. 운영 안전 주의(중요): broker=kis LIVE 에서 safety-sell worker 는 실제 매도 주문을 낸다.
    • forced_close / stop-loss·take-profit 는 워치독 만료(전략 모듈이 snapshot RPC 폴링을 멈춘) 슬롯에만 작동한다 → TREX_WATCHDOG_TIMEOUT 을 전략 모듈의 정상 snapshot 폴링 주기보다 충분히 크게 설정해 정상 운용 슬롯 오발동을 방지할 것.
    • 장 마감 청산은 설정 시 워치독 무관 전체 holding 을 매도하므로 의도적으로만 설정.
    • stop-loss·take-profit·forced_close 는 해당 슬롯에 임계값/만기가 설정된 경우에만 작동(매수 intent 또는 update_thresholds 로 주입). 미설정 슬롯에는 무영향.

Rollback Plan

  • 코드 롤백: BAT-010+011 단일 커밋(a30efa8) revert → safety-sell worker 제거(데몬 6 스레드로 회귀). 타 batch 비의존.
  • 데이터: 004_add_price_thresholds.sql 는 additive(컬럼 추가)라 데이터 파괴 없음. 롤백 시 컬럼 보존(드롭 불필요).
  • 즉시 무력화(코드 롤백 없이): safety-sell 은 임계값/만기/장 마감 env 가 설정된 경우에만 매도한다. 임계값을 주입하지 않고 TREX_MARKET_CLOSE_LIQUIDATION_TIME 을 비우면 worker 는 사실상 inert. 긴급 시 데몬 정지.
  • 트리거 조건 예: 정상 운용 슬롯 오발동(워치독 timeout 과소 설정), KIS 현재가 polling 쿼터 초과, 예기치 않은 청산.

Verification Checklist

  • 배포 전:
    • 단위 pytest -q --deselect ...::test_sandbox_token_and_submit → 236 passed / 23 skipped.
    • 인프라 게이트(PG+RabbitMQ) TREX_RABBITMQ_TEST_URL=... TREX_POSTGRESQL_TEST_DSN=... pytest -q → 259 passed(마이그레이션 001~004 적용 + PG repo round-trip 포함; BAT-010 R-2 해소).
    • ruff check trex_core tests → All checks passed.
    • 실데몬 e2e(paper): RabbitMQ 매수(forced_close_at = 매수+60s) → 워치독 만료 → holding→pending_sell(forced_close_at/trex-safety-sell)→closed 관찰(PASS).
    • 실 KIS LIVE 시세 검증(읽기 전용): get_current_price('005930')=Decimal('329000')(rt_cd=0, tr FHKST01010100). 배포 전 진단에서 REQ-038 구 tr_id(TTTC8397R) 결함 발견 → change-req REQ-038 CHG-04/05 로 정정·재검증 완료(REL-003 re-confirm 근거).
  • 배포 후:
    • 데몬 기동 + 7 워커 스레드(trex-safety-sell 포함) + 큐/exchange/DLQ 선언 확인.
    • 마이그레이션 004 적용 확인(daily_slot 에 stop_loss_price/take_profit_price 컬럼 존재).
    • update_thresholds intent RPC: holding 슬롯 임계값 갱신 + 워치독 리셋 + non-holding ignored 응답.
    • 차기 거래일 실 KIS 관찰: stop-loss·take-profit·forced_close·장 마감 트리거 중 최소 1건 실 체결까지 확인(휴장/시장 상황 의존).

Release Execution Evidence

  • Release Status Transition Target: released

Deployment Facts

  • Executed At:
    • <배포 시작 시각>
  • Completed At:
    • <배포 완료 시각>
  • Environment:
    • <배포 대상 환경>
  • Operator:
    • <배포 수행자>
  • Revision or Artifact:
    • <커밋 SHA 또는 배포 artifact 식별자 (≥ a30efa8)>
  • Commands or Procedure:
    • <실행 명령 또는 배포 절차 요약>

Profile-Specific Checks

  • app-service:
    • Health Endpoint:
      • <HTTP health 없음(RabbitMQ transport) → 큐 declare readiness + 7 스레드 기동 확인>
    • Startup Log Fields:
      • <app/event/command/run_id + trex-safety-sell 스레드 기동 로그>
    • Request Log Fields:
      • <update_thresholds RPC correlation_id 확인>
    • Smoke or Manual Verification:
      • <마이그레이션 004 적용 + update_thresholds RPC + (차기 거래일) 실 KIS 트리거 관찰>

Rollback Outcome

  • Rollback Required:
    • <yes 또는 no>
  • Rollback Trigger:
    • <발생 시 원인, 없으면 none>
  • Rollback Action:
    • <수행한 조치, 없으면 none>

Release Decision Evidence

  • Released Decision:
    • <released 전환 여부>
  • Rationale:
    • <released 전환 판단 근거>
  • Recorded By:
    • <기록자>
  • Recorded At:
    • <기록 시각>

Feedback Handoff

  • Observation Summary:
    • (배포 전, 2026-06-07) 실데몬 paper e2e — RabbitMQ 매수(forced_close_at +60s) → 워치독 자연 만료 → trex-safety-sell 가 holding→pending_sell(forced_close_at) 트리거 → 집행 루프 pending_sell→closed. 단위 236 + 인프라 게이트 259 passed, ruff clean.
    • (배포 전, 2026-06-07) 실 KIS LIVE 시세 검증에서 REQ-038 tr_id 결함 포착 — 구 TTTC8397R 가 "없는 서비스 코드"(rt_cd=1)로 LIVE 손절/익절 silent 미발동. FHKST01010100 로 정정 후 get_current_price=329000 정상. mock/샌드박스로는 못 잡는 결함을 배포 전 LIVE 검증으로 포착(테스트 가치 입증).
  • Discovery Input:
    • <후속 discovery 후보>
  • REQ Input:
    • <후속 req 후보>
  • Change Request Input:
    • KIS 현재가 polling 쿼터 동적 조정(REQ-038 후속) — 워치독 만료 슬롯 급증 시 polling 간격 자동 확대.
    • 가격 임계값 논리 유효성 검증(take_profit > stop_loss 등) — 신규 후보.
    • safety-sell 영속 거부 시 재시도 백오프/쿨다운(신규, 우선순위 ↑): 2026-06-07 실 KIS LIVE SL/TP e2e 에서 매도가 영속적으로 거부될 때(장운영일자가 주문일과 상이합니다, 휴장) safety-sell worker 가 poll interval(5s)마다 거부 주문을 무한 재제출함(slot 이 holding 으로 롤백 → 다음 tick 재트리거). 휴장/잔고부족/규제 등 지속 거부 상황에서 실 KIS 주문 spam + 쿼터 소모 위험. 대응 후보: 슬롯별 재시도 백오프, 거부 사유별 쿨다운, 또는 동일 사유 N회 후 일시 중단 + 경고.