밴드 대신 채점표

화면 절반을 덮은 예측 밴드를 실데이터 시안 다섯 개 끝에 버리고, 오늘 뷰와 정확도 뷰로 갈라 220일 소급 채점과 함께 배포한 이야기.

하려던 것

주가 변동 관측기를 만드는 중이다. 개장 전에 그날의 예상 고저를 예측하고, 장중 5분마다 실제와 대조해 보여주는 관측 전용 서비스다. 첫 화면의 주인공은 예측 밴드였다. 차트 위에 “오늘 가격이 이 안에 있을 것”이라는 띠를 그리는, 이런 서비스라면 누구나 떠올릴 그 그림이다.

그런데 차트를 열 때마다 뭔가 이상했다. 예측 박스가 캔들보다 훨씬 컸다. Claude Code에 물었더니 계산 구조부터 설명해줬다. 5분봉마다 그려지는 박스는 5분짜리 예측이 아니라 “오늘 하루의 최종 고저 범위”를 슬롯마다 반복해 그린 것이고, 그 범위는 최근 20일 일중변동폭의 p95라 주 종목 기준 약 19.5%나 된다는 것이다. 커버리지 85%를 지키려면 그 폭이 필요하다고 했다.

어떻게 시켰나

말로 논쟁하는 대신 시안을 실데이터로 뽑게 했다. Claude는 로컬 HTML로 시안을 만들어 왔는데, 전부 동일한 실제 시세 데이터를 쓰고 그리는 방법만 달랐다. ① 현행 슬롯별 박스, ② 연속된 영역 띠, ③ 영역에 현재 예측선을 얹은 절충안. 나중에 ④ 밴드 채움을 아예 지우고 경계선과 KPI 숫자만 남긴 버전, ⑤ 오늘과 과거를 분리한 버전까지, 시안이 다섯 개가 됐다.

②나 ③은 분명 ①보다 나았다. 하지만 근본은 그대로였다. 폭 15~22%짜리 띠는 어떻게 그려도 차트 절반을 덮는다.

어디서 막혔나

결국 참지 못하고 말했다.

그냥 빼야 되나, 다 마음에 안 드는데? 범위가 너무 넓어서 저렇게 표현하는 게 큰 의미가 없을 듯.

Claude의 답이 인상적이었다. 반박하는 대신 자기 실측 수치를 들어 인정했다. 밴드폭이 15~22%인 순간 범위를 그림으로 보여주는 것 자체가 정보가 아니며, “주가는 오르거나 내립니다”와 다를 게 없다고. 다만 밴드의 가치는 내부가 아니라 가장자리에 있으니, 그림을 빼되 경계값 숫자·이탈 알림·정확도 이력으로 옮기자고 제안했다.

④번 시안에 과거 3일 분봉을 이어 그린 걸 보고 한 번 더 지적했다.

저점·고점은 특정 날짜에 국한된 데이터인데, 과거에는 어느 정도 맞췄다를 보여줘야지.

어떻게 풀었나

여기서 구조가 피벗됐다. 밴드 그림은 폐기. 화면을 둘로 갈랐다. 오늘 뷰는 당일 분봉만 담고, 예상 고저는 경계선과 KPI 숫자(“저점까지 −7.7%“)가 맡는다. 경계선은 가격이 접근할 때만 화면에 들어온다. 억지로 축에 우겨넣으면 캔들이 눌려 처음 문제로 돌아가기 때문이다. 정확도 뷰는 일별 예측 vs 실제 채점표다. 하루가 점선 예측박스 하나와 실제 고저 한 줄이고, 이탈한 날은 빨간 표시가 붙는다.

채점표를 채우려고 과거를 소급 채점시켰다. 각 날의 예측은 그 날 이전 데이터로만 계산해 미래 누출을 막았고, 주요 종목 220일씩 포함 총 484행에 전체 적중률 89%가 나왔다. 이 상태로 배포했다.

같은 날 “거래량을 넣으면 더 정확해지나”라는 감도 회귀로 검증시켰다. 결과는 갈렸다. 갭과 변동폭의 관계는 R² 0.03으로 기각. 전일 거래량과 당일 변동폭은 R² 0.144로 신호가 실재해서, 거래량 적응을 넣자 폭은 거의 그대로인데 적중률이 89%에서 92%로 올랐다. 다만 이 분위 스윕 중에 Claude가 루프 버그를 하나 자백했다. 기준 커버리지를 넘기는 가장 낮은 분위를 찾아야 하는데 루프가 첫 88% 지점에서 멈춰버린 것이다. 그리고 근본 질문에 대한 답도 정직했다. 밴드가 넓은 건 모델 결함이 아니라 종목이 하루 12~15% 움직이는 성질 탓이라, 어떤 피처를 넣어도 그 바닥은 못 낮춘다는 것.

배운 점