청산의 66%가 손절도 익절도 아니었다 — 로테이션이라는 세 번째 출구

예상 밖의 분포

4개월간 청산된 132건을 이유별로 나눠 봤다. 손절과 익절이 대부분일 거라 생각했는데 아니었다.

청산 이유 건수 비중 승률 평균 손익 평균 보유
로테이션 청산 87건 66% 48% +1.19% 5.8일
트레일링 청산 19건 14% 37% +1.69% 4.5일
손절 20건 15% 5% -9.32% 10.8일
기타(수동 등) 6건 5%

청산의 66%가 로테이션이다. 손절도 익절도 아니다.

로테이션 청산이 뭔가

이 시스템은 동시에 보유할 수 있는 종목 수에 상한이 있다. 자리가 다 찬 상태에서 스캐너가 지금 보유 중인 종목보다 점수가 높은 후보를 찾아내면, 낮은 쪽을 팔고 높은 쪽으로 갈아탄다.

즉 "이 종목이 틀렸다"가 아니라 "저 종목이 더 낫다" 는 이유의 청산이다.

설계 의도 자체는 멀쩡하다. 자본이 한정돼 있으니 더 좋은 기회로 옮기는 건 합리적이다.

그런데 이게 맞나

문제는 로테이션이 전체 청산의 절반을 훌쩍 넘는다는 점이다.

로테이션 청산의 평균 보유기간은 5.8일이다. 진입하고 일주일도 안 돼서 다른 종목으로 갈아타고 있다는 뜻이다.

이건 두 가지로 읽을 수 있다.

해석 A — 정상 작동이다. 평균 +1.19%로 플러스고, 승률도 48%로 세 유형 중 가장 높다. 손실이 커지기 전에 자리를 비워 주는 역할을 하고 있는 것일 수 있다.

해석 B — 전략이 스스로를 방해하고 있다. 추세추종은 이긴 포지션을 오래 끌고 가야 수익이 난다. 그런데 엿새가 안 돼 갈아타면 큰 추세를 탈 시간 자체가 없다. MU에서 +31%가 나온 건 7일을 들고 있었기 때문인데, 만약 엿새째에 더 높은 점수의 후보가 나타났다면 그 수익은 없었다.

평균 하나로 보면 안 되는 숫자였다

보유일 분포를 열어 보고서야 알았다. 5.8일이라는 평균은 성격이 다른 두 시기를 한 그릇에 담은 값이었다.

구간 건수 평균 보유 중앙값 최소 보유 평균 손익 승률
2026-07-07 이전 55건 1.8일 1일 0일 +0.58% 45%
2026-07-08 이후 31건 12.9일 8일 5일 +2.41% 55%

앞 구간에는 진입 당일에 갈아탄 건이 22건 있다. 5월에만 35건이 5일을 못 채우고 교체됐다. 뒤 구간에는 5일 미만이 한 건도 없다.

경계선이 정확히 갈리는 이유가 있었다. ROTATION_MIN_HOLD_DAYS = 5 — 최소 보유일 가드가 그때 들어갔다. 2분마다 도는 사이클이 같은 자리를 하루에도 몇 번씩 갈아치우던 churn을 막으려고 넣은 장치인데, 그 뒤로 의도대로 정확히 동작하고 있었다.

그러니 해석 B가 걱정한 상황 — "엿새도 안 돼 갈아타서 추세를 못 탄다" — 은 이미 지나간 문제다. 지금 구간의 평균 보유는 12.9일이고, 그 사이 평균 손익은 +2.41%로 전체 평균(+1.19%)의 두 배다. 고쳐야 할 걸 찾으러 들어갔다가 이미 고쳐져 있는 걸 확인하고 나온 셈이다.

로테이션은 부작용이 아니라 설계다

해석을 고르기 전에 확인할 게 있었다. 이 66%가 의도한 동작인가.

코드를 열어 보니 로테이션은 명시적으로 설계된 기능이었다.

  • 보유 중 가장 약한 종목의 점수와, 대기 중 가장 강한 후보의 점수를 매번 비교한다
  • 그 차이가 20점(ROTATION_THRESHOLD) 이상이면 교체한다
  • 단, 해당 포지션의 손실이 -5%를 넘으면 자동 교체를 멈추고 사람에게 확인 알림만 보낸다

(패닉셀 방지)

마지막 조건이 중요하다. 크게 잃고 있는 포지션은 로테이션으로 안 나간다. 그래서 로테이션 청산의 평균이 플러스로 나오는 건 어느 정도 구조적으로 보장된 결과다. 손실이 큰 건 손절로 빠지고, 로테이션에는 소폭 손익만 남는다.

그러니 "66%가 비정상인가"라는 질문은 틀린 질문이다. 66%는 문턱 20점의 산술적 결과다. 질문은 이렇게 좁혀져야 한다.

점수 차 20점은 갈아탈 만한 차이인가?

이 시스템의 점수는 0~100 범위로 정규화돼 있다. 20점 차이는 그 범위의 5분의 1이다. 직관적으로는 작지 않아 보이지만, 매일 새로 계산되는 점수에서 20점은 하루 이틀의 가격 움직임만으로도 벌어질 수 있는 폭이다. 5.8일이라는 평균 보유기간이 그 방증이다.

확인해야 할 것

지금 기록만으로는 A와 B를 가를 수 없다. 필요한 건 이것이다.

로테이션으로 판 종목이 그 뒤에 어떻게 됐는가?

판 뒤에 올랐다면 갈아탄 게 손해였고, 내렸다면 이득이었다. 그런데 지금 시스템은 청산한 시점까지만 기록하고 그 뒤를 추적하지 않는다. 그래서 답을 낼 수가 없다.

이건 명백한 기록 설계의 빈틈이다. 청산 후 N일간의 주가를 남기도록 고칠 예정이고, 데이터가 쌓이면 그때 다시 쓴다.

다만 기록을 다시 보니 완전히 빈 건 아니었다. 교체가 일어날 때마다 "어떤 종목으로 갈아탔는지"는 남고 있다. 없는 건 기능이 아니라 집계다.

나간 종목과 그 자리에 들어온 종목의 이후 성과를 짝지어 비교하면, 로테이션이 이익이었는지 손해였는지 처음으로 답할 수 있다. 그 비교를 붙이는 게 다음 작업이고, 그전까지 "66%가 과하다"는 말은 의견일 뿐 근거가 아니다.

지금 시점의 잠정 판단

로테이션이 손해를 내고 있지는 않다. 최근 구간 평균 +2.41%에 승률 55%로, 세 유형 중 성적이 가장 낫다. "청산의 66%가 손절도 익절도 아니다"는 사실은 놀랍지만, 그 자체가 나쁜 건 아니다.

속도 문제도 이미 손이 가 있었다. 최소 보유일 5일 가드가 들어간 뒤로 5일 미만 교체는 0건이고, 평균 보유는 12.9일로 늘었다. 남은 질문은 속도가 아니라 방향이다.

갈아탄 게 실제로 이득이었나 — 나간 종목과 그 자리에 들어온 종목의 이후 성과를 짝지어 비교해야 답이 나온다. 그 집계 없이 문턱(20점)을 올리거나 내리는 건 감으로 고치는 것이고, 이 시스템을 만든 이유와 어긋난다.

숫자를 쪼개기 전까지 나는 "5.8일이면 너무 빠르다"고 쓸 참이었다. 평균 하나만 보고 있었기 때문이다. 기록을 남기는 이유가 이거다 — 평균은 서로 다른 두 시기를 섞어 없던 문제를 만들어 낸다.

한 가지는 분명해졌다. 이 시스템에서 "언제 파는가"를 결정하는 건 손절선도 목표가도 아니고 옆자리 후보다. 설계할 때 의도한 구조이긴 하지만, 청산의 66%를 차지할 줄은 기록을 뽑아 보기 전까지 알지 못했다.


데이터 근거

  • 출처: 자체 시스템의 주문·체결 기록 (satellite_log.json)
  • 대상: fill_type = real이면서 청산이 완료된 132건
  • 기간: 2026-04-27 ~ 2026-08-29
  • 청산 이유는 시스템이 청산 시점에 기록한 outcome 값 그대로이며 사후에 분류하지 않았다.
  • 구간 분리 기준은 최소 보유일 가드(ROTATION_MIN_HOLD_DAYS = 5)가 들어간 2026-07-07이다.

분리 후 표본은 앞 55건 / 뒤 31건으로, 뒤 구간은 아직 표본이 적다.

  • 앞 구간 1건(COST, 5월)은 청산일이 진입일보다 앞서 기록돼 보유일이 음수로 계산된다.

건수·손익에는 그대로 두고 최소 보유일 표기에서만 0일로 처리했다 — 기록 오류이며 별도로 고칠 항목이다.

  • 손익률은 실제 체결가 기준, 수수료·세금 미반영

본 글은 정보 공유 목적이며 투자 권유가 아닙니다. 기재된 기록은 모의투자 계좌의 검증 기록입니다.

Comments

Leave a Reply

Discover more from Stock Rollbar · 스톡롤바

Subscribe now to keep reading and get access to the full archive.

Continue reading