콘텐츠로 이동

S346 작업 계획 — D7 선정 로직 재설계 (받침 축 완비 + rank aggregation)

작성: 2026-06-03 (Wed) — S345 말미 PM 지시로 다음 세션 인계 상태: 📋 설계 확정, 구현 대기 (S346 시작점)


0. 배경 — 왜 재설계하나 (PM 지적 누적)

S345에서 D7 score를 "차트게이트 + RS 가점 ×2.5"로 바꿨더니 RS 편중이 생김. 6/02 selected = SKAI(357880): RS 1등·RS과거 1등·수급OF 1등이지만 거래대금 12등·펀더 13등(꼴찌)·재료 11등 = 한쪽으로 극단 쏠린 종목인데 가중치 합산(RS×2.5)이 약점을 덮어 1등이 됨.

PM 선정 논리 (정본):

차트상 갈 만한 자리(전제)인가 → 그렇다면 그게 받쳐지는가: ① 시장상황 ② 재료 ③ 수급(실제 거래대금) ④ 펀더멘탈 ⑤ 섹터 자금유입

현재 시스템의 받침 반영도 (코드 확인, score_compose.py): | 받침 | 현재 | 문제 | |---|---|---| | 차트 갈자리(전제) | chart_verdict + D2 게이트 | ✅ OK | | 시장상황(D1) | d1_macro는 D7 input에 있으나 게이트로만(NEGATIVE면 전체 중단), 종목 score 미반영 | ⚠️ 종목 차별 안 함 | | 수급(실제 거래대금) | ofm_cvd_z(30분봉 방향만) | ❌ 거래대금 절대량/증가 축 없음 | | 펀더(ea) | ea_z ×0.5 | ⚠️ 눌림 | | 재료(catalyst) | catalyst_z ×0.5 | ⚠️ 눌림 | | 섹터 자금유입 | data/sector_flow/{date}.json 존재하나 D7 미사용 | ❌ 통째 누락 |

→ 받침 2개(섹터·실거래대금) 누락 + 1개(시장) 게이트로만 + 2개(펀더·재료) 눌림 → 결국 RS·차트만 남아 편중.


1. 설계 방향 (PM 승인)

(A) 누락 축 추가

  1. 실제 거래대금 축 — market_top amount_억(절대량) + 5d/20d 증가율(유입 가속). 소스: data/market_top/{YYYYMMDD}.json top_amount (S345에서 200행으로 확장됨). ofm(방향)과 별개 축. "돈이 실제로 얼마나·더 들어오는가".
  2. 섹터 자금유입 축 — 종목의 primary_theme/섹터가 sector_flow에서 LEADING/유입 중인가. 소스: data/sector_flow/{YYYYMMDD}.json (S343 백필됨). D1 관찰5(섹터 도착)와 정합.
  3. 시장상황을 종목 차별 축으로 — D1 LEADING 섹터 ∈ 종목 테마면 가점. 현재 d1_macro는 게이트로만 → 종목별 "시장 자금 방향과 일치하는가"로 활용.

(B) 가중치 합산 → rank aggregation (PM "가중치 임의성 제거")

  • 각 축에서 종목 순위(rank) 매기고 순위 합으로 종합 (Borda count).
  • 가중치(2.5/0.5) 불필요 → 가중치에 따라 순위 흔들리는 문제 제거.
  • 한 축만 튀어도 못 이김(SKAI 6등 강등 확인) = 균형 우대.

(C) 차트 게이트 유지 (전제)

  • D2 verdict POSITIVE만 rank aggregation 진입. "차트 갈자리"가 자격 조건.

2. rank aggregation 시산 결과 (6/02, 비용0 검증 완료)

게이트 통과 13종, 순위합 낮을수록 좋음:

종목 순위합 RS RS과거 거래대금 수급OF 펀더 재료
삼성전자 25 5 6 1 7 2 4
두산로보틱스 27 6 7 2 6 3 3
삼성생명 35 4 8 5 8 8 2
제주반도체 35 3 3 9 4 9 7
엔씨소프트 36 9 11 6 3 1 6
SKAI 39(6등) 1 1 12 1 13 11
  • SKAI 1등→6등 (약점 3축 반영). 삼성전자·두산로보(전 축 고르게 상위) 1·2등.
  • ※ 이 시산은 섹터·시장 축 미포함(아직 미구현). 추가 후 재산정 필요.

3. 구현 WBS (S346)

M1. 거래대금 축

  • [ ] build_d7_input 또는 신규 indicator: market_top에서 amount_억 + amt5/amt20 증가율 산출.
  • [ ] D7CandidateRow raw_metrics에 amount/amount_accel 추가.
  • [ ] 결손 처리: market_top 200위 밖 종목(SKAI 같은 중소형 일부) → 거래대금 작음으로 실측 또는 FDR Close×Volume 폴백(s303 OHLCV 98종 한계 → universe 전체 일봉 필요할 수 있음, 데이터 점검).

M2. 섹터 자금유입 축

  • [ ] sector_flow JSON 로드 → 종목 primary_theme → 섹터 status(LEADING/STRONG/...) + 유입 강도 매핑.
  • [ ] 테마명 ↔ sector_flow 섹터명 매핑 테이블 점검(ats_main theme vs sector_series theme 명칭 정합).
  • [ ] raw_metrics에 sector_inflow 추가.

M3. 시장상황 종목 차별

  • [ ] D1 envelope의 LEADING 섹터(자금 도착) 리스트 → 종목 테마가 거기 속하면 가점/순위 반영.
  • [ ] (게이트 역할은 유지) + 종목 차별 축 신설.

M4. rank aggregation 엔진

  • [ ] score_compose 재작성: 가중치 합산 → 축별 rank → 순위 합. 차트 게이트 전제 유지.
  • [ ] 결손 축 처리 정책 결정 (★ PM 논의 필요):
    • SKAI 펀더 UNKNOWN(EA panel 없음)을 최하위로? 중간으로? 제외(그 축 빼고 평균)?
    • S345 원칙 "정보 부재 ≠ 나쁜 신호"와 충돌 → 최하위 페널티는 그 원칙 위반.
    • 후보: (a) 결손축 제외하고 가용축만 순위평균 (b) 결손=중간순위 (c) 결손=최하위(현 시산).
    • 시산: 방식별 top 비교 후 PM 결정.
  • [ ] D7CandidateRow에 per-axis rank + 순위합 보존(리포트 인용).

M5. 리포트 반영

  • [ ] 선정 결론·한줄요약을 rank 기반으로(각 축 몇 등인지 표시 = "왜 이 종목"이 투명).
  • [ ] 6/02 재스코어로 selected 변화 검증(LLM 0, envelope 재사용).

M6. EA panel 확장 (갭1, 병행)

  • [ ] selected가 중소형(EA panel 196종 밖)이면 펀더 결손 구조적 → discover universe(거래대금 200종)로 EA panel DART 재백필. MCP 비용. SKAI 펀더가 안 채워지는 근본 원인.

4. 미결 — PM 결정 대기 (S346 시작 시)

  1. 결손 축 처리 (M4) — 최하위/중간/제외 중. "정보 부재 ≠ 나쁜 신호"와의 정합.
  2. 거래대금 결손 폴백 (M1) — market_top 200위 밖 종목 거래대금 어떻게 구할지(FDR? universe 일봉 백필?).
  3. 축 개수/구성 확정 — RS·RS과거를 1축으로 합칠지(현재 2축이라 RS 비중 2배), 차트를 rank 축에 넣을지 (게이트만? 축도?).
  4. EA panel 확장 범위/비용 (M6).

5. S345 완료분 (이번 세션, 이어받기용)

  • 갭 진단(커버리지/라이브fetch) / 30분봉 271종 6/02 갱신 / 거래대금 풀 100→200 / D7 차트게이트+주도주 가점+rs_high(★이번 재설계로 가중치 부분은 대체될 예정, 게이트·rs_high는 유지) / 병렬화(8.5h→~1.3h, --parallel) / 리포트 수정(truncate·옛문구·재료Dnews우선·종목명·한줄요약).
  • 주의: S346 rank aggregation은 S345의 "RS×2.5 가중치 합산"을 대체함. 게이트·rs_high 지표·병렬· 리포트수정·풀200은 유지. score_compose의 가중치 합산부만 교체.
  • work_log: docs/work_logs/2026-06-03_S345_coverage_gap_diagnosis.md