콘텐츠로 이동

S314 — 테마 선정 → 종목 선정 → backtest (Q3 직접 검증)

작성: 2026-05-25 (Mon) 상위 명세: docs/planning/theme_stock_selection_logic.md (Q1~Q4 사고 체인) 선행: S313 3축 결합 backtest 결과 PM 지적 — "그냥 숫자 맞추기로 하면 안되고, 테마와 종목 선정하기로 들어가야돼" 결론 한 줄: 본 1시점(2026-04-06) 강상승장에서 "60d RS 상위 + 5d 둔화 = 빠질 / 5d 가속 = 갈" Q3 룰은 정반대로 작동 (D+30 spread IN-OUT = -33.27pp, leader 기준). 단 leader 추출(테마 내 4대 기준)은 spread 진폭을 키우는 도구적 가치는 확인.


1. PM 지적과 방향 전환

S313에서 한 작업: 81 종목을 평면에 깔고 z_quant × z_chart × z_theme_rs 결합 후 decile spread 측정 → 종목 선정 로직 부재. 이는 theme_stock_selection_logic.md §6 "하지 않는 것"의 1번(Q1~Q4 건너뛰고 종목 추천), 2번(분리 서술 후 연결 없이 종료) 위반.

S314는 위 문서대로 Q3(자금 이동: 어디서 → 어디로) → Q4(어떤 종목) 순서를 1시점 backtest에 그대로 적용.


2. 입력 + 산식

2-1. 진입 시점/Universe

  • t0 = 2026-04-06 (S312v2 EA_QoQ entry 동일)
  • forward D+5/10/20/30 KOSPI-adjusted alpha (S312v2와 동일 산식)
  • universe 81: EA_QoQ 가용 + ohlcv 보유
  • universe 81 밖 후보도 leader-judge에는 포함 (ohlcv 247종 전부), 단 forward alpha 측정은 81 한정

2-2. ats_main.json themes 필드 결함 발견 + 수정

  • 794 종목 중 17종이 themes 필드가 list가 아닌 공백 구분 string. 예: SK이노베이션 themes = '2차전지 2차전지(생산) 2차전지(전고체) ESS(전력저장장치) 전기차 냉각시스템(액침냉각) 폐배터리 정유 LNG 석유화학'
  • list(string)이 문자 단위로 iterate되어 가짜 단일 문자 테마 "2", "차", "(", ")", "전", "력" 등이 생성됨
  • S313에서 사용한 theme_rs 산출은 이 결함 영향 받음 (단일 문자 테마가 cover≥3을 통과해 RS 분포 오염)
  • 정규화 함수 _normalize_themes() 추가: string이면 split(), "—" 단독 토큰 제거
  • S313 산출물(data/backtest/theme_rs/stock_theme_rs_2026-04-06.parquet)은 결함 영향 일부 남아있음. 본 S314 산출(theme_state_*.parquet)은 수정 후 재산출.

2-3. Q3 룰 정의 (theme_stock_selection_logic.md)

상태 조건 Q3 매핑
HOT rs_60d ≥ +20pp AND rs_5d ≥ +2pp 강세 유지, 빠질 위험 있으나 신호 약
COOLING rs_60d ≥ +20pp AND rs_5d < +2pp 빠질 후보
RE_ACCEL -5pp ≤ rs_60d < +20pp AND (rs_5d/5 > rs_60d/60 AND rs_5d > 0) 갈 후보 (경로 B)
RECOVERY rs_60d < -5pp AND rs_5d > +2pp 갈 후보 (경로 C 낙폭과대 회복)
DEAD rs_60d < 0 AND rs_5d < 0 회피
NEUTRAL 위 5개 아닌 잔여 -

선정 규칙: - 빠질 후보 TOP-5: COOLING, rs_60d desc 상위 5 - 갈 후보 TOP-5: RE_ACCEL ∪ RECOVERY, rs_5d desc 상위 5

2-4. Q4 leader 추출 (테마 내 ranking)

sector/leader-judge 4대 기준 1시점 OHLCV 단독 재구현 (각 0~25, 총 0~100): | 기준 | 산식 | |---|---| | cum_return | 60일 누적 수익률 — 테마 내 percentile | | downside_resilience | 60일 down-day 평균 손실폭 (작을수록 좋음, percentile) | | turnover_concentration | 20일 평균 거래대금 — 테마 내 percentile | | reaction_speed | (ret_5d/5 - ret_60d/60) — 테마 내 percentile |

라벨: 1위 leader / 2~3위 sub_leader / 4위 이하 follower

원 leader-judge의 lead_lag_pattern / substance / fundamentals 보너스는 본 1시점 OHLCV 단독 측정 불가 → 제외.


3. 결과

3-1. 테마 상태 분포 (themes 정규화 후, 의미 있는 테마 81개 / classified 45개)

state n 대표 테마
HOT 3 광통신(+162pp) / 5G(+52pp) / 방위산업(+36pp)
COOLING 10 원전(+164pp) / 건설(+145pp) / 스페이스X(+66pp) / CXL(+46pp) / 유리기판(+37pp) / 2차전지(전고체)(+28pp) / 드론(+26pp) / 우주항공(+26pp) / 원자력발전소해체(+25pp) / 태양광(+20pp)
RE_ACCEL 7 ESS(+19pp) / 2차전지(생산)(+9pp) / 반도체 대표주(생산)(+7pp) / 정유(+4pp) / 석유화학(+4pp) / 변압기·전력기기(+2pp) / 냉각시스템(액침냉각)(-1pp)
RECOVERY 0 (조선/LNG선은 rs_5d +1.37pp로 +2pp 임계 미달 → NEUTRAL로 빠짐)
DEAD 7 AI챗봇(-40pp) 등
NEUTRAL 18 HBM, 반도체 장비, 2차전지(소재부품), 전기차 등

3-2. Q3 선정 (TOP-5 each)

빠질 (COOLING TOP 5): | 테마 | u81 멤버 | |---|---| | 원전 | 000720 현대건설 | | 건설 | 000720 현대건설, 047040 대우건설 | | 스페이스X | 373220 LG에너지솔루션 | | CXL | 005930 삼성전자, 000660 SK하이닉스 | | 유리기판 | 009150 삼성전기 |

갈 (RE_ACCEL TOP 5, rs_5d desc): | 테마 | u81 멤버 | |---|---| | 반도체 대표주(생산) | 005930 삼성전자, 000660 SK하이닉스, 000990 DB하이텍 | | 2차전지(생산) | 373220 LGES, 006400 삼성SDI, 096770 SK이노 | | 석유화학 | 096770 SK이노, 010950 S-Oil | | 정유 | 096770 SK이노, 010950 S-Oil | | ESS | 373220 LGES, 006400 삼성SDI, 267260 HD현대일렉트릭, 298040 효성중공업, 010120 LS ELECTRIC, 096770 SK이노, 066570 LG전자 |

3-3. Q4 leader 추출 (테마별 1위)

빠질 leader (u81 unique 3종): 000720 현대건설 / 005930 삼성전자 / 009150 삼성전기 - 미래에셋증권은 스페이스X leader지만 u81 밖 → 제외 - 005930은 빠질·갈 양쪽 leader (충돌)

갈 leader (u81 unique 3종): 005930 삼성전자 / 006400 삼성SDI / 010950 S-Oil

3-4. forward D+30 alpha (universe 81 baseline -11.73pp)

그룹 n α5 α10 α20 α30
A. 갈 leader (u81 unique) 3 -2.35 -4.82 -3.83 -11.45
B. 빠질 leader (u81 unique) 3 +7.73 +10.23 +12.15 +21.82
C. 갈 sub_leader 4 -1.90 +5.51 +12.88 +7.93
D. 빠질 sub_leader 3 +10.73 +18.54 +25.70 +15.77
E. 갈 전체 멤버 11 +0.49 +1.47 +15.19 +3.43
F. 빠질 전체 멤버 6 +9.23 +14.39 +18.93 +18.80
G. Universe 81 baseline 81 -0.22 -0.15 -4.77 -11.73

3-5. Q3 spread (IN - OUT)

α5 α10 α20 α30
leader -10.07 -15.05 -15.98 -33.27
sub_leader -12.64 -13.03 -12.82 -7.85
all_members -8.74 -12.92 -3.74 -15.36

4. 해석 + 사후 검증

4-1. Q3 가설 검증 (theme_stock_selection_logic.md §4 성공기준)

검증 항목 판정
"빠질 곳" 판단이 맞았는가 틀림. 빠질 leader α30 +21.82pp (baseline -11.73pp 대비 +33.55pp 초과 outperform) — 떨어지긴커녕 강세
"갈 곳" 판단이 맞았는가 틀림. 갈 leader α30 -11.45pp (baseline 거의 동일, KOSPI 못 따라감)
Q3 가설 부호 모든 horizon에서 반전. D+30 spread -33.27pp는 통계적으론 1시점 nominal이지만 방향성 명확

4-2. 왜 틀렸는가 (PM 문서 §4 "왜 틀렸는지 1줄 기록")

1줄 요약: 60d RS 상위 + 5d 둔화 = COOLING 룰은 시장 turning point에서만 작동. 본 1시점은 KOSPI 60d +20% 강상승장의 후반 가속 국면(forward 30d +32%) — 5d 일시 둔화는 호흡일 뿐이며 60d 강세 모멘텀이 계속 유효.

구체 근거: - 빠질 leader 현대건설(+99% 60d → forward +57%pp KOSPI 대비), 삼성전기(+72% 60d → forward +97%pp) 모두 추가 폭등 - 갈 leader 삼성SDI(2차전지 생산, +64% 60d), S-Oil(석유화학/정유, +39% 60d) 모두 forward 약세 (60d 강세였는데 5d 가속도 양수) - 즉 60d 모멘텀 자체가 forward 모멘텀의 강력한 예측자. "고점에서 빠진다"는 평균회귀 가정은 trend 시장에서 위배.

4-3. leader 추출 도구적 가치

그룹 분리 α30 IN/OUT 진폭
leader 단독 -11.45 / +21.82 (spread -33.27)
sub_leader +7.93 / +15.77 (-7.85)
all_members +3.43 / +18.80 (-15.36)

leader 단독이 spread 진폭 가장 큼 → 테마 내 leader 추출은 시장 신호를 압축한다. 이번엔 신호 방향이 가설과 반대였지만, 테마 선정이 맞을 때는 leader 추출이 진폭을 키우는 도구임을 확인.

4-4. ats_main 결함 영향 정리

  • S313 backtest 결과의 일부 RS 분포는 단일 문자 가짜 테마 오염 있었음
  • S314는 수정 후 재산출 → 의미 있는 한국 테마만 분류
  • 단 universe 81 중 24종 themes 결손 (시총 상위 다수) 은 여전히 매핑 불가 → 본 backtest universe 57로 implicit하게 좁아짐. 보고된 그룹 G(universe 81 baseline)는 81 전체.

4-5. 충돌 종목 처리

  • 005930 삼성전자: 갈 leader ∧ 빠질 leader 동시. best_state 우선순위(RE_ACCEL > COOLING)대로 "갈"이지만 본 코드는 양쪽에 carry → 결과 표에서 양쪽 모두에 +10.66pp 기여.
  • 000660 SK하이닉스: 갈 sub_leader ∧ 빠질 sub_leader.
  • 373220 LGES: 갈 leader/sub_leader ∧ 빠질 leader.
  • spread 부호엔 영향 없음(반대 방향이 압도적), 단 절대값 측정엔 noise.

5. 다음 세션 옵션 (PM 결정 대기)

본 1시점 + 강상승장 1회로 Q3 룰 폐기/수정 결론 단정 금지. PM 문서 §5 "성공할 때까지 반복" — 다른 시점/regime에서 재측정 필요.

A. 시점 확장 (regime별 1~2 시점씩)

  • 강상승 후반(2026-04-06, 본 시점)
  • 강상승 초입 (2026-01-Q? 자료 가용 시)
  • 횡보/조정 (KOSPI 5d <0 시점)
  • 약세 (있다면)
  • 각 regime에서 Q3 룰 spread 측정 → regime conditional rule 도출

B. Q3 룰 변형 후보 (1시점 결과로는 단일 시점이라 단정 어려움)

  • 반전: 5d 가속 = 빠질 / 5d 둔화 = 갈? — Q3 가설과 정반대지만 본 데이터 맞음. 다른 시점에서 반복되면 룰 변경.
  • 임계 강화: rs_60d 상위 + rs_5d < 0 (둔화 아닌 음전환)으로 COOLING 좁히기
  • 종목 단위 보강: 테마 level 60d 둔화 + 테마 leader 종목 단위에서 거래대금 감소 동반 시에만 COOLING 인정 (현재는 ohlcv 1시점 누적이라 거래대금 변동 미사용)

C. 본 결과를 그대로 기록만 하고 leader 추출 도구 부분만 운영 진입

  • "테마 선정이 외부(EVENING UNIT 7 catalyst chain)에서 들어왔다고 가정하고, 그 테마 내에서 4대 기준으로 leader 추출"하는 부품은 backtest 1시점이지만 spread 진폭 확인 — 운영에서 의미 있을 수 있음.

D. ats_main 24종 결손 보강

  • universe 81 중 시총 상위 다수가 theme 매핑 없어 backtest 그룹 진입 못함. 별도 매핑 백필 (정공법) 또는 leader-judge가 industry/sector 차원으로 fallback (간이).

6. 산출물

  • 코드 (신규):
  • scripts/quant/themes/theme_state_classifier.py — 5/20/60d RS + 상태 분류
  • scripts/quant/themes/theme_selection.py — Q3 빠질/갈 TOP-K 선정
  • scripts/quant/themes/theme_leader_select.py — 4대 기준 leader 추출
  • scripts/backtest/e3_theme_to_leader.py — 그룹별 forward alpha
  • 코드 (수정):
  • scripts/quant/themes/theme_rs.py_normalize_themes() 추가 (string 결함 수정)
  • 데이터:
  • data/backtest/theme_rs/theme_state_2026-04-06.parquet
  • data/backtest/theme_rs/stock_theme_state_2026-04-06.parquet
  • data/backtest/theme_rs/selected_themes_2026-04-06.json
  • data/backtest/theme_rs/theme_leaders_2026-04-06.json
  • data/backtest/theme_rs/_theme_state_readable.txt, _selected_themes_readable.txt, _theme_leaders_readable.txt
  • data/backtest/e3_theme_to_leader/results.json
  • 문서: 본 파일

7. PM 질문 직답

질문
"테마와 종목 선정하기로 들어가야돼" 라는 지적, 적용했나? . Q3(테마 상태 분류 → 빠질/갈 TOP-5 선정) → Q4(테마 내 leader 4대 기준 추출) → forward alpha 검증 순서로 진행. S313 평면 결합 폐기.
Q3 룰이 작동하나? 본 1시점은 정반대로 작동 (D+30 spread leader -33.27pp). 1시점 결과는 단정 불가 — 다른 regime에서 재측정 필요.
leader 추출은 의미 있나? 도구적으로는 예. leader 단독이 sub/all보다 spread 진폭 최대. 단 테마 선정이 맞을 때 한정.
ats_main 결함은 어디까지 영향? S313 일부 오염. S314 수정 후 81 의미 있는 테마 분류. universe 81 중 24종 theme 매핑 결손은 별개 과제.
다음 뭘 해야 하나? A(시점 확장 regime별 측정) 또는 B(룰 변형) 또는 C(leader 추출 부품만 운영 진입). PM 결정 대기.