문제: 신호는 나오는데 거래가 없다
2026년 7월 20~21일 라이브 로그를 보니 전략은 계속 BUY 신호를 내고 있는데, 실제 매수 체결은 하루종일 0건이었다. 신호 자체는 살아있는데 그게 전부 걸러지고 있다는 뜻이었다.
감으로 고치지 않고, 필터를 채점했다
어떤 필터가 범인인지 짐작으로 하나씩 꺼보는 대신, 32개 종목에서 전략이 실제로 낸 627개의 BUY 시그널(OOS, out-of-sample 구간)을 대상으로 각 조건이 신호를 차단한 비율을 계측했다.
| 조건 | 차단율 |
|---|---|
| MACD 히스토그램 ≤ 0 | 75.6% (주범) |
| 거래량 < 평균 | 62.7% |
| RSI ≥ 50 | 5.9% |
| 통과(매수 성사) | 5.6% |
숫자로 보니 범인이 명확했다. MACD 조건 하나가 전체 신호의 4분의 3 이상을 걸러내고 있었다.
어떻게 고쳤나
SignalFilter에 block_negative_macd라는 파라미터를 추가했다. 기본값은 True로 둬서 기존 동작과 완전히 같게 유지했다 — 이 변경으로 다른 곳의 동작이 바뀌지 않도록 하기 위해서다.
실제로 이 값을 끄는 건 realtime_engine의 라이브 생성 부분에서만이다. 백테스트나 다른 경로는 건드리지 않았다. RSI와 거래량 필터는 그대로 뒀다 — MACD 필터가 유독 과도했다고 판단했지, 필터링 자체가 필요 없다고 본 게 아니었다. 코드 변경 폭도 3개 파일에 32줄 추가, 5줄 삭제로 최소한으로 유지했다.
백테스트로 검증
32개 종목을 대상으로 MACD 필터를 완화한 결과와 현행을 비교했다.
| 변형 | 총거래 | 2년 평균수익률 |
|---|---|---|
| 현행 (MACD 차단) | 248 | -0.73% |
| MACD 완화 | 654 | +0.65% |
거래 수는 3배 가까이 늘었고, 평균 수익률은 마이너스에서 플러스로 전환됐다.
정직하게 남긴 한계
여기서 끝내지 않고, 이 개선이 완전한 해결이 아니라는 점도 그대로 기록에 남겼다.
Sharpe 비율은 어느 기간을 봐도 여전히 음수였다. 승률과 평균 수익률은 개선됐지만, 위험 대비 수익이라는 기준으로 보면 여전히 미달이라는 뜻이다. 근본 원인은 신호 자체에 알파(초과수익 정보)가 부족하다는 데 있었다 — ML 모델조차 정확도(cv_acc) 0.504로, 기저율 0.587보다 낮았다. 이건 이 작업 하나로 해결될 문제가 아니라 신호 파이프라인 자체를 다시 설계해야 하는 별도 과제로 남겼다.
그래서 이 변경은 “무거래 상태를 해소하고 수익률을 플러스로 전환한다”는 근거로 사용자 판단에 따라 라이브에 적용됐다 — 완벽한 전략을 만들었다는 주장이 아니라, 지금 막혀 있는 걸 풀되 남은 한계를 숨기지 않는다는 선택이었다.
테스트는 signal_filter 24건, realtime_engine 69건을 합쳐 93건이 통과했고, block_negative_macd=False일 때의 동작과 RSI·거래량 필터가 여전히 살아있는지를 확인하는 신규 테스트 2건이 추가됐다.
남는 교훈
“왜 거래가 안 되는가”는 답이 여러 갈래로 갈릴 수 있는 질문이다. 후보 필터가 여러 개일 때 하나씩 꺼보며 확인하는 것도 방법이지만, 그보다 먼저 각 조건이 실제로 얼마나 차단하고 있는지를 숫자로 재는 것이 원인을 좁히는 더 빠른 방법이었다.
그리고 승률이나 총수익률이 좋아졌다고 해서 위험조정수익(Sharpe)까지 좋아졌다고 착각하면 안 된다는 것도, 이 작업이 남긴 분명한 교훈이다. 지표는 하나가 아니고, 하나를 개선했다고 나머지가 저절로 따라오지 않는다.