본문 바로가기

카테고리 없음

주식 추천 mcp 프로젝트 - 미스 분석과 일별 스냅샷 아카이빙

320x100

픽봇에는 매주 일요일 지난 한 주의 픽을 채점하고, 그 결과로 학습 규칙을 갱신해 데일리 프롬프트에 주입하는 주간 튜닝 세션이 있다. 몇 주 돌려 보니 규칙이 실제로 쌓이고 반증되면서 제법 그럴듯하게 동작했는데, 구조적인 문제가 하나 보였다.

내가 낸 픽만 채점한다는 것이다. 전형적인 생존 편향이다. 픽한 종목이 어떻게 됐는지는 알 수 있지만, 픽하지 않은 종목 중 무엇이 급등했는지, 왜 우리 프로세스가 그걸 걸렀는지는 아무도 묻지 않는다. 필터가 과하게 조여져 있어도 성적표에는 드러나지 않는다. 걸러진 종목은 채점 대상에 아예 없기 때문이다.

그래서 이번 편은 주간 튜닝에 미스 분석을 붙인 기록이다. 결론만 보면 간단한 기능인데, "지난 주 급등주 목록"이라는 데이터를 확보하는 과정에서 시행착오를 꽤 겪었다.


 

미스 분류 기준

놓친 급등주를 그냥 나열하면 "아 저거 살걸"이라는 후회 목록밖에 안 된다. 학습으로 이어지려면 왜 놓쳤는지가 유형화돼야 한다.

유형 의미 배울 것
A. 커버리지 미스 스캔에 아예 안 잡힘 스캔 채널의 한계
B. 필터 탈락 후보엔 있었으나 필터에서 탈락 어떤 조건이 걸렀는지
C. 선택 미스 최종 후보에서 다른 종목을 픽함 최종 선택 기준
D. 포착 불가 재료 없는 폭등, 뉴스 직후 점상 없음. 미스로 치지 않는다

유형 D를 따로 둔 게 핵심이다. 이유 없는 폭등까지 잡겠다고 필터를 풀면 그게 바로 과최적화다. 놓친 아쉬움보다 잘못 잡은 손실이 더 비싸다. 같은 이유로 필터를 느슨하게 푸는 방향의 규칙은 2주 연속 같은 패턴이 확인될 때만 채택하도록 못박았다.


 

시행착오 1. 리포트 파싱

처음 떠올린 방법은 데일리 리포트 재활용이었다. 매일 리포트의 스캔 결과 섹션에 "등락률 상위: 종목(+N%), ..." 라인이 기록돼 있으니, 지난 주 리포트를 파싱하면 주간 급등주가 복원된다는 계산이었다.

그런데 이건 방향이 틀렸다. 리포트는 추천이 목적인 산출물이고, 스캔 라인은 그 부산물이다. 부산물을 데이터 소스로 쓰면 리포트 형식이 바뀔 때마다 분석이 같이 흔들리고, 역할도 꼬인다. 데이터가 필요하면 데이터를 직접 조회하는 게 맞다.

시행착오 2. 한투 순위 API의 과거 조회 한계

그래서 순위 API 직접 조회로 방향을 틀었는데, 여기서 벽에 부딪혔다. 픽봇은 하루이틀짜리 단타 봇이라 미스 분석이 봐야 할 것은 "지난 화요일에 하루 +25% 터진 종목" 같은 일별 급등주다. 그런데 공식 문서를 뒤져 확인한 결과, 한투 순위분석 계열(등락률, 거래량, 체결강도 등)은 전부 호출 시점 기준이고 과거 날짜를 지정하는 파라미터가 있는 엔드포인트는 존재하지 않는다.

누적일수 옵션으로 "최근 5일 누적 상위"는 나온다. 하지만 누적 순위에서는 매일 +3%씩 오른 스윙형이 상위를 차지하고, 정작 하루 터졌다 되돌린 단타형 급등주는 사라진다. 측정 단위가 전략의 시간 단위와 어긋나면 그 데이터는 답을 주지 않는다.

결론은 발상의 전환이었다. 소급이 안 되면 매일 쌓으면 된다.


 

일별 스냅샷 아카이빙

매일 장 마감 후 그날의 등락률 순위를 JSON으로 저장하는 스크립트를 만들었다.

movers/
├── kr/2026-09-15.json   # 평일 16시 이후 (마감 15:30)
└── us/2026-09-15.json   # 화~토 07시 이후 (그날 아침 끝난 세션 = ET 기준 전일)

실행 주체는 기존에 15분마다 돌던 동기화 작업이다. "오늘 파일이 없으면 스냅샷 실행" 조건만 추가하면 별도 스케줄 없이 붙고, API가 일시적으로 실패해도 다음 15분 틱이 자동으로 재시도한다. PC가 꺼져 있던 날은 그날 데이터가 영영 없지만, 이건 로컬 파이프라인의 태생적 한계라 받아들였다.

휴장일 처리에서 버그를 하나 만들었다 잡았다. 순위 API는 휴장일에도 직전 거래일 데이터를 그대로 돌려주기 때문에, 직전 스냅샷과 상위 10개가 동일하면 휴장으로 판정해 빈 파일을 저장하게 했다. 그런데 처음 구현은 "직전 파일"과만 비교해서, 연속 휴장(명절 연휴) 2일차부터는 비교 대상이 빈 휴장 파일이 되면서 감지가 무산됐다. 금요일 데이터가 연휴 날짜로 저장되는 구조였다. 비교 대상을 "데이터가 있는 마지막 파일"로 바꿔 해결했다.


 

분석 설계: D-1 소급 판정

데이터가 확보됐으니 분석 설계가 남았다. 처음에는 급등 이유를 뉴스로 확인하는 그림을 그렸는데, 이것도 얕은 접근이었다. 뉴스는 이벤트의 한 종류일 뿐이고, 트레이딩 봇의 미스 분석에서 중요한 건 서사가 아니라 정량 선행 신호다.

그래서 질문을 바꿨다. "왜 올랐나"가 아니라 "급등 전날(D-1) 시점에 우리 데일리 프로세스를 돌렸다면 이 종목이 통과했을까" 다.

유형 B, C 종목에 대해 급등일을 D로 놓고, 도구 데이터에서 D-1 이전 값만 잘라 우리 필터를 소급 적용한다.

  1. 수급 선행 - 일별 확정 수급 이력에서 D-1에 이미 "외인, 기관 2일+ 순매수"(통과 조건)가 충족돼 있었는가. 충족이었는데 후보에도 없었다면 스캔 문제, 직전이었다면 타이밍 문제다.
  2. 거래량 선행 - D-1, D-2 거래량이 20일 평균 대비 몇 배였는가. 1.2~1.5배로 빌드업했다면 잡을 수 있었던 급등이고, D-day에 갑자기 터졌다면 사전 포착 불가로 유형 D 재분류다.
  3. 차트 위치 - D-1 종가가 이평 위였는가, 눌림목 완성형이었는가.
  4. 상대강도 - 급등 전에 이미 지수 대비 초과수익이 양(+)이었는가.
  5. 뉴스(보조) - 급등 당일 재료 유무만 확인한다. 재료 없는 급등은 유형 D의 판별 근거가 된다.

결론은 종목마다 한 줄로 남긴다. D-1 소급 판정: 통과였음(스캔 미스) / 수급 탈락 / 차트 탈락 / 포착 불가 + 근거 수치 형태다. 유형 B가 몰려 있으면 필터가 과조임이라는 신호고, 같은 선행 패턴이 2개 이상 종목에서 반복되면 규칙 후보로 올라간다.

이 설계를 하다 보니 도구 쪽에 구멍이 하나 보였다. 시세 도구의 recent_daily(최근 일봉 배열)에 종가만 있고 거래량이 없었다. 거래량 빌드업 판단이 설계의 핵심인데 데이터가 노출이 안 되고 있던 것이다. 원본(한투 일봉, yfinance)에는 있는 값이라 응답에 필드 하나 추가하는 걸로 끝났다. 분석 설계를 먼저 그려보지 않았으면 못 찾았을 구멍이다.

남은 한계도 분명하다. 스냅샷은 도입 시점부터만 쌓이므로 첫 주는 누적 근사 폴백으로 돌고, 채점은 여전히 종가 기준 근사라 장중 터치를 못 본다.

마지막으로, 픽봇의 리포트는 내 프롬프트와 코드를 기반으로 한 참고 자료일 뿐이며 투자 판단과 책임은 본인에게 있다는 점을 유의해야 한다.

728x90