소부장 투자주기 검증

종목 선정 → 진입 → 방어·청산을 순차 검증합니다. 과거를 재검토한 결과와 앞으로 누적할 관측 기록을 구분하며, 수익을 보장하거나 자동 주문하지 않습니다.

소부장 관찰 화면

현재 결론 · 전체 실험 요약

# 반도체 소부장 투자 연구 — 검증 진행 중

2026-09-09 갱신. 현재는 관찰·연구 단계이며 자동주문이나 수익 보장 서비스가 아닙니다.

## 교정 후 잠정 결론

**현재까지는 실전 매수 규칙의 우위가 입증되지 않았습니다.** 평균 수익률이 양수인 조합은 있지만 신뢰구간이 넓고, 진입 방법을 바꾼 개선 효과도 확정하기 어렵습니다. 검증 완료 신호로 자동 승격하지 않습니다.

거래일 2,859개를 사용해 재계산했습니다. 평가 구간은 2025-11-04~2026-08-26이며, 훈련 자료는 그 이전부터 사용합니다. 최근 6개월만의 결과와 같지 않습니다. 현재 구성종목 121개·14분류의 회복 후보 243건과 수축돌파 후보 258건을 24개 조건으로 비교한 것이므로, 결과 행 6,012개를 서로 독립적인 6,012번의 투자로 보아서는 안 됩니다.

두 후보 유형 사이에도 같은 종목·날짜 75건이 겹칩니다. 실제 서로 다른 종목·날짜는 426개, 신호 발생 날짜는 95일입니다. 조건을 더 붙인다고 독립적인 과거 사례가 늘어나는 것은 아닙니다.

아래 수치는 왕복 비용 0.30%를 반영한 **후보 1건당 평균 기회손익**입니다. 미체결·진입 보류는 0, 결과 미확인은 결측으로 구분합니다. 계좌 전체 수익률이나 연환산 수익률이 아닙니다.

| 조건 | 보유 | 후보 / 체결 | 평균 기회손익 | 95% 구간 |
|---|---:|---:|---:|---:|
| 강한 테마 조정 후 회복 · 다음 시가 한도 진입 | 3일 | 243 / 229 | +0.70% | -1.64% ~ +2.67% |
| 동일 | 5일 | 243 / 229 | +1.18% | -2.62% ~ +4.44% |
| 동일 | 10일 | 243 / 229 | +3.15% | -2.22% ~ +8.13% |
| 수축 후 돌파 · 다음 시가 한도 진입 | 3일 | 258 / 234 | +0.66% | -1.80% ~ +2.95% |
| 동일 | 5일 | 258 / 234 | +1.44% | -2.45% ~ +4.31% |
| 동일 | 10일 | 258 / 234 | +2.23% | -5.24% ~ +7.51% |

수축돌파에는 결과 미확인 후보 1건이 있습니다. 20거래일 단위 블록 재표집 구간이며 다중비교 보정 전입니다. 현재 표의 모든 구간은 0을 포함합니다. 회복 후보의 3일 지정가 대기·10일 보유는 기본 비용에서 구간 하단이 약 +0.07%이지만, 비용을 0.50%로 높이면 하단이 음수가 됩니다. 이것을 안정적인 우위로 채택하지 않습니다.

시장 하락 회피 조건으로 제외되는 사례는 회복 1건, 수축돌파 3건에 불과합니다. 이 실험만으로 강세장·약세장에 각각 적합한 방법까지 판정할 수 없습니다.

### 진입 가격을 바꾸면 좋아지는가?

동일 후보를 단순히 다음 날 시가에 매수한 경우와 비교했습니다. 5일 보유 시 시가 한도 설정의 차이는 회복 후보 +0.32%p, 수축돌파 +0.28%p였습니다. 그러나 두 차이의 신뢰구간은 모두 0을 포함합니다. 3일간 눌림 지정가를 기다리는 방법도 안정적으로 더 좋다고 말할 근거가 부족합니다. 아직 '통계적으로 최적 매수가'라고 표시할 수 없습니다.

### 수급·재무를 추가하면 좋아지는가?

| 5일 보유 · 다음 시가 한도 진입 | 회복 후보 | 수축돌파 후보 |
|---|---:|---:|
| 가격 조건만 | +1.18% | +1.44% |
| 외국인 또는 핵심기관 3일 순매수 추가 | +1.12% | +0.99% |
| 분기 매출 성장·영업이익률 조건 추가 | +0.55% | +0.34% |
| 수급과 재무 조건 모두 추가 | +0.09% | -0.04% |

추가 조건을 통과하지 못하면 현금으로 대기한 효과까지 포함합니다. 조건 통과 종목만의 평균과는 다릅니다. 이 단기 실험에서는 단순한 수급·재무 추가가 성과를 개선했다고 확인되지 않았으며, 그렇다고 수급이나 재무가 일반적으로 무용하다는 결론도 아닙니다. 공시 날짜는 과거 시점에 맞췄지만 정정공시 이전 수치의 완전한 복원은 미확인입니다.

### 높은 계좌 수익률도 그대로 믿으면 안 되는 이유

회복·다음 시가·3일 보유·최대 6개/주 테마당 2개라는 한 비교 계좌는 약 +46.34%, 최대낙폭 -6.21%였지만, 이는 실제 체결이 아닌 재구성 결과입니다. 상위 5거래가 순이익의 60.62%, 상위 10거래가 101.90%를 설명합니다. 상위 10거래의 손익을 제외한 단순 귀속 합계는 약 -88만원입니다. 이는 제외 후 자금을 재투자한 전략 수익률이 아닙니다.

같은 계좌에서도 이전 최고 자산을 회복하지 못한 기간이 최장 63거래일, 새 체결이 없는 기간이 최장 38거래일이었습니다. 생계비처럼 일정하게 발생하는 수입을 보장하는 근거가 될 수 없습니다. 어떤 조합은 미확인 보유 평가가 남아 있어 계좌 수익률 자체를 확정할 수 없습니다.

## 연구 구성

- 현재 분류에 속한 소부장 121종목을 대상으로 조정 후 회복과 수축 후 돌파를 비교하고 있습니다. 현재 구성종목을 과거에도 사용한 생존편향이 남아 있습니다.
- 다음 날 시가 진입과 3거래일 지정가 대기, 보유 3·5·10거래일, 시장 하락 회피 여부를 비교합니다. 미체결·거래비용·갭 손절·동시 보유 제한을 반영합니다.
- 외국인 또는 핵심기관의 순매수, 실제 분기 매출 증가·영업이익률 조건을 각각 추가하여 개선 효과를 별도로 검사합니다. 핵심기관은 기관합계에서 금융투자를 뺀 값이며, 실제 자금 주인을 완전히 식별하는 수치는 아닙니다.

## 기존 성과를 바로 사용하지 않는 이유

독립 검토에서 지수 시가·고가·저가가 비어 있다는 이유로 실제 거래일을 삭제한 오류를 발견했습니다. 이 오류는 보유기간과 지표를 왜곡하므로 기존 성과를 무효 처리하고 재계산을 완료했습니다. 이 문서에는 교정 후 수치만 표시합니다. 일부 큰 수익 사례는 저장된 세 가지 가격 자료와 일치했지만, 그것만으로 실제 주문 체결 가능성이나 반복 수익이 증명되는 것은 아닙니다.

주문 수량도 신호 시점의 주문 한도가로 확정하도록 수정했습니다. 나중에 싼 가격으로 체결됐다고 매수 수량까지 늘리지 않습니다.

## 최근 데이터 확보

- 최근 3거래일의 외국인·기관합계·금융투자 수급: 121종목 모두 확보·검사.
- 9월 8일 가격: 실제 KRX 일별 일괄 자료와 KIS의 OHLCV가 121종목 모두 일치하여 교차 인증했습니다. Naver는 57종목에서 거래량만 달랐고, 원인과 세션 구성은 아직 확정하지 않았습니다. 기존 원본과 불일치 기록을 보존했습니다.
- pykrx의 기본 수정주가 조회는 Naver를 경유하므로 독립적인 KRX 확인으로 사용하지 않았습니다. 실제 KRX 일별 일괄 조회 경로를 구분했습니다.
- 연구 성과 비교는 최근 갱신과 분리하여 8월 26일을 종료일로 고정합니다.

## 남은 채택 조건

거래일·원천자료 정합성, 과거 공시 이용 가능 시점, 거래비용 변화, 큰 수익 몇 건에 대한 의존도, 매매 없는 기간, 동시 보유 5~6개와 테마 중복 위험을 확인합니다. 신뢰구간과 표본 수가 부족하면 '불확실'로 표시하며 가장 좋은 과거 수익률 하나만 골라 추천 규칙으로 만들지 않습니다.

### 학습 모델로 우선순위를 더 잘 정할 수 있는가?

동일 후보 안에서 기존 점수·고정 무작위 순서·가격 학습 모델·가격/수급/재무 학습 모델을 비교하는 8개 조건을 먼저 등록했습니다. 아직 모델 성과를 낸 단계는 아닙니다.

표본 사전 점검 결과, 세 평가 구간 중 대부분은 학습용 후보 수가 부족했습니다. 회복 후보의 마지막 구간만 최종 후보 필터 적용 전 상한으로 학습 318건/85일을 확보했으며, 실제 사용 가능 여부는 추가 확인이 필요합니다. 다른 구간을 임의로 보충하거나 최소 표본을 낮춰 모델을 학습시키지 않았습니다. 대부분 날짜에는 후보가 1~2개라서 '상위 3개 선별' 자체가 선택을 바꾸지 않는다는 점도 확인했습니다.

9월 9일 새벽 점검에서 관찰 화면의 5개 후보가 데이터 대기였던 이유는 최신 날짜 부재가 아니라, 8월 중순 일부 종목의 OHLCV 인증 누락으로 최근 20일 지표가 불완전했기 때문입니다. 8월 12~14일 8종목·24행을 기존 KIS/KRX/Naver 원본으로 좁게 재인증하고 캐시·화면을 갱신했습니다. 연구 원본과 성과는 덮어쓰지 않았습니다.

보완 후 9월 8일 기준 관찰 후보 6개는 모두 데이터 대기가 해소됐지만, **참고 진입가와 손절선 사이의 위험 폭이 커서 보류**입니다. 데이터 오류가 해결됐다고 매수 적격으로 바꾸지 않았습니다. 현재 화면의 참고 규칙은 연구 실험과 별도 버전이며, 두 결과를 동일 전략의 성과로 연결하지 않습니다.

과거 실제 거래대금 218거래일·26,378행 수집과 분석용 별도 부착을 완료했습니다. 이 중 46행은 원천에서 관측된 거래량·거래대금 0으로 구분합니다. 218일 전체 원천 해시를 검사했으며, 기존 연구 가격 파일과 factor의 165,174행·70개 열은 그대로 보존했습니다. 연구 후보의 서로 다른 종목·날짜 426건 모두 실제 거래대금 3일/20일 창이 확보됐습니다. 이는 데이터 보완 완료이지 수익성 검증 통과를 뜻하지 않습니다.

## 실용적인 위험 제한을 적용한 결과

추가로 최대 허용 진입가에서 구조적 손절선까지의 비용 포함 계획손실을 8% 이하로 제한하고, 최근 20거래일 실제 거래대금 중앙값 50억원 이상을 요구했습니다. 회복·수축돌파 각각 3일/5일 보유의 네 비교만 실시했습니다.

**이 조건에서는 통과 후보가 없었습니다.** 현재 진입 한도가와 손절선을 그대로 사용하면 계획손실이 최소 약 9.4%, 중앙값 약 21.1%였습니다. 이는 이후 실제 발생한 손실이나 손실 확률이 아니라, 제시된 최대 진입가에서 손절선까지의 거리입니다. 높은 과거 수익률만 보고 이 계획을 실전에 쓰기에는 위험 폭이 큽니다.

당시 원본 자료에서 실제 거래대금 20거래일이 완전히 있는 관측은 1,002행 중 8행뿐이었습니다. 보유기간 변형이 중복된 행 수이며 독립 표본 수가 아닙니다. 이후 별도 KRX 자료로 후보 날짜의 거래대금 창을 모두 보충했습니다. 다만 모든 후보가 가격·손절 간 계획 위험 조건에서 이미 탈락하므로, 유동성 자료 보완만으로 이 위험 제한을 통과하는 것은 아닙니다. 기존 실험 결과는 당시 입력 버전과 함께 보존했습니다. 현금 대기로 수익률이 0인 결과를 '검증된 안전 전략'으로 평가하지 않습니다.

따라서 이 파일럿을 현재의 매수 추천으로 자동 연결하지 않습니다. 매수가 한도를 낮춰 위험을 맞추는 방법은 체결 기회가 달라지는 별도 가설이므로, 손절선을 임의로 높이거나 위험 제한을 완화하지 않고 따로 검증해야 합니다.

### 손절선은 유지하고 매수가만 낮추는 실험

손절선은 올리지 않고, 비용 포함 계획손실이 8% 이내가 되도록 3일 대기 지정가를 낮췄습니다. 회복 후보는 64건, 수축돌파 후보는 57건이 체결되는 것으로 계산됐습니다. 기존 지정가 대비 5일 기회손익 차이는 각각 -0.30%p와 -0.76%p였고, 두 신뢰구간 모두 0을 포함합니다. 위험 폭을 줄였다고 수익성까지 개선된 것은 아닙니다.

이는 앞선 위험 폭 문제를 확인한 뒤 설계한 사후 진단입니다. 갭 손실은 계획손실을 초과할 수 있고, 실제 호가·체결까지 검증된 추천가격은 아닙니다. 과거 실제 거래대금은 별도 보충했지만, 이것으로 지정가 체결 가능성까지 인증되는 것은 아닙니다.

### 목표가·추적 손절을 추가하면 좋아지는가?

같은 다음 시가 진입·같은 초기 손절선·최대 10거래일을 유지하고 비교했습니다. N은 신호일 ATR20으로 고정했습니다.

| 매도 방식 | 회복 후보 평균 기회손익 | 수축돌파 후보 평균 기회손익 |
|---|---:|---:|
| 초기 손절선 + 10일 종가 청산 | +3.15% | +2.23% |
| 위 조건 + 진입가보다 2N 상승 시 전량 익절 | +1.00% | +0.64% |
| 종가가 2N 상승한 다음 거래일부터 최고 종가−3N 추적 손절 | +2.68% | +2.14% |

비용 0.30% 기준입니다. 목표가·추적 손절의 기존 방식 대비 차이는 모두 신뢰구간이 0을 포함하여 개선이 입증되지 않았습니다. 작은 이익을 빨리 확보하는 방식이 큰 상승 일부를 놓칠 수 있다는 단서는 있지만, 다른 종목·시장에서도 동일하다는 결론은 아닙니다. 2N은 손절 위험의 두 배인 2R과 다릅니다. 초기 추적선이 반드시 이익을 보장하는 위치가 되는 것도 아닙니다.

독립 재검토에서 세 방식의 초기 손절선·체결 계산 경로를 통일하고 결측 시가 처리를 보완했습니다. 고정 자료의 기존 청산 결과와 차이는 0건입니다. 수축돌파 계좌에는 결과 미확인 보유가 남아 있어 계좌 성과를 확정하지 않습니다.

이 문서의 수치는 교정 후 제한적인 후향 비교 결과입니다. 이전 결과나 임시 계좌 수익률을 검증 완료 성과로 해석하지 마세요.

## 다음 검증은 어떻게 이어가는가?

같은 과거 자료에서 조건을 계속 바꿔 가장 높은 수익률을 고르면 우연을 선택할 위험이 커집니다. 따라서 현재 비교를 보존하고, 새로운 날짜의 후보·보류 사유와 당시 사용한 가격·수급·테마 자료를 별도 관찰 기록으로 저장합니다. 입력 파일의 해시와 계산 코드 버전을 함께 남겨 나중에 달라진 자료로 당시 판단을 바꾸지 않도록 합니다.

이 기록은 주문이나 모의 체결이 아닌 관찰 자료입니다. 당일 장 마감 후 기존 일일 처리에 연결했으며, 평일 21:10에는 저녁 수집 이후 캐시·관찰 기록을 별도로 갱신하도록 서버에 예약했습니다. 앞선 수집이 끝나지 않았거나 데이터가 부족하면 그 상태도 그대로 저장합니다. 충분한 새 사례가 쌓인 뒤 회복 인식 시점, 진입 가능 가격, 이후 손실·회복 기간을 평가하겠습니다. 새로운 자료가 없는데 같은 날의 기록을 반복 저장한 것은 새로운 검증 사례로 세지 않습니다.

### 분봉으로 확장하기 전 남은 확인

기존 KIS 보완 수집기의 import·응답 필드·분별 거래량 처리를 수정했지만, 자동 저장은 켜지 않았습니다. 삼성전자 9월 8일 장 마감 부근의 공통 20시각에서 KIS와 기존 Kiwoom WS의 OHLC 전체 일치는 11개, 거래량 일치는 0개였습니다. 시장·세션·집계 방식이 같은지 확인하기 전에는 두 원천을 섞지 않습니다.

15:20~15:29에 KIS가 표시한 가격 고정·거래량 0의 10봉은 종가 단일가 대기 구간에 해당합니다. WS에 같은 봉이 없다는 것만으로 수집 오류라고 판단하지 않았습니다. 이 한 종목 표본으로 전체 품질을 단정할 수 없으며, 분봉 원천 인증과 장중 전략 성과 검증은 남아 있습니다. 거래시간과 분봉 응답 의미는 한국투자증권의 [거래시간 안내](https://m.koreainvestment.com/main/customer/guide/_static/TF04ad030000.jsp) 및 [공식 분봉 예제](https://github.com/koreainvestment/open-trading-api/blob/main/examples_llm/domestic_stock/inquire_time_itemchartprice/inquire_time_itemchartprice.py)를 참고했습니다.

연구 설계

# 반도체 소부장 full-cycle 연구·운영 설계 — 2026-09-09

Status: **DESIGN / RESEARCH ONLY. No validated new entry strategy and no production promotion.**

This document specifies an executable, bounded overnight study and an honest decision-support contract. It is not a forecast, optimal-price claim, or promise of trading income. A successful delivery can contain zero qualified trades, substantial cash, and several no-trade months. Five or six positions are capacity limits, never targets.

## 1. Evidence already available

The following artifacts were inspected before proposing new methods. Their published test periods have now been seen and cannot become untouched again.

| Existing study | Relevant result | Permitted interpretation |
|---|---|---|
| `analysis_results/semiconductor_correction_reaccel/REPORT.md` | Theme reacceleration AUC 0.442; top-quintile lift about zero. Overheat + activity symptom correction-risk lift +21.4 percentage points, reported CI +3.0 to +27.9 points. | Correction warning deserves replication; it does not establish a profitable exit or a rebound entry. |
| `analysis_results/semiconductor_stock_reacceleration/REPORT.md` | Stock AUC 0.404; selection lift CI crosses zero. | No validated stock-level reacceleration rule. |
| `analysis_results/theme_reaccel_early_response/REPORT.md` | Raw 3-session response returns negative in 2024 and 2025, positive in 2026. Close-only stop proxy is not executable. | Regime instability and execution uncertainty remain. |
| `analysis_results/semiconductor_entry_member_filter/result.json` | Selected finance/beta filter: 2026 stock-weighted mean approximately −0.15%, versus all members +1.02%; only 13 signal dates. | Do not hard-code finance score ≥0.5 or a beta floor as established selection alpha. Date-weighted and stock-weighted results answer different questions. |
| `analysis_results/semiconductor_six_month_model_search/REPORT.md` | Five-session theme nonlinear ranking improved in four short walk-forward blocks but decayed; stock improvement in three of four blocks. Final selected models did not beat contemporaneous candidate means. | A 5-session challenger is worth replication, not promotion. Ten-session prediction lacked consistency. |
| `docs/AI_CONTEXT.md`, `docs/SIGNAL_FINAL_SHORTLIST.md` | CROS P1c has prior evidence in its original universe; wave, stage, N/ATR are contextual/risk axes. | Import the exact frozen P1c definition as a benchmark. Semiconductor-subset transfer still requires validation. |

Do not use these published figures as a new confirmatory test. Preserve them as prior evidence and record the research exposure in the new manifest.

## 2. Immediate safety and semantic repairs

These precede experiments and change correctness, not alpha thresholds.

1. **Separate observation from qualification.** Keep a liquid strong-theme stock visible if it is relevant to a pullback; annotate weak financials, absent flow, absent trigger, excessive gap, and wide structural risk independently. An empty qualified list is valid. Never reduce the stop distance arbitrarily to turn `RISK_TOO_WIDE` into a buy candidate.
2. **Use one versioned feature contract in research and service.** The correction study uses median member daily returns, SMA20, and the median of log member turnover ratios. The draft service uses mean returns, EMA20, and aggregate recent turnover divided by a different baseline. Changing only `0.587` to `exp(0.587)` does not reconcile the features. Either reproduce the original contract exactly or label and validate a distinct variant. The study's log cutoff 0.587 corresponds to a member-ratio scale near 1.80, not 0.587.
3. **Never fill missing supply with zero.** Join supply to the exact price sessions. Store `coverage`, `available_at`, `source`, `unit`, and `stale_sessions`. Three old observations are not current three-session flow. Core institutions = institution minus financial investment only when both fields have compatible units and known coverage. Unknown minus known remains unknown.
4. **Compute actual initial risk correctly.** For a long position, `risk_fraction = (entry_fill - initial_stop) / entry_fill`; multiply by 100 only in a `_pct` display field. Example: entry 100, stop 95 gives 0.05 / 5%, not 5.263%. Recompute after entry gaps, directional tick rounding and costs. Reject stop ≥ entry, zero/negative prices and invalid tick levels.
5. **PIT is more than an available-date column.** Finance uses a backward as-of join; a weekend release must become visible next eligible session, not disappear during `reindex(trading_dates).ffill()`. When intraday availability is unknown, use the next trading session conservatively. Preserve restatement vintage and fiscal period. Current financial scores must not be backfilled into history.
6. **No future availability filters.** Replace full-sample `notna().sum() >= 180` membership checks with history accumulated by decision time. Do not remove a candidate at entry because later OHLC is missing: that is future-informed allocation. Log post-entry missing-data states and conservative account valuation separately.
7. **No automatic clean/raw splice.** A raw tail after a clean global watermark can still have a different adjustment basis, unresolved action or per-stock hole. Keep it display-only until per-stock continuity, corporate-action and source parity checks pass. A global clean watermark is not a stock-level freshness guarantee.
8. **No truncated future extrema.** `min/max` across shifted columns skips NaN by default; require all H future sessions before assigning an H-session label. A missing return must not become a false label through `.ge(...)`. Labels live outside live feature frames.

## 3. Data and time contract

### 3.1 Immutable run inputs

Create a read-only research snapshot and a run manifest before model fitting. Include source relation/version; snapshot digest; code commit plus dirty-file digests; feature-schema version; dependency versions and distribution digests; stock/date counts; exchange calendar; price adjustment convention; flow units; finance vintage rules; memberships and dates; cost model; seeds; exact trial registry; split/session boundaries; known prior exposure; and eligibility/rejection counts. Never put credentials or connection strings in artifacts.

Use the certified exchange-session calendar. Rolling 3/5/10 means exchange sessions, not the last three observed stock rows or calendar days. Missing/suspended stock sessions remain explicit. Compute features through t close only, after their source is available; enter no earlier than the next eligible execution session. Entry day is holding day 1; an H-session exit close is entry index + H − 1.

### 3.2 Universe and thematic context

Use the existing semiconductor value-chain members as the explicitly named **current-basket retrospective cohort**, not a reconstructed historical investable universe. Deduplicate stock/date opportunities before portfolio allocation. Preserve all theme memberships for concentration accounting; choose a primary context using only contemporaneous strength and a deterministic tie-break.

Prefer effective-dated membership and listing/delisting history if already certified. Do not spend the night inventing historical memberships. Where they are absent, report survivorship/membership bias, prohibit claims about the complete historical semiconductor opportunity set, and require prospective evidence before real-trade promotion. A leave-one-theme-out sensitivity check is not a cure for survivorship bias.

A daily synthetic theme index uses explicitly covered member one-day returns. Missing breadth members are not bearish votes, and missing returns are not zeros. Freeze coverage rules before fitting; report eligible denominator, expected members and effective member count. If valid members are too few for the declared theme contract, mark its state unknown. Do not compute thresholded current-basket ranks as though small groups have continuous precision.

### 3.3 Allowed feature families

| Family | Minimal features | Mandatory guard |
|---|---|---|
| Price/context | 1/3/5/20-session returns, ATR20/close, SMA20 distance/slope, trailing-high drawdown in ATR units, candle location, market/theme relative return, breadth/change | Trailing only; indicators identical in service and research; sufficient actual history. |
| Flow | Foreign and core-institution 3/5-session net / monetary turnover; persistence; change in normalized flow | Exact session alignment, known units and publication lag; missing indicators; no share-volume denominator for KRW amounts. |
| Financial quality | PIT annual operating margin and revenue growth, with period, release date and age | Current clean quarterly mixtures remain quarantined; no inferred earnings surprises without announcement-time vintages. |
| Wave | Causal short-band position, width, period, reliability | Existing monthly-frozen period selector only; prefix-invariance tests; unreliable/missing wave is not a positive signal. |

For quantities needing scale conversion, store raw unit and fraction, not ambiguous numbers called `score`. Avoid double-counting price derivatives as independent votes: stage, moving averages, wave position and momentum are correlated descriptions, not four independent confirmations.

Financial quality initially annotates structural suitability. It becomes a hard selection gate only if the matched incremental study supports it; a fixed “0.5 quality” threshold is not evidence. Liquidity and execution feasibility remain safety constraints, not optimized alpha knobs. Historical market-cap incompleteness must not be hidden behind a deployment-only cap floor.

## 4. Validation architecture and holdout integrity

### 4.1 Honest untouched block

First register a latest chronological lockbox boundary before additional analysis. Choose by date/calendar, not returns. A suggested size is the latest 63 mature sessions, if data depth permits. Do not print its candidate outcomes or scores during development.

However, the inspected six-month study already reports through 2026-09-04. If those dates overlap the lockbox, call it **locked internal validation / previously exposed**, not untouched. No rearrangement can restore unseen data. The true untouched test must then be newly arriving prospective sessions after the freeze. Document this now; do not claim overnight confirmation from a relabeled 2026 block.

Do not consume a legitimately unseen lockbox unless a frozen candidate passes the development gates. If all candidates fail, retain the lockbox unopened. An end-of-night deadline does not justify peeking.

### 4.2 Nested rolling evaluation

- Prefer at least 252 prior sessions for training and 63 sessions per outer evaluation block; require at least three sufficiently populated outer blocks. If certified data supports only six months, report a pilot, not robust validation.
- Inside each outer training history, use three forward-chaining date splits for method/threshold selection. Group every stock and overlapping theme on the same date into the same split. Never apply a row-based random split to the panel.
- Purge training labels whose outcome window overlaps validation. Purge by recorded `label_end_session`; conservatively reserve 13 sessions for up to 3-session entry validity plus 10-session holding. If a policy introduces a longer wait, update the purge automatically. Test input lookback may include historical train prices; future labels may not.
- Fit imputation, scaling, probability calibration, quantiles, ranks requiring a historical distribution and hyperparameters only on each fold's training data. Never run standardization across all dates.
- Freeze the chosen pipeline before each outer block. Prior outer-block outcomes may enter later training only after labels mature, as in real deployment. The resulting adaptive-policy sequence is evaluated as one predeclared procedure; do not retrospectively select the best outer strategy and call its same outer data confirmatory.

`TimeSeriesSplit` provides chronological splits and a gap, but the adapter must split unique session dates and enforce event label end-times; its row gap alone does not understand multi-stock panels. [scikit-learn official API](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.TimeSeriesSplit.html)

### 4.3 Baselines and inference

Keep cash, same-date eligible semiconductor basket, a verified broad-market benchmark, and exact original CROS P1c transfer as comparators. Match the entry clock, costs, horizon and capacity. Separate absolute net P&L from incremental selection return: a rising sector can make every weak selector look profitable.

Primary endpoint: daily shared-capital net return improvement over the matched candidate-policy baseline, with all no-fill/no-trade dates included. Secondary: net return per planned opportunity, filled-trade expectancy, calibrated win probability, drawdown and tail loss. AUC is diagnostic, not a trade gate by itself.

Resample full date cross-sections in contiguous blocks, retaining simultaneous stocks and theme overlap. Use a predeclared 20-session moving/stationary-block baseline with 10/40-session sensitivity, at least 2,000 reproducible resamples. Date-IID resampling or taking every third observed signal date does not remove overlapping 10-session outcomes. Use a max-statistic family-wise or SPA-style comparison over the registered search; report unadjusted and adjusted inference. `arch` offers stationary/block bootstraps and multiple-model comparison procedures; reuse it when the installed/isolated environment passes compatibility and licence checks. [Official arch repository](https://github.com/bashtage/arch)

## 5. Bounded multi-method study

The following is a maximum search budget, not a requirement to fit every cell when data is inadequate. Record empty/failed cells. Do not append new thresholds after seeing outer results.

### Stage A — 36 predeclared selection chains

Three causal setup families × two ranking methods × two market policies × three horizons (3/5/10 sessions) = **36** chains. Each uses next-open entry, no profit target, a research-comparison 1.5 ATR initial stop, and time exit at H. The 1.5 ATR setting is a baseline convention, not a validated optimal stop.

Setup families:

1. **Strong-theme pullback, observed recovery.** Theme index above rising SMA20; breadth at least one half of valid members; stock has a trailing 10-session high drawdown. Normalize drawdown by ATR. Admit the central train-calibrated interval Q25–Q75 among positive drawdowns in that context, rather than a universal 2.5–15% band. Require t close to exceed the prior two sessions' highs. Keep unconfirmed current pullbacks as observations, not filled trades.
2. **Pullback → contraction → breakout.** A causal pullback occurred in the previous ten sessions; trailing 5-session true-range/20-session ATR is below its train Q50; close breaks the prior five-session high. Each sequence step has a recorded date. No ex-post trough or future “base completion” label is an input.
3. **Frozen CROS P1c transfer.** Use the existing repository's exact canonical event definition, unchanged. Apply the common data/universe/execution contract. Do not substitute “CROS_UP” or another union without explicitly proving the mapping.

Ranking methods:

- **Transparent baseline:** equal-weight mean of within-date price relative-strength rank, candle-close-location rank and inverse ATR/close rank, with stable stock-code ties. This is an explicit challenger rule, not a production quality score.
- **Small nonlinear challenger:** `HistGradientBoostingRegressor` for realized next-open/H-close net residual return; fixed `max_iter=100`, `max_leaf_nodes=7`, `min_samples_leaf=50`, `l2_regularization=1`, `learning_rate=0.05`, fixed seed, and `early_stopping=False` to avoid an implicit random validation split. No hyperparameter grid. If train sample is inadequate, record unavailable rather than fit a smaller leaf opportunistically.

The existing L1 logistic stock model is reported as a prior benchmark, not retuned into another search family overnight. Quantile levels below come from training distributions and do not imply guaranteed return quantiles.

Market policies:

- `ALL_REGIMES`: record up/sideways/down states but do not veto entries.
- `AVOID_MARKET_DOWN`: no new entries when a verified broad-market index is below declining SMA60. Unknown benchmark state cannot be treated as bullish. The down predicate uses t and t−5 values only.

Evaluate both with the same theme setup rules. Report market-regime × sector-regime × volatility strata, but do not fit a separate model for every cell. A regime filter must justify lost opportunities and cash drag as well as avoided losses.

### Stage B — at most 6 matched information ablations

Within each training fold retain at most two Stage A finalists, including their selected horizon. Evaluate three additions for each: `price+flow`, `price+flow+finance`, and `price+flow+finance+reliable_wave`. Thus at most **6** additional chains. Compare both native coverage and identical complete/eligible observation dates. Missing-data coverage must not masquerade as alpha. Any unreliable-wave variant is unavailable, not silently imputed to “support.”

Keep an added family only if matched incremental net performance and calibration/stability improve in training validation. Otherwise deploy the simpler feature set if later qualified. Do not assume that finance, flow or wave must be used because they exist.

### Stage C — at most 24 execution chains

For at most two Stage B/Stage A finalists, with horizon and selection fixed inside train, compare two entry protocols × two stops × three exits = **12** each, maximum **24**. The study therefore adds no more than **66** scored chain configurations before declared sensitivity tests. Count sensitivities in the trial ledger if they influence selection; they are not free trials.

Entry protocols:

- `NEXT_OPEN_CAPPED`: next open only if the opening gap does not exceed train Q90 of positive next-session gaps in the same setup, and the planned structural stop is still valid. Otherwise no fill.
- `PULLBACK_LIMIT_3`: a fixed t-close limit using train Q50 of positive next-three-session pullback depth, normalized by ATR; valid for three exchange sessions. The historical depth distribution uses all mature eligible training opportunities, not only future winners. Cancel on observed invalidation. A gap below structural invalidation cancels the order, not a magically favourable fill.

Stops:

- `STRUCTURE`: minimum low of the five completed pre-signal sessions minus 0.25 ATR(t), frozen at signal time. This is a declared structure convention.
- `TRAIN_MAE_Q75`: stop distance in ATR units = Q75 of full H-session adverse excursion from next-open entry, across **all** mature train opportunities for that setup. Re-estimate only at the scheduled train boundary. These are retrospective labels used only in training calibration; never per-trade future values.

Exits:

- `TIME`: protective stop plus the precommitted H-session close exit.
- `TARGET`: protective stop plus a target from train Q50 of positive H-session maximum favourable excursion across all eligible training events (zeros retained for events with no favourable excursion), otherwise H close. A zero/nonpositive calibrated target makes this chain unavailable, not successful.
- `TRAIL`: protective stop plus a 2 ATR trailing distance from the highest **completed prior close**, effective on the following session, otherwise H close. It cannot use today's high to place a stop that today's low allegedly hit first.

Quantile sample fallback is deterministic: require at least 100 mature events and 30 distinct dates in the setup-specific train group; otherwise pool the same setup across market regimes; if still inadequate, mark the quantile method unavailable. These are research adequacy guardrails, not claims of statistical sufficiency. Do not estimate per-stock stop quantiles from a handful of winning events.

Separately report the already studied overheat warning as an exit-risk **ablation only after an entry chain qualifies**. Its predictive correction label is conditioned partly on being near a high, so compare within that same risk set. A profitable stop/exit timing effect cannot be inferred from warning classification lift.

## 6. Execution and portfolio accounting

Reuse existing helpers before adding a thin deterministic event-order adapter:

- `analysis/evaluate_signal_entry_timing_20260907.py`: next-open, causal confirmation, limit and no-fill states, explicit H counting. Its old date-IID confidence interval is not sufficient for this study.
- `analysis/audit_recommenders_2y.py::simulate_risk_reward`: gap handling and stop-first daily-bar convention.
- `analysis/evaluate_signal_portfolio_20260907.py`: shared cash, stable ranking, five/six capacity and rejection ledger. Repair future-OHLC prefiltering before reuse; preserve all candidate attempts.
- `analysis/theme_band_context.py`: monthly-frozen historical wave contexts, subject to prefix-invariance verification.

`backtesting.py` has commission/spread and next-open execution support, but does not itself certify Korean source units, corporate-action PIT semantics, shared multi-stock constraints, or the conservative same-bar entry contract below. Use it as a small independent execution oracle when licence/compatibility permits, not a drop-in production replacement. Its repository is AGPL-3.0; do not introduce it into service code without licence review. [Official API](https://kernc.github.io/backtesting.py/doc/backtesting/backtesting.html), [official repository](https://github.com/kernc/backtesting.py)

Accounting requirements:

1. Gap through a protective stop exits at the first tradable open/available execution price, not the stop. Limit-down/no-liquidity bars may leave a position trapped; a daily low touching a level does not prove a sale was possible.
2. When stop and target occur on the same daily bar, use stop first. With intraday limit entry, a favourable high may have preceded entry; do not credit a same-bar profit target absent sequencing evidence. If both a possible entry and protective stop are crossed, use conservative entry-then-stop treatment or explicit bounded uncertainty; never delete only adverse ambiguous trades.
3. Predetermined time exits may use H close as an execution approximation with costs. Decisions based on that same close's newly computed indicators execute next session, not retroactively at the close.
4. Preserve `NO_FILL_TIMEOUT`, `INVALIDATED`, `GAP_REJECTED`, `DATA_UNAVAILABLE`, `CAPACITY_REJECTED`, `ALREADY_HELD`, `CASH_REJECTED` and filled outcomes. No fill has zero trading P&L in opportunity/account metrics and stays in the denominator. Data-unavailable is uncertainty, not zero risk.
5. Future missing bars never change earlier selection. An open position with missing mark gets a flagged last-known valuation and a conservative downside sensitivity; do not call the resulting NAV certified or invent a tradable exit. Resolve delisting/action payoff from certified evidence before promotion.
6. Maintain adjusted research and executable price bases consistently. Never join adjusted close to raw OHLC. Adjust held share counts/cost basis/stop levels on certified actions at the effective time. Do not delete extreme loss events merely because they breach a return cutoff; quarantine with reasons and stress the exclusion.
7. Use a documented effective-date schedule for fees and sell-side taxes when available. Do not assert current Korean statutory rates without checking official evidence. If unavailable, use explicitly assumed all-in 0.30%, 0.60%, 1.00% round-trip scenarios, with entry and exit portions charged when incurred; a scenario is not a fee quote. Test opening gaps separately from fees and respect daily turnover participation.
8. Allocate one shared capital pool. A reproducible research scenario is 0.25% NAV initial risk per trade, ≤20% notional per name, ≤1% aggregate planned initial risk, no leverage, and five positions maximum; six is a sensitivity only. These are illustrative controls requiring user-specific capital/risk settings before live use. Cash, costs, rounding and existing positions can reduce allocation to zero.
9. Risk-sized quantity is `floor(min(risk_budget/(fill-stop+cost_buffer_per_share), notional_cap/fill, liquidity_cap/fill, cash_available/(fill+entry_cost_per_share)))`. Planned stop risk is not a bound on gap loss. Do not average down or add leverage to restore expected income.
10. Treat semiconductor subthemes as correlated, not six independent bets. Count overlapping theme exposure; report concentration by stock and broad factor. Include scenario joint gaps of −5% and −10% in held names, explicitly stresses rather than forecasts. Report cash fraction, turnover, gross/net exposure and whether five versus six capacity materially changes tail risk.

## 7. Promotion gates

The thresholds below are conservative governance choices, not mathematical guarantees. Freeze before scoring and never relax them because the candidate list is empty.

| Status | Necessary evidence | User-facing capability |
|---|---|---|
| `DATA_BLOCKED` | Missing/stale/uncertified required data, source/basis mismatch or insufficient current history | Show issue and data dates; no actionable entry levels. |
| `OBSERVATION` | Valid descriptive structure but no trigger or no statistical qualification | Current strong-theme pullback, relevant context and explicit invalidation references; clearly not a buy. |
| `CONDITIONAL_SETUP` | Causal trigger and executable hypothetical plan; historical evidence provisional or biased | Conditional watch plan with assumptions, not qualified trade language. |
| `RESEARCH_QUALIFIED` | All data/execution tests; nested OOS absolute net expectancy and paired improvement CI lower bounds >0; multiplicity-adjusted p≤0.05; at least 100 filled OOS trades, 50 distinct entry dates, three populated outer blocks; positive incremental net in ≥2/3 blocks; positive at 2× base friction; tolerable predeclared drawdown/tail stress | Shadow tracking only until a genuinely unseen/prospective test and PIT universe limitations are resolved. |
| `TRADE_REVIEW_READY` | Frozen strategy passes independent/prospective evidence, live input parity, feasible fill risk, account caps and manual risk settings; no unresolved material bias | Human review candidate. Still no automated order authority or guaranteed outcome. |

Also remove the largest contributing stock and the best month in sensitivity analysis; a reversal of the main conclusion blocks promotion pending more evidence. Minimum counts are floors, not a substitute for confidence intervals or regime coverage. If a method works only in one predeclared regime, label the limited scope and require adequate independent samples there; do not invent a post-hoc favourable regime.

Publish trade count, fill rate, mean/median net trade return, realized payoff ratio, win rate with uncertainty, opportunity return, date-matched incremental return, exposure-adjusted and account return, maximum drawdown/duration, worst month, consecutive losses, tail expected shortfall, no-trade months, cash share, best-stock/month contribution and cost sensitivity. Do not annualize a tiny pilot into an income expectation.

## 8. Full-cycle lifecycle and API contract

Strategy evidence and position state are different axes. A newly invalidated setup must never make an already-held position disappear from exit management.

```text
OBSERVED -> WATCHING -> ARMED -> ENTRY_PENDING -> OPEN -> EXIT_PENDING -> CLOSED
                |          |          |
                +----------+----------+----> CANCELLED / EXPIRED

OPEN + invalidation / stale data -> exit-risk review, not deletion from the list
```

In this service `ENTRY_PENDING` is a hypothetical/manual plan unless an actual broker acknowledgement exists. Daily high/low touches do not establish a live fill. Unknown holdings must be labelled `position_source=none`; do not show “hold,” “take profit,” or a return on a position the user never confirmed.

Minimum per-candidate response (field names illustrative, stable schema version required):

```json
{
  "schema_version": "semi-cycle-v2",
  "run_id": "immutable-manifest-id",
  "as_of_session": "YYYY-MM-DD",
  "generated_at": "ISO-8601",
  "stock_code": "000000",
  "theme_ids": ["theme-id"],
  "universe_basis": "current_basket_retrospective",
  "evidence_status": "CONDITIONAL_SETUP",
  "lifecycle_state": "WATCHING",
  "reason_codes": ["UNVALIDATED_ENTRY", "FLOW_STALE"],
  "data_quality": {
    "price_asof": "YYYY-MM-DD",
    "flow_asof": "YYYY-MM-DD",
    "flow_stale_sessions": 2,
    "flow_coverage": 0.3333,
    "finance_available_at": null,
    "wave_reliable": false,
    "price_basis": "declared-basis-id"
  },
  "strategy": {"id": "frozen-id", "version": "digest", "horizon_sessions": 5},
  "plan": {
    "entry_protocol": "NEXT_OPEN_CAPPED",
    "valid_until_session": "YYYY-MM-DD",
    "entry_reference": null,
    "max_entry_price": null,
    "initial_stop": null,
    "target": null,
    "time_exit_rule": "entry_session_plus_H_minus_1_close",
    "risk_fraction": null,
    "estimated_net_reward_risk": null,
    "level_basis": "conditional_reference_not_order"
  },
  "position": {
    "source": "none",
    "quantity": null,
    "average_fill": null,
    "opened_at": null,
    "initial_risk_cash": null,
    "active_stop": null,
    "realized_pnl": null
  },
  "validation": {
    "report_id": "artifact-id",
    "unseen_test_passed": false,
    "oos_fill_count": null,
    "oos_entry_dates": null,
    "net_expectancy_ci": null,
    "unresolved_limitations": ["historical_membership_unknown"]
  }
}
```

Use null for unknown, not zero. Do not use an opaque `confidence=80` without a calibrated event and sample definition. Distinguish expected price range, conditional order reference, actual fill and chart annotation.

If position tracking is implemented later, append immutable events with `event_id`, `position_id`, `observed_at`, `effective_at`, `source`, `reason`, strategy version, before/after quantity and stop, and idempotency key. Revisions append correction events; they do not overwrite fills. Long protective stops cannot be loosened automatically. Partial exits/reentries are excluded from the first study unless added as a separately registered policy. Restart/replay must reconstruct the same state and NAV.

The HTTP request should read a completed snapshot; expensive historical fitting should run offline. Serve the last complete snapshot with visible freshness and reason codes. Fail closed when a required data contract changes; never silently “upgrade” a stale setup by combining incompatible cache versions.

## 9. Incremental implementation order and acceptance tests

### P0 — Freeze, repair, and expose the right status

Create the trial/split manifest; audit prior exposure. Repair risk units, flow missingness/session alignment and feature parity. Keep production advice unqualified. Add fixture tests before recalculation. Export the current observation funnel: scope → data valid → structural context → pullback → trigger → execution feasible → evidence qualified → portfolio admissible. Each removed stock retains every applicable reason, not only the first failing guard.

### P1 — One causal panel and replay adapter

Factor reusable feature definitions behind a versioned interface without rewriting existing services. Build new study outputs under a dedicated run directory. Add global calendar alignment, label maturity, actual available timestamps, raw/adjusted guard and future-data mutation tests. Adapt existing entry/exit/account helpers; do not add a new general-purpose backtester.

### P2 — Bounded nested study

Run Stage A first. Run information/exit ablations only if adequately populated finalists exist. Save every trial and rejection. Stop expanding the search when the statistical floor is not met; investigate data integrity or produce an honest negative report. Do not rerun a lockbox after a failed result.

### P3 — Account audit and read-only handoff

Generate candidate ledger, execution ledger, per-session NAV, per-month outcomes and failure cases. Audit current strong-theme pullbacks against the exact frozen feature code. Add the lifecycle/status schema as a read-only snapshot; persist hypothetical/manual states only with clear source semantics. No external orders, no paid APIs, no credentials in outputs.

### P4 — Final freeze and prospective shadow

Produce one concise Korean report: what was tried, what passed/failed, today's observations, why any entry is withheld, available risk plans, data age, cash/no-trade expectations, and next evidence needed. Register the frozen prospective strategy and schedule ordinary existing collection/replay mechanisms only if authorized. Do not claim completion of prospective evidence during an overnight task.

Required acceptance fixtures:

- entry 100 / stop 95 → 5% risk; invalid/inverted stops reject;
- missing flow ≠ observed zero; stale three rows cannot match fresh three bars;
- same source normalized as KRW versus 100-million KRW yields identical flow fraction after conversion;
- weekend/after-close financial release enters no earlier than allowed;
- future price/flow/finance mutation leaves every earlier feature/decision unchanged;
- wave output for a prefix equals the same dates from an extended history;
- all H label sessions required; unknown outcomes remain unknown;
- synthetic split/action cannot mix raw and adjusted OHLC or create a false stop/return;
- stop-gap loss exceeds planned stop when appropriate; target+stop same bar uses stop first;
- intraday limit entry cannot capture a pre-entry high; cancelled/no-fill plans survive in reports;
- a future missing bar cannot remove an earlier accepted allocation;
- no-fill and zero candidates preserve cash without NaN/divide-by-zero metrics;
- same stock in overlapping themes has one position; capacity 5/6, cash, initial-risk and liquidity caps hold;
- replay, restart and duplicate events give identical holdings/cash/NAV;
- missing held-position data flags risk but never hides the holding;
- UI/API cannot label `OBSERVATION` or `CONDITIONAL_SETUP` as a verified buy.

## 10. Reuse and dependency decision record

Existing NumPy/pandas/SciPy/scikit-learn and repository research helpers cover almost all required computation. The inspected virtual environment reports NumPy 2.4.6, pandas 2.2.3, SciPy 1.17.1 and scikit-learn 1.8.0; `arch` and `backtesting` are not installed. Repository dependency files differ, so the execution run must record **actual** installed versions rather than copy requirement assumptions. This document does not install or upgrade packages.

Use installed scikit-learn pipelines and fixed HistGradientBoosting only after version/API compatibility tests. `arch` is a candidate for block uncertainty and multiple comparison, subject to exact release, licence, distribution and security review; this design's source review is not a completed package adoption audit. `backtesting.py` is an optional isolated oracle, not a service dependency. No package's existence or source popularity certifies market-data semantics or profitability.

The justified custom gap is small: a StockPulse-specific adapter enforcing session/availability/provenance contracts, conservative KRX daily-bar ambiguity, shared-cash portfolio constraints and immutable decision/fill state. Statistical estimators, generic indicators and a broad backtesting framework should not be reimplemented overnight.

## 11. Immediate execution assignment — reduced 12/24-chain pilot

To leave overnight time for correctness and portfolio audit, the executor should prefer this reduced pilot to the full 66-chain ceiling. Register the reduced grid before execution; do not run both grids and omit the unsuccessful trials.

1. **Panel and execution audit first.** Implement the shared panel from section 3 and the acceptance fixtures for missing flow, label maturity, no-fill, gap/ambiguous bars and future-data mutation. Use the same causal SMA/member-median theme contract as the prior correction study. Export observation funnel counts before fitting. Keep outcome columns out of the live feature object.
2. **Twelve timing chains.** Two setups (section 5's observed-recovery pullback and contraction-breakout) × two entry protocols (`NEXT_OPEN_CAPPED`, `PULLBACK_LIMIT_3`) × H=3/5/10. Use fixed transparent ranking, `STRUCTURE` stop and `TIME` exit. Quantile calibration is train-only. No stop-width, target or nonlinear-model search in this pilot. Compare to same-date all-eligible-next-open and cash policies. Include opportunity P&L with no fills and shared-capital daily NAV.
3. **Twelve paired regime chains, if data permits.** Repeat those twelve with `AVOID_MARKET_DOWN`; the original twelve operate in all regimes. No further slope thresholds. Report the paired net-return/drawdown difference, missed positive opportunities, cash share and no-trade months. If fewer than three retrospective outer blocks are available, label the entire run `PILOT_INSUFFICIENT_HISTORY`.

Required executor outputs: `manifest.json`, `feature_contract.json`, `folds.csv`, `trial_registry.csv`, `candidate_ledger.parquet`, `trade_ledger.parquet`, `daily_nav.parquet`, `fold_metrics.csv`, `monthly_metrics.csv`, `current_observations.json`, and a short report. All paths should sit under a new run-specific research directory. The future genuinely untouched shadow begins after this version is frozen; already inspected 2026 blocks remain retrospective.

Do not build a financial-quality hard filter into this reduced pilot. If time remains, run a clearly registered **diagnostic** matched coverage comparison of price versus flow/finance annotations; it cannot change the chosen strategy or add a buy qualification without being counted as further selection. The full Stage B/C study is a later follow-up, not an excuse to continually increase the night's search budget.

Final release principle: **correct observations and an explicit no-trade decision are useful service outputs; unvalidated precision is not.**

데이터 감사

# Semiconductor cycle v2 — data audit

Generated from read-only queries on 2026-09-08T16:26:15.705284+00:00; no production tables or source rows were changed.

## Scope and frozen panel

- Deployed value-chain definition: **14 groups / 121 enriched stocks** (canonical unique codes are read from the cache; audited theme additions are applied exactly as the service does).
- Price watermark in the target universe: **2026-09-04**; supply watermark: **2026-09-08**. These are not synchronized after the frozen session.
- Recommended reproducible cutoff: **2026-08-26**. Keep the fixed current-basket retrospective cohort at **121 codes** for price/structure results; evaluate a separate **119-code price+flow variant** because flow is absent for **036010, 045970**. Never fill missing flow with zero.

## Coverage

See `data_audit_group_coverage.csv` for every basket and `data_audit_stock_coverage.csv` for every enriched code. The frozen date has complete price+flow rows for the 119-code common universe; later dates are partial/asynchronous.

## Units and PIT finance

- Investor flow fields are monetary KRW amounts; the cycle features should use `(institution_net - financial_net)` for core institutions and divide by KRW turnover, not share volume.
- Clean financial amounts are stored as standardized KRW integers by the existing loaders. The clean financial table has no unit column, so source provenance is required; this is a metadata limitation, not a reason to rescale rows in this audit.
- Before the frozen cutoff, 4392 usable PIT rows cover 121 stocks. {'exact_disclosure_date': 4465, 'proxy_disclosure_date': 43}.
- Consensus is explicit-unit data but only spans 2026-07-27–2026-08-26 in this cutoff slice; it is not a substitute for long-history PIT actuals.

## Quality findings

- Duplicate keys: price 0, supply 0; invalid positive-OHLC/volume rows: 205; OHLC bound violations: 0.
- Exact zero returns: 8385 rows (8225 with positive volume); longest run 36. These are review flags only, not automatically spurious and were not patched.
- Price provenance changes across history (KIS/KIS-adjusted, CREON bridge, fact table, and unknown/Naver-cross-matched rows). The clean schema has no explicit adjustment-basis flag; do not silently mix raw and adjusted series. Use the frozen certified panel and retain source/certification columns in downstream artifacts.

## Corporate-action continuity sample

- Sampled 036930, 007660, 095340, and 357780. The action index is announcement-only in this sample: effective dates are missing and `usable_for_price_adjustment` is false. The ±3-row return windows in `data_audit_action_continuity.csv` are diagnostic context only; continuity is **unavailable**, and no source data were changed.

## Blockers / action items

1. Keep the current-basket retrospective cohort fixed at 121 codes; only the flow feature variant should be marked missing for 036010 and 045970.
2. Preserve the 2026-08-26 cutoff (or recertify a later date after all target codes have both price and flow) for reproducible cycle studies.
3. Add adjustment-basis and financial-unit provenance at the clean-layer schema boundary; until then, retain source/certification and loader semantics in every manifest.
4. Populate corporate-action effective dates/factors before using event continuity as a pass criterion.

독립 검토 · 수정 전 결과의 한계

# Semiconductor cycle v2 — independent review, 2026-09-09

## Verdict

**NO-GO for accepting the current research performance as finalized.** A confirmed calendar-construction defect deletes genuine trading sessions and requires full feature, fold, event, entry-comparison and portfolio regeneration. This is not evidence that the reported five largest profits are fabricated: their input OHLCV agrees exactly across three stored source snapshots. The two findings must be kept separate.

Review scope: read-only inspection of `analysis/run_semiconductor_cycle_v2_pilot.py`, `analysis/semiconductor_cycle_portfolio_audit.py`, `analysis/compare_semiconductor_cycle_entries.py`, their result artifacts, certified price rows, source snapshots and corporate-action tables. No production/research code or database rows changed. This document is the only file created by this review.

The numbers below refer to the **pre-calendar-repair** artifacts inspected during this review. They must not be presented as post-repair performance.

| Inspected artifact | SHA-256 |
|---|---|
| `analysis/run_semiconductor_cycle_v2_pilot.py` | `5010951fd4ef8cb774acc61bd7f682611a18469a09ddf2912c7fcec315a32ced` |
| `analysis/semiconductor_cycle_portfolio_audit.py` | `c0bc965590420611491897ec775562482dd5c526b8db77cbeaef22a732b2ac27` |
| `analysis_results/semiconductor_cycle_v2/portfolio_summary.csv` | `6ddb7ac8ebb39fb3a09177d659cab893e40a6f6bba49e9aa7e9c2055bc1f0591` |
| `analysis_results/semiconductor_cycle_v2/pilot_metrics.csv` | `3ab4b924a046b9a6db5b5d190d0106a7c038f437c4bcf09796aded9de45a69f5` |

## P0 — A field-completeness filter deletes real trading sessions

`load_panel()` reads `fact_index_daily` as the exchange calendar but requires positive index open, high, low and close. The model itself uses only index close. On 2026-03-24, 25 and 26 the official-normalized relation has valid closes but NULL open/high/low, so the WHERE clause deletes the entire session.

| Session | `fact_index_daily`, code 1001 close | Index O/H/L | Certified pilot stock rows | Source-snapshot stock counts, CREON / Naver / KIS |
|---|---:|---|---:|---|
| 2026-03-24 | 5553.92 | NULL | 116 | 1248 / 1269 / 2809 |
| 2026-03-25 | 5642.21 | NULL | 116 | 1248 / 1269 / 2810 |
| 2026-03-26 | 5460.46 | NULL | 116 | 1248 / 1269 / 2810 |

The pilot calendar jumps directly from March 23 to March 27. This is a calendar bug, not an absence of stock prices. It changes daily returns, ATR, setup windows, market moving averages, next-open execution, H-session exits, stop monitoring, mark-to-market, bootstrap blocks and the rolling split boundaries.

Concrete reproduction: 017900 closes at 2015 on March 23, 2615 on March 24, 3395 on March 25, 3175 on March 26 and 3250 on March 27. Reindexing to the defective calendar creates a false one-session return of +61.29%. Similarly 007810's March 23-to-27 +38.16% is incorrectly compressed into one session.

Other stock-price dates absent from the pilot calendar are 2017-09-22 (30 stocks), 2017-12-20 (33), 2022-01-03 (66) and 2022-05-09 (69). These also require reconciliation because they affect training history. The three 2026 dates above have been directly checked against index rows and three source families; the older dates were identified by calendar-versus-stock coverage and need the same date-by-date verification.

Do not solve this by blindly copying the convenience index relation. On March 23, `fact_index_prices` reports KOSPI 5405.75 while `fact_index_daily` reports 5466.49. For this model, retaining validated `fact_index_daily` close-only rows is the minimal correction for the confirmed missing dates. More generally, separate exchange-session existence from optional index-field availability; missing market input should yield `MARKET_UNKNOWN`, not removal of the date.

The highlighted H3 recovery / next-open / all-regimes / CAP6_THEME2 portfolio has no direct holding crossing those three missing sessions. That does **not** exempt it: upstream features, subsequent opportunities and fold boundaries change. Other chains do contain positions crossing the missing period, including nine next-open H10 contraction-breakout opportunities. Recompute all chains and all dependent artifacts under a new manifest.

## Source audit of the five largest highlighted profits

The five trades' entry and exit prices reproduce the portfolio returns after the documented 0.15% cost on each side:

`net_return = exit_close * 0.9985 / (entry_open * 1.0015) - 1`.

| Code | Hypothetical entry → exit | Entry open | Exit close | Net return | Account P&L |
|---|---|---:|---:|---:|---:|
| 042700 | 2026-02-25 → 2026-02-27 | 210500 | 323500 | +53.22% | KRW 8,863,721 |
| 089030 | 2026-03-04 → 2026-03-06 | 51300 | 71100 | +38.18% | KRW 6,355,714 |
| 219130 | 2026-01-19 → 2026-01-21 | 26250 | 34200 | +29.90% | KRW 4,974,953 |
| 098460 | 2026-04-23 → 2026-04-27 | 33400 | 43500 | +29.85% | KRW 4,972,356 |
| 036540 | 2026-01-27 → 2026-01-29 | 5450 | 6860 | +25.49% | KRW 4,248,356 |

Checked stock-session windows were: 042700 February 23–27 (5 rows), 089030 March 3–6 (4), 219130 January 16–21 (4), 098460 April 21–27 (5), and 036540 January 26–29 (4). For every window, `fact_price_source_snapshot` contains `creon_daily_bridge`, `finance.naver.com` and `kis_adjusted`: **22 stock-session rows × 3 sources = 66 snapshots**. Maximum differences versus clean open, high, low, close and volume were all exactly zero for all 15 stock/source groups. `fact_daily_prices`, labelled `kis_adjusted`, also agrees for these rows.

No primary-source switch occurs within those windows. A further check of all 126 closed holding windows in the highlighted portfolio found no change in `primary_source` inside any holding window. This is a local continuity check, not a full historical adjustment audit of feature lookbacks.

The largest profit is not a single mysterious 53% daily jump. For 042700, the closes are 214500, 275500 and 323500 on February 25, 26 and 27, respectively. The large return accumulates across the three holding sessions. The April 098460 trade likewise includes 32550 → 42300 → 43500 closes. Large multi-session returns alone are not a basis for deleting these winners.

### What the source match does not establish

- All snapshots were collected retrospectively in August 2026, months after the trades. They do not prove what StockPulse actually possessed at the original signal times. This remains historical reconstruction, not prospective shadow evidence.
- Matching provider labels do not prove fully independent upstream price generation. In particular, adjusted historical series may agree because they share action conventions or underlying data.
- Neither `research_corporate_action_index` nor `kis_corporate_action_raw` returned actions for these five codes in the checked December 2025–May 15, 2026 window. An empty, possibly incomplete action table is **not proof of no action**.
- No raw-exchange unadjusted tape, certified adjustment-factor ledger, original auction orders or contemporaneous execution reports were inspected. Therefore the correct conclusion is **“stored three-source OHLCV parity confirmed; PIT/raw-exchange/execution certification unresolved”**, not “actual realized trades verified.”

For scale only, hypothetical entry quantity divided by full-day volume was 0.0074%, 0.0027%, 0.5634%, 0.0201% and 0.0590% for the five listed trades. None is obviously excessive relative to full-day volume, but full-day liquidity cannot certify opening-auction liquidity or the assumed fill price.

## Concentration and interpretation of the +46.80% result

Highlighted chain: `STRONG_THEME_PULLBACK_RECOVERY__NEXT_OPEN_CAPPED__H3__ALL_REGIMES`, policy `CAP6_THEME2`.

Pre-repair closed P&L is KRW 46,797,281 over 126 closed trades on KRW 100 million initial capital. Total winning P&L is KRW 110,779,185; total losing P&L is KRW −63,981,904.

| Attribution diagnostic | Share of total net account profit |
|---|---:|
| Largest trade | 18.94% |
| Top 3 trades | 43.15% |
| Top 5 trades | 62.86% |
| Top 10 trades | 105.73% |
| Largest net-contributing stock, 080220 | 17.30% |
| Best exit-month, January 2026 | 44.90% |

The fixed-ledger sum excluding the top ten trades is **KRW −2,683,592**, or −2.68% of initial equity. Excluding the best net stock leaves +38.70% of initial equity; excluding the best exit-month leaves +25.79%. These are **attribution sensitivities without capital reallocation**, not investable exclusion-strategy backtests or revised maximum drawdowns. They show dependence on a small number of outsized winners, not that any single stock alone determines all profits.

The same chain's three pre-repair portfolio policies were:

| Policy | Total return | MDD | Mean close exposure | Closed trades |
|---|---:|---:|---:|---:|
| CAP5_THEMEANY | +43.40% | −8.62% | 19.48% | 122 |
| CAP6_THEMEANY | +40.58% | −7.40% | 17.92% | 134 |
| CAP6_THEME2 | +46.80% | −6.33% | 16.84% | 126 |

The theme cap looks favourable in this retrospective sample, but its lower exposure is part of the comparison. It is not enough to conclude that theme diversification itself has a stable causal advantage. The reported +0.51% opportunity mean and +46.80% account return are different estimands: the latter sums repeated fixed-slot allocations, rejects many opportunities and changes the accepted stock set. Their numerical difference is not itself a formula error or proof of a superior selector.

## Remaining code/design issues after the calendar correction

### P1 — An entry-cap order does not freeze executable share quantity

`replay()` reserves a cash budget at signal time but sets quantity only upon observing the eventual fill price: `floor(reserved / (fill_price * (1+fee)))`. For a preplaced limit order that gaps down, this buys more shares than the quantity that could have been submitted using the fixed limit. For next-open auction orders, it also assumes exact budget-targeted sizing at an unknown auction price.

This is not evidence of outcome-return selection—the fill price is read when the session arrives—but it is a favorable execution abstraction. Either declare an explicit cash-notional order facility actually supported by the modeled execution venue, or freeze share quantity using the known order cap/limit, then release unused cash after the fill. Compare the difference before interpreting account-level precision. Entry and exit liquidity/price-limit states remain unmodeled.

### P1 — The theme cap is a primary-label cap, not full overlapping exposure

The evaluator retains one strongest theme context per stock/session and counts only `order['theme']`. A stock with multiple semiconductor memberships consumes only one label's allowance. This is a reproducible primary-theme allocation rule but does not implement the design's stricter “count every overlapping exposure” contract. Call it a primary-theme cap, or carry the full known membership set and count all relevant exposures. Neither establishes independence of semiconductor subthemes.

### P1 — The executed setup definitions still differ from the planned quantile replacement

`setup1` still hard-gates drawdown between −2.5% and −15%, then adds ATR-quantile bounds. Therefore the study evaluates a **fixed-percentage gate intersected with an ATR quantile gate**, not replacement of the arbitrary percentage interval. `setup2` still requires current drawdown ≤−2.5%; the planned “a pullback occurred during the previous ten sessions” state is not represented as a dated sequence. The contraction threshold is now applied, but the setup name should not imply a fully implemented three-step event lifecycle.

These do not automatically imply look-ahead, but they are material hypothesis/manifest differences. State the actual definitions rather than interpreting results as the originally registered alternatives. Do not expand the search opportunistically to fix weak performance.

### P1 — Rejected/unknown observation coverage and empty months need full-calendar reporting

The final `no_trade_months` denominator is the months that have signal rows, not every evaluation month. The highlighted chain has no July 2026 signal rows, so its pilot metric reports zero no-trade months despite an empty July. Build monthly reporting on the complete outer-evaluation calendar, and distinguish no new fills, no positions and reserved-cash-only months.

There are 12 opportunity rows with NaN ranking scores across the 24-chain ledger. Sorting NaN last is deterministic but should be an explicit `RANK_UNAVAILABLE` policy, not an undeclared eligibility fallback. Verify whether such rows were admitted after higher-ranked candidates exhausted.

### P1 — Input provenance and execution qualifications remain weaker than the unit-test label

The executable panel discards `primary_source`, `reference_source`, adjustment basis, action evidence and retrieval time after extraction. A generic `ohlcv_cross_verified` marker is insufficient to enforce per-trade action and PIT semantics. Preserve immutable input digests and source metadata alongside the panel, even if pure computation consumes only numeric fields. Do not label `qa_status=PASSED_UNIT_TESTS` as independent research qualification.

Quantile adequacy checks count setup rows, not the number of valid observations in each calibrated feature. The minimum counts for `gap90`, `depth50` and `contraction50` should be recorded separately; a valid 100-row setup does not guarantee 100 valid forward-depth labels. Current calibrations have finite values, but absence of field-specific counts prevents auditing the statistical adequacy claim.

## Checks that did not reveal a new formula/future-selection defect

- The code now calculates limits in ATR price units and invalidates limit ≤ stop.
- Entry day counts as H=1; the per-event execution loop preserves an observed early stop despite later missing data and keeps a filled-but-unresolved position's return unknown.
- Portfolio admission ranks by signal-time score/code/id, reserves cash and capacity before future fill outcomes, and does not use future profit to choose candidates.
- New candidates are reserved after the session close; closing proceeds do not finance that same day's already-placed opening orders.
- Cash includes reserved cash once; reservations are not double-counted as NAV assets. The cost formula agrees between event returns and closed-trade accounting.
- The paired entry comparison is explicitly same-candidate next-open comparison, not an all-eligible-stock selection test. Its pointwise, unadjusted intervals and previously exposed 2026 period are disclosed. These are necessary qualifications, not promotion evidence.

These positive checks do not override the calendar NO-GO or certify actual fills.

## Required exit from this review

1. Repair session existence independently of optional index OHLC fields; verify the seven discrepant dates. Add a regression fixture with valid index close, NULL O/H/L and complete stock prices: the date must survive and count toward H.
2. Regenerate the entire feature/fold/event/entry-comparison/portfolio artifact set and record new source/code/result hashes. No partial refresh that leaves old panels with new portfolio summaries.
3. Keep pre-repair figures explicitly superseded, not silently overwritten as if never reported. Recheck source parity and concentration against the new accepted-trade set.
4. Report primary-theme-cap semantics, order-sizing approximation, full-calendar empty months, source/action/PIT limits and tail-winner dependency alongside any corrected result.
5. Maintain research-only/no automatic promotion. A passing unit suite and attractive retrospectively selected account path do not establish reliable trading income.

## Addendum — four historical sessions verified, no inferred market prices

After the three March 2026 dates were restored through index close-only rows, the following four dates remained absent from `fact_index_daily` code 1001. Read-only source-snapshot checks establish strong, explicit evidence of session existence:

| Date | Naver snapshot stocks | KIS-adjusted snapshot stocks | Exact paired OHLCV rows | Clean cross-verified stock rows |
|---|---:|---:|---:|---:|
| 2017-09-22 | 929 | 1976 | 554 | 437 |
| 2017-12-20 | 940 | 2005 | 573 | 453 |
| 2022-01-03 | 1086 | 2395 | 873 | 711 |
| 2022-05-09 | 1093 | 2420 | 904 | 736 |

The paired row count requires identical stock/date/open/high/low/close/volume between `finance.naver.com` and `kis_adjusted`, not merely both sources containing a date. On all four dates, 000660 has exact matching OHLCV and positive volume in both sources. For example, September 22, 2017 has O/H/L/C = 82900/84300/82000/83100 and volume 5,970,218; December 20 has 80900/81600/79900/80100 and volume 4,375,810. The 2022 dates additionally have KOSDAQ150 index code 2203 close rows, 1521.90 and 1189.52, respectively. No KOSPI row was found in the convenience relation either.

**Recommendation:** add these four explicit verified dates to a versioned session-override set, retaining the queried evidence counts and override reason. Reindex stock features to that restored calendar and consume each actual certified stock bar. Leave the missing KOSPI close as NaN; do not forward-fill it, synthesize it or substitute KOSDAQ150 levels. `market_down` is unknown wherever the required KOSPI close/60-session history is unavailable; the market-veto policy must remain blocked there until the prescribed history is again complete. Price-only policies can continue if their own stock/theme data contract is satisfied.

This restoration is supported by stored source evidence, not represented as a newly acquired official exchange-calendar document. No additional holiday inference is required to keep a date with hundreds of independently labelled, positive-volume stock records in the research timeline. Future calendar changes should still reconcile explicit exchange-calendar evidence and source coverage rather than automatically trusting every stray stock date.

Important unit caveat discovered during this check: on 2017-09-22, 005930 Naver volume is 278,448 while KIS-adjusted volume is 13,922,400, exactly 50 times larger. December 20 shows 201,611 versus 10,080,550, also 50 times. The prices are approximately/effectively adjusted onto the same nominal scale, but the volume conventions differ. Thus broad source-date existence supports the session restoration; it does **not** certify universal OHLCV adjustment-unit compatibility. Preserve the existing cross-verification filters and do not multiply historical monetary flow or turnover by a mismatched adjusted share volume.

Acceptance fixture: remove only KOSPI index data on a known session while retaining valid stock prices. That session must remain in the calendar; stock ATR and holding-day counts must use it; market state must be unknown rather than bullish, zero-return-filled, or compressed out of history. The four verified historical overrides and the three March 2026 close-only dates should have explicit regression assertions.

청산 실험 · 독립 재검토

# Frozen-N exit diagnostic — independent review

Date: 2026-09-09. Scope: read-only source, fixtures, manifest and generated exit artifacts. No code or database modifications. This review does not report a winning exit or endorse an optimal sell rule.

## Decision: old exit artifacts invalidated pending correction

**NO-GO for accepting the inspected six-cell comparison as completed QA.** Two confirmed execution-contract defects must be corrected in a common engine and all dependent artifacts regenerated. The coordinating agent accepted both findings and assigned correction. This document reviews the old implementation, not the subsequently repaired version.

Inspected manifest code hash: `81781a90ee565edd7858a29a0de3a30dfef9c461c53498435d96313803fcab6f`. Its `COMPLETE_BASE_EXACT` / `PASSED_FIXTURES_BASE_EXACT` status proves reproduction of the old pilot on the observed rows; it does not establish equivalent execution semantics between BASE and challengers or correct handling of unseen missing-field cases.

## P0-1 — challengers silently changed the initial structural stop

`_base_replay()` uses the original float S0. `_exit_replay()` sets `active = floor_tick(S0)`, with `floor_tick` implemented as whole-KRW floor. Therefore TP2N and the **not-yet-activated** trail start with a different protective stop from BASE. The trade ledger retains the same original `stop` field, so comparing stored entry fields alone does not expose the effective-stop difference.

Reproduction: E=100, S0=90.5, N=5, a later bar low=90.25 and no +2N activation. Actual BASE exits at 90.5; the inactive trail with stop 90 does not stop and can survive to H10. This is a synthetic fractional-price counterexample demonstrating a violated contract, not a claim about the size of the observed performance bias.

Observed magnitude: all 110 inactive-trail `STOP` rows have modeled exit price different from the original S0, with maximum difference approximately **0.9934 KRW**. In ordinary integer-priced bars this mostly changes the exit price by less than one won; it does not justify claiming the actual result was inflated by the large synthetic-example difference.

Required correction: identical initial effective S0 in every cell. If a common tick policy is deliberately changed, change BASE too, regenerate the reference and audit its difference from the frozen pilot. New target/trail rounding must not modify the original protective stop before activation.

## P0-2 — separate BASE engine erases known exits and is not the tested BASE path

The production loop calls `_base_replay()` for BASE, but `_self_tests()` tests `_exit_replay(..., 'BASE_S0_H10')`. These are different functions with different event ordering.

With a held position, known opening price 89 below S0=90.5 and missing same-bar low/close, actual `_base_replay()` returns `DATA_UNAVAILABLE`; `_exit_replay()` correctly records the known opening `STOP_GAP`. An opening exit does not need later fields to become known. Matching the old pilot's missingness bug is not a correctness certificate.

The challenger engine also checks high and close before processing a known intraday stop. With O=100, L=89 below an active stop and H/C missing, it returns unknown even though the conservative protective-stop event is established. An inactive trailing rule never needs high to establish that stop.

Required correction: one common ordered engine for all cells, used by both `main()` and fixtures. Process necessary opening events first, then a known intraday protective stop, then target/close/trail transitions using only the fields each transition needs. Missing later information cannot erase an already established exit. Compare the corrected BASE against frozen pilot artifacts explicitly; if the common correctness repair changes outcomes, record the difference rather than forcing equality to a flawed reference.

## Checks passed in this review

- The registry contains exactly two setups × three exits at H10. Cost 0.30% and 0.60% are sensitivities, not additional selected exit strategies.
- Across each common opportunity, stored fill price, original S0 and frozen signal N are identical. BASE output exit date/price also matches the old source ledger on the inspected generated rows. These checks do not negate the effective-stop defect above.
- Direct execution of `_self_tests()` passed. The `pytest` launcher was unavailable in the inspected main virtual environment (`No module named pytest`), so no successful pytest run is claimed here.
- Additional direct fixtures confirmed close-only activation, next-session stop effectiveness and monotonic ratcheting: a first close at 130 with E=100/N=5 creates a following-session 115 reference; a subsequent lower close does not loosen it, and a later opening gap at 114 exits at 114.
- The target opening event correctly precedes a later low: opening above the target exits at the conservative target level. Without an opening exit, a complete bar touching both target and stop uses stop first and marks ambiguity.
- N is taken from the signal ATR and not adaptively recomputed. The new target remains E+2N, subject to the declared numerical rounding.
- The cost formula applies the specified charge on both sides. Shared-cash replay uses placement-time share quantities, next-session fills, reservations and causal release of closing proceeds. Different exits can legitimately change later admissions; that is not pure paired exit alpha.
- No-fill opportunities remain present, and unresolved held outcomes retain unknown returns. The remaining exception is the known-event/missing-later-field defect above.

## P1 — incomplete reporting and remaining qualification boundaries

1. `changed_entry_count` is NaN in all 12 account rows. Calculate BASE/challenger accepted-fill overlap and differing admission reasons by setup and cost. The event-paired comparison isolates exit effects; account differences also include capital reuse and replacement entries.
2. Metrics need explicit observed paired counts, unmatched-known/unknown counts and matched return means. Having known challenger returns but missing BASE is not an observed paired delta.
3. All six contraction-breakout account rows are flagged `performance_incomplete=True`. Their numeric NAV is provisional and must not be advertised as finalized account performance. Preserve the flag prominently in any web/table presentation.
4. The report discloses a **1-KRW numerical approximation**, not a verified historical tick/auction contract. This is sufficient only for a labeled research approximation, not actual order qualification. Auction capacity, locked limits, gaps without executable liquidity and real slippage remain unverified.
5. The wrapper test currently delegates to a short self-test block. Add independent assertions calling the actual common production engine for fractional S0, known opening exit with later missing fields, known intraday stop with missing close, target-opening priority, same-bar ambiguity, nonactivation from high alone, frozen N, monotonic trail and future-prefix invariance.
6. Preserve hashes of imported execution/account logic and the output artifacts alongside the script and input hashes. A changed imported replay function can alter account results even if the exit-script hash remains unchanged.

The risk-policy run already rejected the candidate entries under the fixed planned-loss constraint. Targets and a trail that activates only after a gain do not remedy the initial exposure before that gain. Maintain **unqualified-entry / retrospective diagnostic only**, irrespective of the corrected exit comparison's direction. A +2N target is not +2R, a 3N trail first activated at +2N need not lock a profit, and a full target exit is not the UI's conditional partial-reduction policy.

## Re-review gate

Regenerate all six cells and both cost sensitivities only after the shared-engine fixtures pass. Recheck effective S0 equality, actual BASE dispatch, source-reference mismatch audit, paired coverage, causal state transitions and account overlap/incomplete flags. Record old artifacts as superseded. A subsequent review may pass numerical research QA; it must still withhold execution qualification, optimal-exit claims and promises of stable income.

## Corrected-version addendum — bounded numerical QA accepted

The preceding findings are retained as the review of superseded code. Re-review of `010b50d3796686ba16d281986c5fcb5ea58b3cf5e975875471ca2573d880e243` confirmed that both P0 defects were fixed: BASE and challengers dispatch through one common causal engine, use identical original fractional S0 before activation, and preserve known opening/intraday stops without requiring irrelevant later fields. Actual output BASE exit dates/prices matched the frozen pilot; inactive-trail STOP price minus S0 was exactly zero.

One additional boundary case was identified and, at the coordinating agent's explicit request, minimally corrected in this review: a missing opening price with known low below S0 does not reveal whether the sale would occur at a worse opening gap. The common engine now returns `DATA_UNAVAILABLE` when the current opening price is missing, nonfinite, zero or negative, rather than manufacturing an exact S0 fill. A known executable opening stop remains resolved even with all subsequent OHLC fields missing. No strategy, parameter, ranking or entry rule was changed.

Final reviewed source hash: **`4f8efe43199b3f140caf2f5ac01f295e82e2a43db82d5a66ada32a8b4a5f0729`**. The test file now contains three unittest methods, including 15 invalid-opening subcases across the three rules and three known-opening-gap cases. `venv/bin/python3 -m unittest discover -s tests -p test_semiconductor_cycle_exits.py` passed all three methods. The common-engine self-tests also cover fractional S0, opening target precedence, intraday stop-first, close-only activation and next-session trail behavior.

The entire unchanged six-cell/two-cost job was replayed to the isolated directory `/tmp/semi-exit-review-6vVJCn`, without overwriting the original numeric results. It produced 1,503 event rows and 12 cell/cost summary rows, with BASE reference difference count zero. The following **seven artifacts were byte-for-byte identical** to the corrected pre-guard outputs: event ledger, event metrics, account summary, account daily NAV, account actions, account closed trades and the report. Thus the added opening guard did not alter any current reported result; the frozen price panel contains no partial rows with unknown open and known low.

The isolated manifest differed only in the source-code hash. After confirming all seven result files were identical, the existing result manifest's source hash was updated to the final reviewed hash above; its output hashes are unchanged. The imported portfolio-source digest also matched. The temporary replay remains available for comparison and no database or production-service changes were made.

### Reporting checks after correction

- Exactly six registered cells remain, with 0.30%/0.60% cost sensitivities and no new search.
- Per-opportunity fill price, original S0 and frozen N are invariant across the three exits.
- Matched coverage is explicit: 243 observable opportunity pairs per recovery cell and 257 per contraction-breakout cell; one contraction opportunity remains unknown. No unmatched known outcomes are hidden in these current pairs. These are opportunity pairs and include no-fill zero outcomes, not 243/257 necessarily executed trades.
- Account accepted-fill intersections, additions, removals and symmetric-difference counts are populated and satisfy the set-count identities. They are not presented as pure exit alpha: changing exit time can change later entries.
- All six contraction-breakout account/cost rows remain `performance_incomplete=True`. Both the artifacts and report explicitly flag the unresolved account state. Their numerical NAV must remain provisional; the correction does not authorize finalized performance claims for them.
- The whole-KRW target/trail approximation and absence of historical tick/auction qualification remain disclosed. Initial S0 is now common and is no longer silently rounded differently by rule.

**Latest decision:** accept the final-hash implementation and its frozen outputs for the limited six-cell **retrospective numerical diagnostic**, with pointwise/unadjusted uncertainty and explicit missing-outcome coverage. The prior implementation NO-GO is resolved for this bounded run. This is not statistical proof of return superiority, approval of incomplete account NAV as final, permission for live execution, a validated optimal sell rule, or a remedy for the failed initial-risk/liquidity gate.

후보 데이터 대기 · 보완 전 진단

# Semiconductor-cycle DATA_WAIT read-only audit

Service-equivalent read model asof: `2026-09-08`; cache asof: `2026-09-08`; expected session: `2026-09-08`.
Observed candidates: 6; DATA_WAIT: 5.

## Findings

- DATA_WAIT reasons are preserved exactly in `data_wait_audit_candidates.csv`; no clean/certified data was patched.
- Theme recent-20 coverage is expanded by theme/date/member in `data_wait_audit_theme_sessions.csv`; certification is `ohlcv_cross_verified`.
- ATR coverage is expanded by code/date in `data_wait_audit_atr_missing.csv`; 098460 is included explicitly.
- Index evidence latest official session is `2026-09-08`; index-1001 close-positive on expected date: `True`. This is source evidence only, not a holiday-calendar certification.

No API/service/database changes were made.

가격 인증 누락 · 보완 결과

실행·검토 중입니다. 결과가 저장되면 이 페이지에 표시됩니다.

과거 실제 거래대금 · 별도 데이터 부착

# Actual KRX turnover attachment

Data-only attachment. Existing proxy turnover and factor columns were preserved. The actual KRX source, monetary unit, complete-session windows, and missing/known-zero distinction are recorded in the manifest and coverage CSV. Candidate-date coverage reads only the six pre-specified opportunity metadata columns; outcome/performance columns are not read. PIT and corporate-action continuity are not claimed as fully verified.

종목 우선순위 · 후속 검증 설계

# Fixed-candidate ranking study — feasibility and frozen protocol

Status: DESIGN ONLY / NO MODEL FITTING OR NEW PERFORMANCE MINING. The coordinating agent explicitly expanded the initial six-cell proposal to **eight cells before this study's outcomes were inspected** so that price-only learning is distinguishable from price/flow/finance learning. This change is part of the preregistration, not a result-driven extension.

## 1. Feasibility checkpoint

Only schema, date coverage and observation counts were inspected. The current corrected pilot has the following **raw setup counts before final candidate filters, label maturity and inner splitting**; these are upper bounds on usable training samples, not approvals to fit:

| Outer block / training end | Recovery events / dates | Contraction-breakout events / dates |
|---|---:|---:|
| 1 / 2025-10-15 | 227 / 55 | 165 / 42 |
| 2 / 2026-01-15 | 373 / 94 | 246 / 71 |
| 3 / 2026-04-20 | 777 / 146 | 493 / 123 |

The frozen H5 evaluation opportunities contain 243 recovery events on 79 dates and 258 contraction-breakout events on 74 dates. Median candidates per date is only two in both setups. A top-three rule can exclude a same-day candidate on only 23/79 recovery dates and 28/74 breakout dates; a top-five rule differs from taking all candidates on only 10/79 and 15/74 dates. These are **candidate-count diagnostics**, not performance results. A large average return on mostly singleton/two-stock dates cannot establish ranking skill.

The inspected factor manifest reports 165,174 stock-session rows but only 1,295 recorded monetary-turnover rows; 163,879 use a flagged proxy. Verified flow history begins in August 2023. The coordinating agent reports that the new actual-turnover backfill begins on 2025-10-01 and is still running. Therefore the enriched model is **not currently cleared to fit**; its early training folds are likely unavailable even after that backfill. The price-only model may also fail the fixed sample floors after candidate filtering and inner splitting. Report unavailable cells rather than lowering the floors or replacing the enriched model silently.

No claim is made that eight trainable cells exist. The useful first output is an eight-cell/fold availability matrix with exact reasons.

## 2. Exactly eight registered cells

Use the existing two setup definitions, H=5, `NEXT_OPEN_CAPPED`, `ALL_REGIMES`, common structural stop/time exit and base cost. Preserve the corrected pilot's candidate dates, theme-context selection and feature definitions; do not discover new setups, widen pullback gates or optimize entry/exit parameters.

Each setup has four ranking policies:

1. `TRANSPARENT`: existing frozen `score_asof` rank; deterministic stock-code tie-break.
2. `SEEDED_RANDOM`: deterministic SHA-256 ordering of `20260909|setup|signal_date|stock_code`. Do not use Python's process-randomized `hash`, resample seeds or choose a lucky realization. It is one registered comparator, not a randomness significance test.
3. `HISTGB_PRICE`: the fixed nonlinear regressor using the price allowlist below.
4. `HISTGB_PRICE_FLOW_FINANCE`: the same regressor with the declared validated flow/finance additions; unavailable if its own data/fit gates fail. It is not relabelled price-only when inputs are missing.

Thus 2 setups × 4 policies = **8 cells**. `ALL_CANDIDATES` is an explicitly unranked common-opportunity benchmark, reported separately, not another selected ranking strategy. No additional seeds, ensemble, learner, rank cutoff or hyperparameter search is permitted.

Use **top three** as the sole ranked short list, retaining fewer if fewer eligible observations exist. Ranks four and five may be shown as descriptive reserve observations, but no alternate top-five performance trial is run. Ties use stock code. All candidates remain in the ledger; list exclusion is not deletion from the opportunity population.

## 3. Model and strict feature boundary

Reuse `HistGradientBoostingRegressor(max_iter=100, max_leaf_nodes=7, min_samples_leaf=50, l2_regularization=1, learning_rate=0.05, early_stopping=False, random_state=20260909)`. No randomized early-stopping split or tuning. Pin the actual installed scikit-learn version and digest. The fixed transparent and random policies require no fitting.

Price allowlist, all available by the signal decision: `ret1`, `ret3`, `ret5`, `ret20` (the pilot's absolute 20-session return currently named `rs20`), `drawdown10_atr`, `tr5_atr20`, `close_location`, `atr20_over_close`, `theme_breadth`, `theme_slope5`, `theme_ret5`. Rename only to clarify semantics; do not claim `rs20` is market-relative when the source computes an absolute return. All price features must be finite, valid and on the same certified adjustment basis.

Enriched additions: `foreign_net3_over_trade_value3`, `core_institution_net3_over_trade_value3`, `quarter_opm_fraction`, `quarter_revenue_yoy_fraction`, `quarter_age_days`. Core institution = institution minus financial investment only when both are valid. Monetary flow must be KRW; the denominator is actual compatible KRW trading value over the exact same three restored exchange sessions, positive in aggregate. **Do not normalize by `close × volume` or treat proxy trading value as actual.**

Financial features require a causal exact-disclosure actual single-quarter snapshot and its comparable prior-year quarter; same-day uncertain releases are excluded conservatively. Select the latest fiscal period first, then the latest version actually available by t within that period. Preserve receipt/source/vintage and age; no annual fallback, cumulative/derived-quarter substitution, consensus or latest-current snapshot backfill. Apply the existing data-validity/freshness contract, not profit/OPM/YoY **selection thresholds**. The model may learn from valid negative growth/margins; unknown is not bad quality or zero.

Keep metadata, features and labels in separate tables. The model matrix is constructed from an exact ordered allowlist, not by dropping known bad columns. Explicitly reject `next_open`, `future3_low`, `gap_next`, `depth3_atr`, `fill_*`, `exit_*`, `net_return`, `MAE`, `MFE`, `label_end`, outcome statuses, candidate ID, stock code, date and current quality/cache scores as model inputs. A string prefix blacklist alone is insufficient.

For this small study, use complete validated feature rows rather than imputing unknown supply/finance into fictional observations. Missing enriched features make that row unavailable **to the enriched model only**. Preserve native coverage counts and matched comparisons; do not change the price-only or transparent universe behind the scenes.

## 4. Training labels, purging and fixed availability floors

Reuse historical candidate construction and entry execution from the corrected pilot, with fold-training-only quantiles. The existing saved OOS event ledger is **not** a ready-made training set for its own dates. Build historical training events causally, without importing future test quantiles, future source availability or current memberships as though historically certified. Retain the disclosed current-basket retrospective limitation.

Primary label for a fully resolved historical event is its next-open-capped/structural-stop/H5 **net opportunity return**, including zero for known no fills, minus the same-setup/same-signal-date mean among the predeclared eligible candidates with fully observable labels. This removes the common same-day setup return from the ranking target; the future-return mean is a **training label only**, never a feature. Do not train on incomplete same-day target cross-sections. Dates with one candidate have no cross-sectional ranking information and are excluded from model fitting, but retained in full evaluation/coverage/account reporting.

Use the existing three outer chronological blocks. Inside each outer training history, reserve the last 63 exchange sessions as a single fixed development-validation block. Purge the inner fit set by actual label-end session, with at least five-session separation for this fixed next-open H5 protocol; retain the outer pilot's conservative gap. Training labels must be fully resolved before the relevant fit/validation boundary. No panel-row random splits, full-sample scaling or future calibration.

Fixed preflight floors for **each model and each fit**: at least 300 eligible mature event rows, 60 distinct signal dates, 20 stocks and 30 dates with at least two eligible candidates after the declared feature contract. The 300-row floor is six minimum leaves of 50; it is a conservative implementation adequacy choice, not a guarantee of learning. Inner validation requires at least 60 eligible events, 20 dates and five dates with more than three eligible candidates. These floors are frozen before fitting; do not reduce them to rescue an empty cell.

If either inner fit or validation availability fails, mark that model/outer fold `NOT_RUN_INSUFFICIENT_SAMPLE`, retaining transparent/random reference outputs. Do not fit a shallower model, borrow future events or train on test data. If adequate, fit once, report fit-sample diagnostics and the untouched inner validation metrics versus transparent/random/all-candidate references. **Do not select a parameter or suppress the outer result because inner performance looks bad.** Refit the unchanged model on the full eligible outer training set, then freeze predictions for that outer test block.

This design evaluates a fixed learner, not a winning inner model. Pool outer inference only if at least two outer blocks run adequately; otherwise report a one-block pilot without a stability claim. A missed model fold is not a zero-return prediction or secretly substituted baseline model.

## 5. Fair comparisons and portfolio accounting

Report both native feature coverage and a **common eligible date/stock set** for each model-versus-transparent/random comparison. Recompute all compared ranks within that same set before taking top three. Also report all-policy common coverage when enriched rows exist. A gains table caused by dropping low-coverage observations is not proof that finance or flow improved ranking.

Primary descriptive outputs: per-date top-three mean net opportunity return, same-date all-candidate mean, top-three-minus-all spread, and paired spread difference versus transparent and seeded random. No-fill is zero, unresolved outcome is unknown. Report rankings on dates with >3 candidates separately from dates where top three necessarily equals all. Include rank IC only on adequately populated, nonconstant date cross-sections; do not turn a singleton into a successful rank prediction.

Bootstrap full date cross-sections using the corrected exchange calendar and existing block method. Do not resample individual stocks independently or report in-sample fit metrics as validation. Intervals are pointwise/unadjusted across the registered comparisons, not multiplicity-adjusted proof of alpha. Do not select the seed, model or horizon from the largest outer point estimate.

Secondary account replay uses the same initial virtual capital, fixed E0/6 slots, `CAP6_THEME2` primary-theme limit, placement-time integer quantity, no leverage, cash/slot reservations, cost and entry/exit semantics. Each day's frozen top-three short list supplies that policy's order attempts; a capacity/cash rejection must not silently pull rank four into one policy only. Admission never reads future fills/returns. All-candidate reference means the common unranked opportunity basket, not a fantasy infinitely funded account; any account reference must state its actual capacity/order rule.

Different rankings legitimately produce different accepted holdings. Report accepted-fill overlap, additions/removals, cash/exposure, duplicate/capacity/theme/cash rejections and account P&L concentration. Freeze full calendar start/end across cells, including no-signal months. When a model is unavailable for a fold, do not present a stitched cash fallback as evidence that its ranking beat the market; compare only the same available folds and show the unavailable interval explicitly.

Actual-turnover backfill must be complete and audited before creating the frozen enrichment version. Do not let a running collector gradually improve one policy's historical data while other cells use an older snapshot. Liquidity availability is not an outcome. This experiment introduces no liquidity/8% risk gate variation: those independently failed/insufficient safety policies remain separate, and all ranking outputs remain **research observations, not qualified trades**.

## 6. Limited robustness and acceptance criteria

If useful and adequately populated, predeclare **attribution-only** sensitivity excluding the single largest-contributing evaluation date and separately the single largest-contributing stock from the paired-spread summary. Label these outcome-selected deletions as fragility diagnostics, not alternative executable strategies or new tuned rankings. Do not refit to exploit the exclusions. A result dominated by either deletion cannot support a stability claim. Low sample counts may make these checks unavailable.

Required fixtures: future-field mutation leaves earlier predictions unchanged; exact feature allowlist rejects every label column; labels never cross fit boundaries; stock/date membership deduplication does not inflate sample counts; fixed seed gives identical ranking across processes/input row order; singleton/top-three-all dates contribute no artificial selection lift; incomplete PIT/flow/monetary units block only the affected model row; native versus matched coverage is explicit; failed folds never fit; no-fill and unknown outcomes differ; shared-cash admission never consults future outcome completeness; model scores do not alter the original entry prices/stops.

Save the eight-cell/fold availability registry **before fitting**, then input/protocol/code/dependency hashes, train/validation counts, fit/validation/outer diagnostics, immutable OOS predictions, per-date comparison/coverage tables and separate account ledgers. Report all eight cells, including unavailable ones. No selective reporting of the successful price-only branch under an enriched-model name.

## 7. Handoff decision

Proceed first with **read-only preflight counts**, not model fitting. On the currently inspected inputs, the enriched learner is data-blocked and price-only fitting is conditional on the strict post-filter/inner-split floors; it is entirely possible that no model fold qualifies. If so, deliver the frozen plan and explicit shortage rather than inventing a trained model.

All 2026 evaluation dates were previously exposed through other research. Even an adequately populated outer comparison is retrospective and current-basket-biased, not untouched confirmation. Top-three/five observation lists and a six-position simulation cannot become live recommendations through ranking quality alone while entry-risk, liquidity, source/PIT and prospective-validation gates remain unresolved.

추세 채널 가설 · 하단 근접/상단 이격 검증

# 반도체 소부장 추세 채널 가설 검증

## 방법

- Creon 5분봉 121종목을 일봉으로 집계했다.
- 각 날짜의 채널은 **직전 60거래일만**으로 로그가격 선형추세와 잔차 15·85백분위 채널을 계산했다. 따라서 미래 저점·고점을 연결하지 않는다.
- 하단 근접은 상승 기울기에서 일중 저가가 하단선 +0.45 ATR 이내이고 종가가 하단선−0.45 ATR 이상인 경우다.
- 상단 과이격은 상승 기울기에서 종가가 상단선+0.20 ATR 이상이면서 직전 EMA20보다 1.25 ATR 이상 높은 경우다.
- 80% 선행 구간과 마지막 20% 홀드아웃을 분리해 결과를 저장했다.

## 읽는 법

`event_summary.csv`의 `holdout_lb60`이 핵심이다. 하단 근접은 같은 상승추세 기준선보다 3·5일 수익률/상승비율이 일관되게 높을 때만 지지 가설을 지지한다. 상단 과이격은 이후 수익률이 낮거나 음수일 때만 조정 가설을 지지한다. 표본이 적은 개별 종목 결과는 단독 규칙으로 사용하지 않는다.

## 핵심 결과 (사전 지정 60일 채널)

| 표본 | 사건 | 기간 | 건수 | 평균 수익률 | 상승 비율 |
|---|---|---:|---:|---:|---:|
| train_lb60 | lower_touch | 3일 | 3,524 | +1.16% | 49.9% |
| train_lb60 | lower_touch | 5일 | 3,524 | +1.68% | 49.4% |
| train_lb60 | upper_stretch | 3일 | 2,264 | +1.74% | 50.7% |
| train_lb60 | upper_stretch | 5일 | 2,264 | +2.96% | 52.8% |
| train_lb60 | positive_trend_baseline | 3일 | 12,182 | +1.48% | 52.0% |
| train_lb60 | positive_trend_baseline | 5일 | 12,182 | +2.52% | 53.0% |
| holdout_lb60 | lower_touch | 3일 | 780 | -4.30% | 31.5% |
| holdout_lb60 | lower_touch | 5일 | 773 | -7.24% | 25.9% |
| holdout_lb60 | upper_stretch | 3일 | 101 | -5.53% | 22.8% |
| holdout_lb60 | upper_stretch | 5일 | 99 | -9.16% | 19.2% |
| holdout_lb60 | positive_trend_baseline | 3일 | 1,987 | -3.45% | 33.1% |
| holdout_lb60 | positive_trend_baseline | 5일 | 1,968 | -5.81% | 28.5% |

해석은 학습·홀드아웃 양쪽에서 같은 방향이어야 한다. 어느 한 구간에서만 성과가 좋아도 곧바로 매수 규칙으로 채택하지 않는다.

## 산출물

- `event_summary.csv`: 룩백별 전체·홀드아웃 이벤트 통계
- `stock_holdout_summary.csv`: 종목별 홀드아웃 3일 통계(3건 이상만)
- `latest_channel_state.csv`: 마지막 관측일의 채널 위치
- `episode_regime_summary.csv`: 연속 터치를 하나의 사건으로 묶고 시장 내부 강약을 나눈 검증

## 후속 검증 · 캔들 회복과 수급 결합

121종목 중 하루 31% 초과 가격 단절이 있는 112290, 356860, 417840, 482630를 보수적으로 제외한 117종목 민감도 분석이다. 기업행위 수정계수를 임의 추정하지 않았다. 사후 품질 선별이므로 실전 재현 성과가 아니다.
수급이 함께 확보된 2026-08-26까지 사용. 검증 시작 2026-06-11. 학습 구간의 보유기간이 검증 구간을 넘으면 제외했다.
60일 채널 하단에 당일 또는 직전 2일 접근한 뒤 양봉·전일 대비 상승·종가 위치 CLV≥0.25를 회복으로 정의했다. 외국인 또는 기관−금융투자 순매수 금액이 양수일 때 수급 확인으로 정의했다.
모든 비교는 수급 확인 가능한 공통 표본에서 다음 날 시가 진입, 3·5·10거래일째 종가 청산, 왕복 비용 0.30% 가정이다. 동일 종목 보유기간은 겹치지 않는다.
비교군은 같은 날 양의 채널 기울기를 가진 종목이다. 그룹 강세는 전일까지 20일 수익률의 소부장 종목 중앙값이 양수인 상태다.

| 구간 | 조건 | 보유일 | 사건 | 종목 | 날짜 | 순수익 평균 | 상승률 | 같은 날 비교군 | 초과수익 |
|---|---|---:|---:|---:|---:|---:|---:|---:|---:|
| development | touch | 5 | 963 | 114 | 138 | 0.77% | 49.1% | 0.95% | -0.18% |
| holdout | touch | 5 | 199 | 84 | 39 | -8.25% | 21.6% | -8.36% | 0.10% |
| development | touch_recovery | 5 | 741 | 114 | 115 | 0.25% | 45.9% | 0.67% | -0.42% |
| holdout | touch_recovery | 5 | 149 | 74 | 23 | -9.58% | 20.8% | -9.51% | -0.06% |
| development | touch_recovery_flow | 5 | 702 | 113 | 112 | 0.51% | 46.3% | 0.78% | -0.28% |
| holdout | touch_recovery_flow | 5 | 140 | 70 | 24 | -9.55% | 20.0% | -9.25% | -0.30% |
| development | touch_recovery_both | 5 | 411 | 111 | 103 | 0.22% | 43.6% | 0.84% | -0.61% |
| holdout | touch_recovery_both | 5 | 62 | 43 | 20 | -9.94% | 14.5% | -10.96% | 1.02% |
| development | touch_recovery_flow_group_up | 5 | 381 | 109 | 68 | 0.97% | 48.0% | 1.10% | -0.13% |
| holdout | touch_recovery_flow_group_up | 5 | 1 | 1 | 1 | -4.00% | 0.0% | -8.65% | 4.65% |

판단: 사건 평균 수익률과 같은 날 비교군의 차이를 함께 보아야 한다. 하단 접촉 뒤 큰 손실만으로 하단선 자체가 위험을 설명한다고 결론 내릴 수 없다. 앞선 단순 평균 비교는 시장 하락 영향을 충분히 통제하지 못했다.

5일 결과에서 단순 하단 접근은 비교군 대비 +0.10%p, 캔들 회복+한 주체 순매수는 −0.30%p, 양 주체 동반 순매수는 +1.02%p였다. 날짜별 초과수익의 참고 신뢰구간이 모두 0을 포함하므로 재현 가능한 우위는 아직 확인되지 않았다. 그룹 강세 결합은 홀드아웃 1건으로 판단 불가다.

조건들을 이번에 추가 탐색했으므로 기존 홀드아웃도 재사용한 탐색 결과다. 별도 미래 검증 없이 검증 완료 신호로 승격하지 않는다.
현재 121종목 구성 기준의 생존편향, 기업행위 수정기준의 불완전한 확인, 종목 간 동조화가 남아 있다. 이 채널은 저점 두 개를 연결한 추세선과도 다르므로 원래 가설 전체를 기각하는 근거는 아니다.
원자료: confirmation_summary.csv, confirmation_events.csv, confirmation_manifest.json. 신뢰구간은 날짜별 초과수익을 5개 관측일 블록으로 재표집한 참고치이며 다중검정 보정 전이다.

## 상승 강도·가격 패턴별 재검증

이번 결과: 분류가 필요하다는 지적은 타당하다. 최근 검증 구간 6,201개 종목×날짜 중 강한 상승은 275개(4.4%)뿐이다. 전체 평균으로 강한 상승 종목의 규칙을 판단하기 어렵다.

그러나 분류 후에도 이번 60일 회귀채널의 하단 접근은 안정적인 우위로 확인되지 않았다. 매끄러운 강한 상승은 개발구간 5일 +1.24%(112건), 최근 검증 −5.27%(13건). 진동형 강한 상승은 개발구간 −0.21%(78건), 최근 검증 −8.07%(34건)다. 진동형의 최근 대응 초과수익 +1.37%p는 참고 신뢰구간 −2.06~+4.33%p로 불확실하다.

이 결과는 강한 상승추세의 매매 가치가 없다는 뜻이 아니다. 과거 20일 상승률·이평선 배열이 유지돼도 급격한 전환 초기에 분류가 늦을 수 있고, 회귀채널 하단과 실제 확인된 저점 연결 지지선은 다르다. 현재 결과로 신호를 적용하거나 가설 전체를 기각하지 않는다.

20·60일 수익률 양수, 종가>60일선, 20일선>60일선, 20일선 상승을 상승추세로 정의. 그중 20일 수익률 ≥ 23.4%는 강한 상승이다. 상승 구간 학습표본의 중앙값으로 기준을 고정했다.
가격 이동 효율 = |20일 가격변화| / 20일 절대 일간 가격변화 합. 효율 ≥ 0.267는 매끄러운 추세, 그 미만은 진동형으로 분류했다. 진동형은 주기 존재를 확정한 분류가 아니다.
분류는 전일 정보만 사용하며 종목마다 매일 달라진다. 가격 단절 4종목 제외한 117종목, 2026-08-26까지. 다음날 시가 진입, 비용 0.3%. 같은 종목 보유기간 중복 제외.
비교군은 같은 날·같은 패턴의 다른 종목 3개 이상이다. 대응 표본이 없는 사건은 절대수익 통계에는 포함하되 초과수익에서 제외했다.

| 구간 | 패턴 | 조건 | 사건 | 대응사건 | 5일 순수익 | 승률 | 대응 초과수익 |
|---|---|---|---:|---:|---:|---:|---:|
|development|강한상승_매끄러운추세|하단접근|112|111|1.24%|49.1%|0.04%p|
|holdout|강한상승_매끄러운추세|하단접근|13|8|-5.27%|38.5%|-4.25%p|
|development|강한상승_매끄러운추세|하단접근_회복|44|44|-0.65%|36.4%|-1.72%p|
|holdout|강한상승_매끄러운추세|하단접근_회복|7|6|-16.57%|14.3%|-0.92%p|
|development|강한상승_매끄러운추세|하단접근_회복_수급|37|37|0.43%|37.8%|-0.24%p|
|holdout|강한상승_매끄러운추세|하단접근_회복_수급|7|6|-16.57%|14.3%|-0.92%p|
|development|강한상승_매끄러운추세|상단과이격|385|385|1.89%|50.9%|0.36%p|
|holdout|강한상승_매끄러운추세|상단과이격|13|11|-12.28%|23.1%|-5.02%p|
|development|강한상승_진동형|하단접근|78|66|-0.21%|48.7%|-0.30%p|
|holdout|강한상승_진동형|하단접근|34|33|-8.07%|35.3%|1.37%p|
|development|강한상승_진동형|하단접근_회복|41|37|-0.97%|51.2%|-0.96%p|
|holdout|강한상승_진동형|하단접근_회복|14|14|-13.48%|28.6%|0.86%p|
|development|강한상승_진동형|하단접근_회복_수급|37|34|-0.72%|51.4%|-0.65%p|
|holdout|강한상승_진동형|하단접근_회복_수급|14|14|-13.48%|28.6%|0.86%p|
|development|강한상승_진동형|상단과이격|58|50|4.35%|53.4%|2.64%p|
|holdout|강한상승_진동형|상단과이격|15|14|-13.81%|6.7%|1.35%p|
|development|완만한상승|하단접근|454|448|1.59%|49.6%|0.14%p|
|holdout|완만한상승|하단접근|59|57|-8.54%|20.3%|-0.95%p|
|development|완만한상승|하단접근_회복|316|313|0.39%|44.6%|-0.51%p|
|holdout|완만한상승|하단접근_회복|37|37|-11.42%|10.8%|-0.07%p|
|development|완만한상승|하단접근_회복_수급|296|293|0.50%|45.6%|-0.53%p|
|holdout|완만한상승|하단접근_회복_수급|35|35|-10.77%|11.4%|0.10%p|
|development|완만한상승|상단과이격|246|246|0.82%|48.8%|-0.34%p|
|holdout|완만한상승|상단과이격|6|5|-5.56%|16.7%|1.98%p|
|development|최근하락|하단접근|550|548|0.44%|47.6%|-0.03%p|
|holdout|최근하락|하단접근|140|140|-7.63%|24.3%|-0.06%p|
|development|최근하락|하단접근_회복|430|429|1.01%|48.4%|-0.09%p|
|holdout|최근하락|하단접근_회복|104|104|-8.16%|24.0%|-0.48%p|
|development|최근하락|하단접근_회복_수급|412|411|1.24%|47.8%|-0.09%p|
|holdout|최근하락|하단접근_회복_수급|94|94|-7.70%|24.5%|-0.13%p|
|development|최근하락|상단과이격|19|19|10.65%|47.4%|9.13%p|
|holdout|최근하락|상단과이격|3|3|-14.61%|0.0%|-3.75%p|
|development|하락후반등|하단접근|25|24|1.50%|48.0%|-0.48%p|
|holdout|하락후반등|하단접근|5|5|-7.00%|0.0%|0.37%p|
|development|하락후반등|하단접근_회복|11|10|-0.47%|36.4%|-4.88%p|
|holdout|하락후반등|하단접근_회복|3|3|-7.20%|0.0%|-2.09%p|
|development|하락후반등|하단접근_회복_수급|11|10|-1.48%|27.3%|-4.53%p|
|holdout|하락후반등|하단접근_회복_수급|3|3|-7.20%|0.0%|-2.09%p|
|development|하락후반등|상단과이격|17|16|7.70%|58.8%|4.05%p|
|development|횡보_혼조|하단접근|142|125|1.19%|52.8%|0.10%p|
|holdout|횡보_혼조|하단접근|35|28|-10.18%|17.1%|1.19%p|
|development|횡보_혼조|하단접근_회복|82|72|0.72%|50.0%|0.02%p|
|holdout|횡보_혼조|하단접근_회복|26|19|-10.78%|19.2%|-0.88%p|
|development|횡보_혼조|하단접근_회복_수급|72|65|0.23%|48.6%|-0.27%p|
|holdout|횡보_혼조|하단접근_회복_수급|26|19|-10.78%|19.2%|-0.88%p|
|development|횡보_혼조|상단과이격|41|38|3.05%|43.9%|2.53%p|
|holdout|횡보_혼조|상단과이격|12|12|-13.52%|0.0%|-5.26%p|

후속 탐색이므로 독립 확증은 아니다. 유사 종목의 사건이 같은 날 몰릴 수 있으며, 적은 검증 날짜와 비교군 누락을 확인해야 한다. 가격 단절 종목 제외는 사후 품질선별이다.
상세: pattern_summary.csv (3·5·10일 및 날짜 블록 신뢰구간), pattern_events.csv, pattern_latest.csv, pattern_composition.csv.

## 5~10일 반등 기회와 실현 수익 검증

결론: 10일 내 진입가 대비 +3.3%에 한 번 도달하는 비율은 저점 상승 지지선 접근 81.8%(33건), 수축 후 3일 고점 돌파 76.9%(13건), 조정 후 회복+수급 75.0%(28건)였다. 이는 손절 이후의 반등도 포함한다. 동일 조건에 +3.3% 목표·−5% 손절과 비용을 반영하면 순수익은 각각 −1.28%, −0.83%, −2.63%다. 확률이 높다는 이유만으로 수익성 우위로 평가할 수 없다.

우선 연구 방향: (1) 저점 상승 지지선 근처의 가격대를 관찰 후보로 유지, (2) 수축 후 단기 고점 회복을 진입 확인 후보로 유지, (3) 단순 양봉과 당일 순매수 결합은 우선순위를 낮춘다. 다음 연구의 목적함수는 손절 전에 목표 도달할 확률·비용 후 기대수익·신호 이후의 진입 대기기간을 함께 평가하는 것이다. 이번 고정 손절·목표는 최적값이 아니며 향후 최적화 시 새 검증 구간이 필요하다.

117종목, 2026-08-26까지. 전일 기준 20·60일 수익률 양수, 상승하는 20일선>60일선, 종가>60일선인 구간만 사용. 가격 단절 4종목은 기존 감사와 동일하게 제외.
확인된 두 저점 상승을 이용한 지지선도 검사했다. 저점은 좌우 2일 저가 비교 후 2일 뒤에만 알려진 것으로 처리. 두 저점 간격 ≥3일, 최근 60일 범위. 이후 선형 연장선 ±0.6 ATR 접근.
신호 다음날 시가 진입. 반등은 진입가 대비 +3.3% 고가 도달(비용 0.3% 후 +3% 목표)이며, 손절 발생 뒤 반등도 포함하는 기회 지표다. 별도로 −5% 손절·+3.3% 목표 청산, 미도달시 5·10일 종가 청산 수익을 계산했다. 갭 손절은 시가, 같은 날 양쪽 도달은 5분봉 순서로 확인하고 같은 5분봉에서 양쪽 도달하면 손절 우선이다.
같은 종목 보유기간 중복 제외. 동일 날짜의 다른 상승추세 종목 3개 이상을 비교군으로 사용. 이미 본 검증 구간 재탐색이므로 독립 확증 결과는 아니다.

|구간|조건|기간|사건|반등도달률|도달일 중앙값|기간말 순수익|목표·손절 순수익|반등확률 차이|
|---|---|---:|---:|---:|---:|---:|---:|---:|
|development|상승추세전체|5|1340|74.9%|1.0|1.26%|-0.55%|-0.8%p|
|holdout|상승추세전체|5|121|71.1%|1.0|-7.57%|-1.31%|0.3%p|
|development|상승추세전체|10|788|81.6%|2.0|4.18%|-0.34%|-3.0%p|
|holdout|상승추세전체|10|72|68.1%|1.0|-13.49%|-1.48%|-8.3%p|
|development|조정2_12pct|5|1006|74.7%|1.0|1.67%|-0.23%|-0.8%p|
|holdout|조정2_12pct|5|66|69.7%|1.0|-5.93%|-1.28%|-4.3%p|
|development|조정2_12pct|10|651|82.2%|2.0|3.70%|-0.36%|-1.6%p|
|holdout|조정2_12pct|10|50|68.0%|1.0|-12.60%|-1.32%|-11.0%p|
|development|조정_양봉회복|5|401|70.6%|2.0|0.67%|-0.67%|-1.7%p|
|holdout|조정_양봉회복|5|31|61.3%|1.0|-10.22%|-2.35%|1.6%p|
|development|조정_양봉회복|10|331|84.0%|2.0|5.59%|-0.64%|0.7%p|
|holdout|조정_양봉회복|10|28|75.0%|1.0|-14.26%|-2.63%|5.8%p|
|development|조정_회복_수급|5|357|69.2%|2.0|0.48%|-0.81%|-2.0%p|
|holdout|조정_회복_수급|5|31|61.3%|1.0|-10.48%|-2.62%|4.1%p|
|development|조정_회복_수급|10|301|83.4%|2.0|5.61%|-0.70%|0.9%p|
|holdout|조정_회복_수급|10|28|75.0%|1.0|-14.26%|-2.63%|5.8%p|
|development|조정_수축후3일고점돌파|5|121|75.2%|2.0|2.01%|-0.09%|2.2%p|
|holdout|조정_수축후3일고점돌파|5|14|64.3%|1.0|-9.87%|-0.56%|-8.6%p|
|development|조정_수축후3일고점돌파|10|116|83.6%|2.0|5.34%|-0.09%|1.9%p|
|holdout|조정_수축후3일고점돌파|10|13|76.9%|1.0|-14.06%|-0.83%|0.1%p|
|development|저점상승_지지선접근|5|600|73.7%|1.0|1.17%|-0.47%|-0.9%p|
|holdout|저점상승_지지선접근|5|44|68.2%|1.0|-9.65%|-0.96%|1.6%p|
|development|저점상승_지지선접근|10|453|82.1%|2.0|2.86%|-0.39%|-2.6%p|
|holdout|저점상승_지지선접근|10|33|81.8%|1.0|-11.47%|-1.28%|4.0%p|
|development|저점상승_접근_회복수급|5|298|71.8%|1.0|0.83%|-0.27%|-0.9%p|
|holdout|저점상승_접근_회복수급|5|17|47.1%|1.0|-12.73%|-1.88%|-14.0%p|
|development|저점상승_접근_회복수급|10|249|80.7%|2.0|3.18%|-0.54%|-1.3%p|
|holdout|저점상승_접근_회복수급|10|13|76.9%|2.0|-15.73%|-1.47%|-2.3%p|
|development|조정_회복수급_그룹상승|5|272|71.0%|2.0|0.28%|-0.79%|-0.9%p|
|development|조정_회복수급_그룹상승|10|238|85.3%|2.0|4.66%|-0.73%|1.5%p|

목표가 접촉만으로 체결을 보장하지 않는다. 같은 5분봉 내 순서는 손절 우선으로 평가했다.
8개 규칙을 탐색했고 비용·손절·목표는 비교용 가정으로 최적화하지 않았다. 기업행위·현재 종목 구성 편향과 작은 검증표본 한계가 남는다. 원자료: rebound_window_summary.csv, rebound_window_events.csv.

## 진입 가격·대기기간 비교

결론: 0.5 ATR 눌림은 개발구간에서 사전 선택됐고 최근 29기회 중 23체결, 목표 선도달 19건(82.6%), 체결당 +1.88%, 미체결 포함 기회당 +1.49%였다. 같은 기회에서 다음날 시가 매수는 −1.87%였다. 비용을 0.6%로 높여도 0.5 ATR 방식의 기회당 수익은 +1.26%다.

하지만 인접 가격 민감도 검증에서 0.4 ATR은 체결당 −0.76%, 0.6 ATR은 −0.53%로 뒤집혔다. 0.5 ATR 한 점의 높은 성과를 최적 매수가로 채택하지 않는다. 표본이 작고 인접 가격에서 수익이 유지되지 않는 불안정한 연구 후보이며, 매수 추천 서비스에는 반영하지 않았다.

수축 후 돌파는 개발구간에서 선택한 0.25 ATR 지정가가 최근 8체결에서 −2.19%였다. 최근 결과를 보고 0.5 ATR로 선택을 바꾸면 사후 선택이므로 채택하지 않는다.

지지선 접근과 수축 후 돌파만 연구. 신호 다음날 시가 vs 신호 종가 / 종가−0.25·0.5·1 ATR 지정가. 지정가는 3거래일 대기 후 취소. 체결일부터 10거래일, 목표 +3.3%, 손절 −5%, 비용 0.3%. 5분봉으로 체결·청산 순서를 계산. 0.4·0.6 ATR은 결과 확인 후 추가한 민감도 검사이며 최적정책 선정에 포함하지 않았다.
미체결은 기회당 수익 0%로 포함. 이는 포트폴리오 수익률이 아니며, 기다리는 동안 다른 투자 기회는 계산하지 않는다. 모든 방식에 동일 신호·전체 12일 관측 가능한 표본을 적용하고 종목별 12일 중복 제외. 개발구간에서 기회당 수익이 높은 방식을 선정해 최근 구간을 비교했다.
지정가가 5분봉 중간에 체결되면 그 봉의 앞선 고가로 목표 청산하지 않는다. 같은 봉 목표·손절은 손절 우선. 호가·주문대기순서·가격단위는 반영하지 않은 연구용 체결 가정이다.

|조건|구간|진입방식|기회|체결률|체결당 순수익|기회당 순수익|시가 대비 차이|개발선정|
|---|---|---|---:|---:|---:|---:|---:|---|
|저점상승_지지선접근|development|limit_025atr|373|79.4%|0.02%|0.02%|0.30%p|False|
|저점상승_지지선접근|development|limit_040atr|373|66.2%|0.19%|0.13%|0.41%p|False|
|저점상승_지지선접근|development|limit_050atr|373|61.1%|0.51%|0.31%|0.59%p|True|
|저점상승_지지선접근|development|limit_060atr|373|56.3%|0.61%|0.34%|0.62%p|False|
|저점상승_지지선접근|development|limit_100atr|373|39.4%|0.38%|0.15%|0.43%p|False|
|저점상승_지지선접근|development|limit_close|373|88.2%|-0.26%|-0.23%|0.05%p|False|
|저점상승_지지선접근|development|next_open|373|100.0%|-0.28%|-0.28%|0.00%p|False|
|저점상승_지지선접근|holdout|limit_025atr|29|89.7%|-0.41%|-0.36%|1.50%p|False|
|저점상승_지지선접근|holdout|limit_040atr|29|86.2%|-0.76%|-0.66%|1.21%p|False|
|저점상승_지지선접근|holdout|limit_050atr|29|79.3%|1.88%|1.49%|3.36%p|True|
|저점상승_지지선접근|holdout|limit_060atr|29|72.4%|-0.53%|-0.39%|1.48%p|False|
|저점상승_지지선접근|holdout|limit_100atr|29|27.6%|-2.01%|-0.56%|1.31%p|False|
|저점상승_지지선접근|holdout|limit_close|29|93.1%|-1.70%|-1.59%|0.28%p|False|
|저점상승_지지선접근|holdout|next_open|29|100.0%|-1.87%|-1.87%|0.00%p|False|
|조정_수축후3일고점돌파|development|limit_025atr|111|83.8%|0.84%|0.71%|0.82%p|True|
|조정_수축후3일고점돌파|development|limit_040atr|111|67.6%|1.05%|0.71%|0.83%p|False|
|조정_수축후3일고점돌파|development|limit_050atr|111|59.5%|0.76%|0.45%|0.57%p|False|
|조정_수축후3일고점돌파|development|limit_060atr|111|51.4%|0.74%|0.38%|0.50%p|False|
|조정_수축후3일고점돌파|development|limit_100atr|111|32.4%|1.01%|0.33%|0.44%p|False|
|조정_수축후3일고점돌파|development|limit_close|111|92.8%|0.55%|0.51%|0.63%p|False|
|조정_수축후3일고점돌파|development|next_open|111|100.0%|-0.12%|-0.12%|0.00%p|False|
|조정_수축후3일고점돌파|holdout|limit_025atr|11|72.7%|-2.19%|-1.59%|-0.82%p|True|
|조정_수축후3일고점돌파|holdout|limit_040atr|11|63.6%|-0.56%|-0.35%|0.42%p|False|
|조정_수축후3일고점돌파|holdout|limit_050atr|11|63.6%|0.72%|0.46%|1.23%p|False|
|조정_수축후3일고점돌파|holdout|limit_060atr|11|54.5%|-0.92%|-0.50%|0.27%p|False|
|조정_수축후3일고점돌파|holdout|limit_100atr|11|54.5%|0.49%|0.27%|1.04%p|False|
|조정_수축후3일고점돌파|holdout|limit_close|11|90.9%|-1.15%|-1.05%|-0.27%p|False|
|조정_수축후3일고점돌파|holdout|next_open|11|100.0%|-0.77%|-0.77%|0.00%p|False|

이미 탐색한 최근 구간 재사용이며 독립 검증은 아니다. 표본·날짜 수가 작고 4개 가격단절 종목 제외, 현재 종목구성 편향이 남아 있다. 원자료: entry_wait_summary.csv / entry_wait_trades.csv.

## 매끄러운 상승 5종목 · 조정 징후

최근 20일 선형성이 높은 5종목을 사후 선택한 기술적 점검이다. 미래에 선별 가능했던 전략의 검증이 아니다. 당일 종가에 징후 확인 후 다음 5거래일 중 종가가 5% 이상 낮아지는 경우를 조정으로 정의. 직전일 20일 수익률 양수·20일선 상승·종가>20일선인 구간을 사용했다.
징후별 같은 종목 5일 중복 제외. 종목 간 같은 날 동조화, 조건별 표본 날짜 차이, 사후 종목선정 편향 때문에 아래 비율을 현재의 조정 확률로 사용하지 않는다. 캔들수축은 (고가−저가)/직전 ATR20≤0.7, 이격확대는 (종가−MA20)/ATR20≥2다.

|징후|사건|이후 조정|비율|
|---|---:|---:|---:|
|10일선이탈|48|18|37.5%|
|5일선이탈|69|20|29.0%|
|거래증가하락|43|16|37.2%|
|기준상승구간|104|43|41.3%|
|둔화와5일선이탈|58|18|31.0%|
|상승속도둔화|86|26|30.2%|
|외인핵심기관동반매도|46|17|37.0%|
|윗꼬리_저가권종가|43|13|30.2%|
|이격확대|53|24|45.3%|
|캔들수축|45|14|31.1%|

|종목|가격일|3일 변화|5일선 이격|10일선 이격|거래량 배수|최근 징후|
|---|---|---:|---:|---:|---:|---|
|티에프이|2026-09-08|2.17%|1.01%|5.90%|0.36|상승속도둔화 / 이격확대 / 캔들수축|
|HPSP|2026-09-08|6.18%|3.29%|4.65%|1.25|윗꼬리_저가권종가|
|피에스케이홀딩스|2026-09-08|13.13%|4.94%|11.64%|1.27|이격확대|
|티씨케이|2026-09-08|9.98%|3.93%|6.61%|0.97|윗꼬리_저가권종가|
|마이크로컨텍솔|2026-09-08|13.95%|6.99%|9.38%|1.22|이격확대 / 캔들수축|

최근 수급은 별도 패널이 8/26까지만 있어 9/8 수급으로 해석하지 않았다. 상세: five_correction_symptoms.csv, five_correction_latest.csv.
## 맞춤 조정신호 · 최근 1년 차트 적용

기간 2025-09-09~2026-09-08. 차트에서 사용하는 일봉과 동일한 계산기로 5종목을 재생했다. 오늘 진행 중인 봉은 제외. 40거래일 준비기간 및 가격 단절 점검 후 계산한다.
조정주의: 종목별 과열·상승실패 징후. 조정진행: 주의 조건 이후 5일선 아래 하락 또는 전일 저가 이탈+2% 이상 하락이 이미 관측됨. 미래 하락 확정이나 매도 명령이 아니다.
주의일 고가 회복 시 해제, 관찰기간은 5거래일. 과거 발생 마커는 지우지 않는다. 마커는 당시 정보로 계산되지만 규칙을 정하는 데 같은 과거 자료를 봤으므로 성과는 독립 검증이 아니다. 가격·거래량만 사용하며 미확인 최신 수급을 0으로 가정하지 않는다.

|종목|맞춤 주의 조건|
|---|---|
|[티에프이](https://sangsoo.synology.me/stock-picks/425420)|20일선 대비 2 ATR 이상 이격 + 상승속도 둔화 또는 캔들 수축|
|[HPSP](https://sangsoo.synology.me/stock-picks/403870)|윗꼬리 40% 이상·저가권 종가 + 거래량이 직전 20일 중앙값 이상|
|[피에스케이홀딩스](https://sangsoo.synology.me/stock-picks/031980)|직전일 2 ATR 이상 이격 후 2% 이상 하락·저가권 종가|
|[티씨케이](https://sangsoo.synology.me/stock-picks/064760)|20일선 대비 5% 이상 이격 + 윗꼬리 40% 이상·저가권 종가|
|[마이크로컨텍솔](https://sangsoo.synology.me/stock-picks/098120)|20일선 대비 2 ATR 이상 이격 + 캔들 수축 + 상승속도 둔화 또는 비상승 종가|

|종목|신호|표시 건수|평가완료|이후 5일 추가 5% 하락|평균 5일 변화|
|---|---|---:|---:|---:|---:|
|티에프이|조정주의|10|8|4/8 (50.0%)|+5.47%|
|티에프이|조정진행|4|4|2/4 (50.0%)|+4.65%|
|HPSP|조정주의|6|5|3/5 (60.0%)|-4.09%|
|HPSP|조정진행|8|8|3/8 (37.5%)|+0.08%|
|피에스케이홀딩스|조정주의|3|3|1/3 (33.3%)|+1.72%|
|피에스케이홀딩스|조정진행|11|10|2/10 (20.0%)|+3.71%|
|티씨케이|조정주의|2|1|0/1 (0.0%)|+4.97%|
|티씨케이|조정진행|5|4|2/4 (50.0%)|+6.38%|
|마이크로컨텍솔|조정주의|4|3|0/3 (0.0%)|+13.13%|
|마이크로컨텍솔|조정진행|2|2|0/2 (0.0%)|+6.40%|

추가 하락은 신호일 종가보다 이후 5거래일 중 종가가 5% 이상 낮아진 경우다. 조정진행 당일 이미 발생한 하락은 성과에 포함하지 않았다. 주의와 진행은 같은 에피소드일 수 있고 관측기간도 겹칠 수 있으므로 건수를 독립 표본으로 합산하면 안 된다.
운영 차트의 과거 가격이 공급처 수정주가 보정으로 변경되면 재계산될 수 있다. 최근 1년 전체의 가격 수정기준을 인증한 것은 아니다. 관찰 신호로 제공하며 현재의 하락 확률로 해석하지 않는다.
파일: custom_correction_events_1y.csv / custom_correction_summary_1y.csv / custom_correction_manifest.json / custom_correction_chart_inputs.json.