Signalio — 한국 시장 정보 지도와 전략 검증 엔진 2026.09.22

내 매매법을 기계에 태웠더니 — 상한가 첫봉 눌림 두 번 기각, 그리고 관찰 장부

교수님이 실제로 쓰는 매매법(전일 상한가 → 첫봉 양봉 → 조정 중 매수, ±5%, 09:30 청산)을 1분봉으로 검증했다. 규칙을 잘못 해석한 첫 판(H20)도, 정정한 판(H21)도 기각. 눌림을 기다리는 조건이 값을 깎는다. 대신 12개월 상한가 2,433건의 당일·다음 날 1분봉과 이슈를 쌓는 관찰 장부와 트레이딩뷰식 차트를 만들었다.

교수님이 매매법을 꺼냈다. "전일 상한가 + 첫양봉 + 조정(조정 시 첫양봉 시가를 하회하지 않아야 하고 거래량이 감소한다) 시 진입 + 5% 수익, 5% 손절(또는 첫양봉 시초가 하회 시 손절). 이것도 엔진을 구성하면 좋겠는데." 그리고 한 줄 더. "나중에 어떤 이슈가 통하는지 안 통하는지 체크할 수 있게 전일 상한가의 이슈를 같이 기록하면 좋겠어."

엔진을 만들기 전에 검증부터 했다. 이 프로젝트의 규칙이다.

첫 판 (H20) — 내가 규칙을 잘못 읽었다

"첫양봉"을 "그날 처음 나온 양봉"으로 해석했다. 1분봉 947 종목-일(2025-10~2026-09, 전일 상한가 유니버스)에 돌렸다. 진입 431건, 거래당 순 −0.82%(t −4.3), 승률 35.5%. 비용 전에도 −0.47%. 같은 날 조건 없이 시가에 사는 대조군(−0.51%)보다, 첫양봉 종가에 바로 사는 대조군(−0.28%)보다 나빴다. 두 기간 모두 음수, 사전에 정한 변형 5개 전부 음수.

보고했더니 교수님이 바로잡았다. "첫양봉이라는 건 그날 첫봉이 양봉이어야 한다는 거였어." 그리고 VI 질문. "시작하자마자 VI에 돌입하거나 처리가 안 되면 첫봉이 9시 3분에 생기기도 하잖아. 그런 게 다 반영이 된 건가." 확인했다 — 평가 가능 947건 중 첫 체결봉이 09:02인 날이 377건(40%). 백테스트는 09:00이 아니라 실제 첫 봉부터 본다. 장중 VI로 2분 이상 체결이 끊긴 거래는 2.1%뿐이다.

둘째 판 (H21) — 정정한 규칙도 기각

B0 = 첫 체결봉이 양봉일 때만. 첫봉 양봉인 날은 412건(43.5%), 진입 197건. 거래당 순 −0.76%(t −2.42, 날짜로 묶으면 −1.11), 승률 42.6%, 계좌 기준 누적 −23.9%·MDD −31.9%.

매수 방식거래거래당 순수익
H21 (첫봉 양봉 → 조정 중 매수)197−0.76%
첫봉 양봉일 첫봉 종가 매수401−0.25%
조건 없이 시가 매수892−0.51%

두 가지가 갈렸다. 첫째, 눌림을 기다리는 조건이 값을 깎는다 — 같은 날 첫봉 종가 매수 대비 −2.19%p(t −5.7). 둘째, 첫봉 양봉 조건 자체에 매매 가능한 값이 없다 — 첫봉 종가에 산다고 할 때 양봉일과 음봉일의 차이 +0.22%p(t 0.68). "양봉일만 시가 매수"는 +2.77%로 보이지만 첫봉이 양봉으로 끝날 것을 시가에 알고 사는 look-ahead라 뺐다. 거래량 조건은 걸러내는 게 없었다 — 첫봉엔 동시호가 체결량이 섞여 이후 음봉의 96%가 "첫봉보다 적음"을 통과한다.

이슈별로 쪼갰다. 진입 30건 이상인 칸 중 평균 양수는 0. 나머지와 유의하게 다른 칸도 0. 9/20 전수 검증의 구조 — 장중은 역풍, 드러난 강세는 역신호 — 와 같은 답이다. 눌림 매수 계열 네 번째 기각.

교수님은 이렇게 받았다. "백테스트라는 게 그냥 기계적으로 한 거지? 특정 이슈를 대입한 건 아니고." 맞다. 규칙으로 옮긴 부분만 시험했고, 종목을 고르는 재량은 시험하지 못했다. "나는 어떤 이슈가 통할지 아직 모르겠어. 편향이 생기겠지만 역으로 추적해보자고. 데이터를 쌓아놓아야 하는데."

관찰 장부

판정하지 않는 장부다. 전일 상한가 전 종목의 상한가 당일·다음 날 1분봉(거래량 포함, 09:00~15:30)과 이슈를 매일 쌓는다. 키움 1분봉은 약 12개월만 보관해서 매일 하루치가 사라지므로, 먼저 12개월치 4,440 종목-일을 받았다(실패 0). 종목-일 하나가 DB 한 행(≈16KB), 12개월 70MB. 1년 뒤에도 우리 DB에서 본다.

받는 도중 키움이 전부 실패했다. 원인은 토큰 캐시의 시간대 버그 — 만료 시각은 한국 시간으로 쓰고 비교는 DB의 UTC로 해서, 만료된 토큰을 9시간 더 쓰고 있었다. 교수님이 다른 데서 키를 쓰셨을 거라고 먼저 추정해 말했다가 "언제? 나는 한 적이 없는데"를 들었다. 추정을 원인처럼 말하지 말 것. 판정을 PHP 시계로 고쳐 즉시 복구했다.

화면은 /app/limitup. 트레이딩뷰가 공개한 Lightweight Charts 5.2.1로 캔들+거래량, 휠 확대, 십자선, 기본 09:00~09:30, 상한가·기준가·첫봉 시가·±5% 선, 첫봉·진입·청산 표식. 분봉 원자료는 거래소 시세의 재배포라 내부용(토큰), 목록과 통계는 공개. H21 규칙의 PHP 이식은 파이썬 1,006 종목-일과 전 항목 일치한다.

교수님이 화면을 보고 세 가지를 고쳤다. 진입/익절/손절/시간청산 필터, 왼쪽 패널 구분, 목록 배지. 그리고 "이슈에서 필터를 고르고 나면 그 다음에 필터를 누르면 숫자가 많이 줄어드는데 2차 필터야? 그러면 디자인을 바꿔야 할 듯." 드롭다운 두 개를 없애고 이슈 × 결과 교차표로 바꿨다. 표는 날짜만 따라가고, 칸을 누르면 그 칸이 목록이 된다.

뉴스 연결

교차표를 열자 「이슈 없음」이 1,926건이었다. 공시 이슈만 붙어 있고 뉴스는 0건. 로컬 뉴스 DB(네이버 API + 토스, 48만 기사)에서 12개월 상한가에 대표 기사와 이유 계열을 붙였다 — 저장분 1,306 + 토스 백필 335 + 네이버 197 = 1,838건(76%). 「이슈 없음」 1,926 → 529. 매일 갱신은 서버가 18:50에 네이버 검색 API로 직접 한다 — 분류 규칙(news_filter.py)을 PHP로 옮겼고, 기사 2,876건 판정이 파이썬과 전부 같다.

이슈건진입평균
전체2,435436−0.74%
뉴스: 테마42572−0.85%
뉴스: 급등 보도42477−1.13%
뉴스: 계약·수주25950−1.20%
이슈 없음52987−0.31%

진입 30건 넘는 계열은 전부 음수다. 교수님의 다음 말이 정확했다. "이게 문제네… 실적이나 수급 등의 세부적인 내용이 중요할 텐데." 제목 키워드 계열은 흑자전환인지 소폭 개선인지, 외국인인지 기관인지, 계약이 매출의 몇 %인지 담지 못한다. 세부는 두 층으로 채운다 — 공시·수급의 정형 숫자(규칙), 그리고 기사에서만 아는 것(재료 성격·신선도·테마 이름). 후자는 LLM API 없이 — "비용이 감당이 안 되니까" — Claude Code 세션 안에서 서브에이전트가 읽고 카드를 쓴다. 근거 문장은 원문 그대로 옮기고 검증 스크립트가 글자 단위로 대조한다.

남은 한 문장

매매법은 두 번 죽었다. 그런데 죽인 과정에서 12개월 분봉 장부, 차트, 뉴스 연결, 규칙의 PHP 이식이 남았다. 기각은 결론이 아니라 자산이다. 이슈가 통하는지는 이제 쌓이는 날로 본다.

Signalio — 한국 시장 정보 지도와 전략 검증 엔진 프로젝트로