fix: 스윙 자동편입 차단 + DT 처리량 복구 + ATR/양봉 세션 경계 + DLQ 안전
사용자 요구 "스윙으로 편입하는 건 없어야 해" — 시스템이 매수하지 않은 KIS
계좌 잔고가 strategy_type='swing' 이 되는 경로를 전부 닫았다. 2026-09-30
09:26 에 유한양행 8주가 -6.49%/-40,000원 손절된 것이 직접 계기다.
## 스윙 자동편입 차단
- 강등 허용(swing→external). 기존엔 승격만 가능해 유입 잔고가 영구히
자동 손절 대상이었다. 3중 방어로 정상 포지션 강등을 막는다:
system_buy_registry(주문 즉시 인메모리) / 연속2회+120초 / db_worker 큐 적체 보류
※ 레이스는 이론이 아니다 — _verify_and_sync_execution 이 매수 직후
_delayed_sync_portfolio(0) 을 지연 0초로 부른다
- 수량 인식 분류(_classify_holding_strategy_type_v2):
_sys<=0<qty → external / 0<_sys<qty AND _sys==_dt_held → external
== 을 쓴 이유: 과소·과대 어느 쪽으로 틀려도 swing(관리 유지)으로 실패한다
- _system_qty 를 과대 집계 쪽으로 편향 — 오판이 안전한 방향으로 나게
- external 행에 스윙 추가매수 차단(혼재 발생 자체를 봉쇄, 청산은 통과)
- 근거를 두 벌로 분리: 신규태깅·강등방어는 registry 포함("있다고 보는 게 안전"),
승격·ActiveTrade 교정은 durable("없다고 보는 게 안전"). 안전 방향이 반대다
- 정합 루프가 external/혼재 행을 교정하지 않게(전제 "active 1행 = 전량 대표"를
직접 검사). 미교정 시 ActiveTrade 가 부풀어 스윙 청산이 유입분까지 판다(§3.5)
- status 허용목록 → 거부목록(FAILED 만 제외). 진짜 구멍은 FILLED 가 아니라
PENDING 이었다(체결확인 실패 시 영구 PENDING, 주식은 보유 중)
- SELL 중복제거 키에 nullif+trim — order_id 는 NULL 이 아니라 '' 로 저장된다
(build_kis_order_id 가 미발견 시 "" 반환). coalesce 만으로는 그룹이 붕괴해
SELL 이 과소 집계되고 유입 행이 영구히 swing 이 된다
## DT 처리량
- 감시종목 20 → 30 (DAY_TRADE_WATCHLIST_SIZE, 예산 상한 32에서 마진)
- 선조회 동시성 4→8, per-stock 45초, 단계 데드라인 120초 신설
(120 < 150 _SCAN_TIME_BUDGET < 180 _guard). 오후는 종목당 32초가
타임아웃 20초를 넘겨 4~7종목만 스캔되던 포화 상태였다 — 약 9배 복구
- 리스크 노출 불변: 동시 5종목·종목당 6%·DT 30% 무변경. 기회만 증가
## 세션 경계 (ATR·양봉)
- _atr() 이 내부에서 세션을 끊는다. 워밍업 시계열의 당일 첫 봉 TR =
오버나이트 갭이라 갭 3%에서 ATR 1.50배, 10%에서 2.75배 부풀었고
클램프 없는 target=현재가+1.5×ATR 을 직접 왜곡했다
→ 진입 ATR == 청산 트레일링 ATR 보장
※ 부작용 승인됨: 09:30~10:10 은 ATR 부재로 폴백 -3.5% 가 실효 손절폭
- 양봉 판정이 형성 중 버킷을 보던 것 → 마지막 완성봉(거래량 게이트와 같은 봉)
- 1.5R 하한 보장(두 분기). risk=max(1.5×ATR,2%) 라 저변동 종목은
R:R 0.21 까지 떨어졌다 — §7 "1.5R 분할" 규약 복귀, RSI_BB 와 동일
## DLQ 안전
- replay_dlq 나이 제한: 상태 2시간+같은날짜 / 기록 24시간 / close 는
충돌판정만(7일). "닫아라"는 지시는 시간이 지나도 거짓이 되지 않는다 —
격리하면 반대로 유령 active 행이 남는다(§8.4.1 129개와 같은 형태)
- 상태 충돌 확인(유령 생성 위험 시 expired/ 격리, 삭제 안 함)
- DB 장애 시 단락 — 없으면 500파일 × 접속타임아웃만큼 기동이 정지한다
## 진단·테스트
- 진입 reason 에 [진단 ATR=…, 갭=…], 탈락 후보 RSI·갭 집계 로그(하루 ~60줄)
- 잔고조회 실패 debug→warning (available_cash=0 → 모든 진입 조용히 차단)
- 벽시계 의존 테스트 재발 방지: autouse 가드(시각 미고정 시 AssertionError)
+ 호출부 전수 테스트
- 소스 문자열 매칭 단언을 동작 검증으로 전환(값·분기 판정 한정)
테스트 848 → 865 passed / 0 failed. 전략 임계값 변경 0건. alembic 불필요.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -274,6 +274,25 @@ class Settings(BaseSettings):
|
||||
# ═════════════════════════════════════════════════════════════════════════════
|
||||
DAY_TRADE_ENABLED: bool = True # 데이트레이딩 활성화
|
||||
DAY_TRADE_MAX_POSITIONS: int = 5 # 동시 최대 종목 수 (8→5, 2026-09-23 30% 배분: 5×6%=30%)
|
||||
# 감시종목 수 (populate_daytrading_watchlist 의 상한). 20→30, 2026-09-30.
|
||||
# 용도: ORB 돌파 후보 풀 확대 — 진입 임계값을 낮추지 않고 표본만 늘린다.
|
||||
# ⚠️ 리스크 노출과 무관하다: 동시 보유는 DAY_TRADE_MAX_POSITIONS(5), 종목당 예산은
|
||||
# DAY_TRADE_MAX_CAPITAL_RATIO(6%), DT 합산은 DAY_TRADE_MAX_RATIO_DT(30%) 가 각각
|
||||
# 독립적으로 상한을 건다. 늘어나는 것은 기회(스캔 후보)뿐이다.
|
||||
# 상한 근거(2026-09-30 산정, daytrading/entry_service 스캔 예산):
|
||||
# 선조회 wall = 종목수 × 분봉 페이지수 × 페이지비용 ÷ _SCAN_PREFETCH_CONCURRENCY(8)
|
||||
# - 페이지비용 3.2초 = 운영 실측 요청 3.0초(monitoring/api-stats avg_duration,
|
||||
# 재시도 포함) + in-loop sleep 0.2초(API_MIN_REQUEST_INTERVAL+0.05)
|
||||
# - 페이지수는 시간대 비례(당일 1분봉÷30): 09:30 4장 / 12:00 6장 / 14:00 10장 / 15:00 12장
|
||||
# - 예산 = _SCAN_PREFETCH_TOTAL_BUDGET(120초, 선조회 단계 데드라인)
|
||||
# ⇒ 14:00 기준 상한 = 120×8/(10×3.2) = **30종목** (오전 기준으로는 60종목)
|
||||
# 15:00 직전(12장)에는 30종목이 144초를 필요로 해 약 17% 가 잘리지만, 라운드로빈
|
||||
# 오프셋이 다음 사이클에 이어받으므로 특정 종목이 영구히 누락되지는 않는다.
|
||||
# 진입 마감이 15:00·EOD 청산이 15:20 이라 마지막 1시간의 부분 커버리지는 감수한다.
|
||||
# ORB 수집(09:00~09:29)은 종목당 1페이지·0.3초 간격이라 상한이 수백 종목으로 훨씬 느슨하다.
|
||||
# 후보 공급 측 제약: 운영 실측 당일 분석 종목이 53개뿐이다(2026-09-30) —
|
||||
# 40~50 으로 올리면 사실상 전량 편입이 되어 점수 기반 선별이 사라진다.
|
||||
DAY_TRADE_WATCHLIST_SIZE: int = 30
|
||||
DAY_TRADE_CAPITAL_RATIO: float = 0.30 # 전체 자본 대비 최대 30% (0.50→0.30, 2026-09-23 스윙 70%)
|
||||
DAY_TRADE_PER_STOCK_RATIO: float = 0.06 # ⚠️ 소비자 0건 — 실효 없음(2026-09-28 확인).
|
||||
# DT 종목당 한도의 정본은 아래 DAY_TRADE_MAX_CAPITAL_RATIO 다. 이 키는 strategy_configs
|
||||
|
||||
Reference in New Issue
Block a user