AlgoLab Blog · 퀀트·백테스트 검증 · 2026

손절 후 재진입 대기 — 0·3·10일 돌려 보니 수익은 같았다

퀀트 · 청산 설계 2026-10-27 · 약 8분 읽기 · 알고랩 AlgoLab
한 줄 요약

손절 직후 며칠 쉬고 다시 들어가는 규칙은 수익을 늘리지 않았습니다. 바꾼 것은 "연달아 몇 번 잘리느냐"였습니다. 같은 20일 돌파 진입, 같은 −5% 손절에 재진입 대기만 0·3·5·10·20거래일로 바꿔 국내 22종목 10년(2016-01~2026-10, 거래 927~1,049건)을 돌렸더니, 거래당 기대값은 0일 2.00% → 20일 1.67%로 오히려 줄었습니다. 그 차이는 거의 전부 에코프로 거래 1건(+310%)에서 나왔고, 에코프로를 빼면 1.60~1.82%로 대기 일수와 무관했습니다. 대기가 실제로 줄인 것은 최장 연속 손절(14회 → 10회)과 고변동 종목의 MDD였습니다. 손실을 키우는 쪽은 "바로 다시 산 것"보다 200일선 아래에서 산 것이었습니다. (왕복 비용 0.3% 가정, 생존 종목만, 설명용 전략, 과거≠미래)

목차

  1. 왜 "손절 후 며칠 쉬기"를 묻나
  2. 실측 설계 — 진입·손절은 같게, 대기만 5종
  3. 전체 결과 — 기대값은 대기를 길게 할수록 줄었다
  4. 평균을 끌어올린 건 거래 1건이었다
  5. 대기가 실제로 줄인 것 — 연속 손절과 MDD
  6. 대기보다 큰 차이 — 200일선 아래 진입
  7. 봇에 넣을 때 — 거래일로 세고 상태를 파일에 남긴다
  8. 재현 코드와 한계
  9. 자주 묻는 질문

1. 왜 "손절 후 며칠 쉬기"를 묻나

돌파 매매 봇을 돌리다 보면 이런 장면이 나옵니다. 월요일에 매수했다가 수요일에 −5%로 손절했는데, 다음 주 월요일에 같은 종목이 다시 20일 고가를 넘어 봇이 또 삽니다. 그리고 또 잘립니다. 의뢰하시는 분들이 이 기록을 보고 가장 먼저 요청하는 수정이 "손절한 종목은 며칠 동안 다시 사지 말게 해 달라"입니다. 흔히 쿨다운이라고 부르는 규칙입니다.

직관은 분명합니다. 손절이 났다는 건 그 종목이 지금 내 규칙과 안 맞는다는 신호이니, 잠깐 쉬면 같은 실수를 반복하지 않을 것 같습니다. 문제는 쉬는 동안 진짜 추세가 시작되면 그것도 같이 놓친다는 점입니다. 어느 쪽이 큰지는 직관으로 알 수 없어서 돌려 봤습니다. 이 글은 ATR 손절 vs 고정 손절, 분할매도 실측에 이은 청산 실험의 세 번째 편이고, 같은 22종목·같은 진입 규칙을 그대로 씁니다.

2. 실측 설계 — 진입·손절은 같게, 대기만 5종

항목설정
데이터FinanceDataReader 일봉(수정주가), ASOF = "2026-10-23" 고정, 집계 구간 2016-01-04~
종목 22개2016년 이전 상장 KOSPI·KOSDAQ 종목 — 통신·금융(저변동)부터 바이오·2차전지(고변동)까지. ATR 손절 글과 같은 목록
진입종가 > 직전 20거래일 고가 최고값 → 다음 날 시가 매수
청산① 손절: 진입가 −5%(저가가 닿으면 손절가, 시가부터 아래면 시가) ② 추세 이탈: 종가 < 직전 10거래일 저가 최저값 → 다음 날 시가
재진입 대기손절로 나온 뒤에만 0·3·5·10·20거래일 동안 새 신호 무시. 추세 이탈 청산 뒤에는 대기 없음
비용왕복 0.3% (수수료·세금·슬리피지 근사)
환경Python 3.10 · pandas 2.2.3 · numpy 2.0.2 · FinanceDataReader 0.9.202

"대기 3일"은 손절 체결일 다음 3거래일 동안 신호가 나도 무시하고, 4거래일째 종가 신호부터 받는다는 뜻입니다. 대기 0일은 손절 다음 날 종가에 돌파 신호가 나면 그다음 날 바로 다시 삽니다. 손절과 추세 이탈을 구분한 이유는, 추세 이탈로 나온 경우는 이미 한동안 보유한 뒤라 "또 잘리는 반복"과 성격이 다르기 때문입니다.

3. 전체 결과 — 기대값은 대기를 길게 할수록 줄었다

ASOF 2026-10-23  tickers 22  stop -5%  trades(wait 0) 1,049

[1] 전체 (22종목 거래 합산)
wait  trades   win%  stop_hit%  expectancy  med_cum   med_mdd  max_stop_streak
  0d    1049  29.6%     49.9%      2.00%     -7.2%   -45.2%      14
  3d    1028  29.8%     49.4%      1.96%      0.3%   -46.0%      10
  5d    1016  29.4%     49.8%      1.83%     -1.2%   -47.4%      12
 10d     985  29.6%     49.5%      1.76%    -11.1%   -44.5%      11
 20d     927  29.6%     49.1%      1.67%    -10.5%   -41.6%      10

표에서 읽을 것은 세 가지입니다.

  1. 대기를 길게 해도 승률과 손절 비율은 그대로다. 승률 29.4~29.8%, 손절 비율 49.1~49.9%로 다섯 설정이 거의 같습니다. 쉬고 들어간다고 해서 더 좋은 자리를 고르게 되지는 않았습니다.
  2. 거래당 기대값은 오히려 줄었다. 0일 2.00%에서 20일 1.67%로 단조롭게 내려갑니다. 대기 때문에 빠진 거래(0일 대비 최대 122건)가 평균보다 나은 거래였다는 뜻입니다.
  3. 종목별 누적 수익 중앙값(med_cum)은 들쭉날쭉하다. −11.1%에서 +0.3%까지 순서 없이 흔들립니다. 종목별로 1등을 세어도 0일 4개, 3일 2개, 5일 1개, 10일 7개, 20일 6개로 뚜렷한 승자가 없습니다.

손절 직후 들어간 거래만 따로 보면 이렇습니다(직전 거래가 손절이었던 진입).

[2] 손절 직후 들어간 거래만 (직전 거래가 손절)
wait  trades   win%  expectancy
  0d     508  26.2%      1.18%
  3d     492  26.4%      1.13%
 10d     472  25.8%      0.59%
 20d     439  25.1%      0.42%

손절 뒤 재진입은 전체 평균(2.00%)보다 확실히 못합니다. 여기까지는 직관과 맞습니다. 그런데 대기를 길게 해도 이 숫자가 좋아지지 않고 더 나빠집니다. 손절 직후의 진입이 나쁜 것은 "너무 빨리 들어가서"가 아니라는 뜻입니다.

4. 평균을 끌어올린 건 거래 1건이었다

대기 0일 결과에서 손절 뒤 재진입까지 걸린 거래일을 구간별로 나눠 봤습니다.

[6] 대기 0일 기준 — 손절 뒤 며칠 만에 다시 들어갔나
gap       trades   win%  expectancy  down%
   2-3d      32  28.1%     12.65%  12.5%
   4-5d      23  30.4%      0.88%  26.1%
  6-10d      63  25.4%     -1.10%  25.4%
 11-20d      65  29.2%      2.43%  27.7%
   21d+     325  25.2%      0.27%  48.6%

손절 2~3거래일 만에 다시 들어간 32건의 평균이 12.65%로 압도적입니다. 이것만 보면 "손절 후 바로 다시 사는 게 정답"처럼 보이지만, 안을 열어 보면 다릅니다.

에코프로 086520  2023-02-03 진입  +310.3%  trend  (손절 3거래일 뒤)
에코프로 086520  2021-07-14 진입   +93.2%  trend  (손절 3거래일 뒤)
에스엠   041510  2023-01-31 진입   +35.7%  trend
mean 12.65%   median -5.30%   상위 2건 제외 0.04%

32건의 중앙값은 −5.30%, 즉 절반 이상이 다시 손절로 끝났습니다. 평균 12.65%는 에코프로 2023-02-03 거래 하나(+310%)가 만든 숫자이고, 상위 2건을 빼면 0.04%입니다. 그래서 22종목에서 에코프로만 빼고 다시 계산했습니다.

0% 1% 2% 0일 3일 5일 10일 20일 2.001.63 1.961.65 1.831.60 1.761.63 1.671.82 22종목 전체 에코프로 제외 21종목
재진입 대기 일수별 거래당 기대값(%) · 22종목 2016-01~2026-10 · 왕복 0.3% 비용 포함
wait  trades  expectancy(에코프로 제외)  상위 1% 거래도 제외
  0d     992        1.63%                  0.12%
  3d     974        1.65%                  0.11%
  5d     964        1.60%                  0.04%
 10d     934        1.63%                  0.02%
 20d     877        1.82%                  0.20%

에코프로를 빼자 "대기를 길게 할수록 줄어든다"는 흐름이 사라지고 1.60~1.82%로 평평해졌습니다. 상위 1% 거래까지 빼면 0.02~0.20%로 모두 0 근처입니다. 결론은 단순합니다. 이 데이터에서 재진입 대기 일수는 수익을 바꾸지 못했고, 바꾼 것처럼 보인 차이는 큰 추세 1~2건을 잡았느냐 놓쳤느냐였습니다. 실제로 에코프로의 누적 수익은 대기 0일 771%, 대기 10일 161%로 갈렸습니다. 돌파 전략은 소수의 큰 거래로 버티는 구조라, 그 큰 거래가 하필 손절 직후에 왔다면 대기는 비싼 규칙이 됩니다.

5. 대기가 실제로 줄인 것 — 연속 손절과 MDD

수익에서 차이가 없다면 대기는 쓸모가 없을까요. 종목별로 0일과 10일을 나란히 놓으면 다른 것이 보입니다.

종목최장 연속 손절 0일 → 10일MDD 0일 → 10일누적 수익 0일 → 10일
HLB 02830014회 → 11회−81.8% → −70.7%−71.1% → −67.3%
알테오젠 19617011회 → 7회−60.1% → −50.4%+125.8% → +91.5%
에코프로 08652010회 → 8회−54.2% → −47.9%+771.2% → +161.4%
에스엠 0415108회 → 6회−50.9% → −56.9%−37.2% → −41.9%
셀트리온 0682706회 → 6회−47.4% → −57.1%−2.9% → −48.3%
삼성전자 0059304회 → 3회−24.6% → −24.1%+287.7% → +290.4%

고변동 종목(HLB·알테오젠·에코프로)에서는 대기가 최장 연속 손절을 2~4회 줄이고 MDD를 6~11%p 얕게 만들었습니다. 22종목 전체로도 최장 연속 손절이 14회에서 10~12회로 줄었습니다. 반면 셀트리온은 대기 10일 때문에 빠진 거래 중에 수익 거래가 있어 누적 수익이 −2.9%에서 −48.3%로 나빠졌습니다. 대기는 평균을 바꾸는 규칙이 아니라 경로를 바꾸는 규칙이고, 그 경로 변화가 종목마다 다른 방향으로 나왔습니다.

실전에서 경로는 무시할 수 없습니다. 같은 종목에서 14번 연속 손절이 나면 대부분 사람은 중간에 봇을 끕니다. 그래서 "대기를 넣을까"는 수익의 문제가 아니라 연속 손절을 몇 번까지 견딜 수 있느냐의 문제로 보는 게 맞습니다. 그 기준을 미리 정해 두는 법은 봇 손실 구간에서 끌까 둘까에서 다뤘습니다.

6. 대기보다 큰 차이 — 200일선 아래 진입

그렇다면 손절 뒤 재진입이 평균보다 못한 진짜 이유는 뭘까요. 신호일 종가가 200일 이동평균 위인지 아래인지로 거래를 나눴습니다.

[3] 구간별 — 신호일 종가 vs 200일 이동평균
regime wait  trades   win%  expectancy
 down   0d     343  27.7%     -0.16%
 down  10d     323  27.9%     -0.08%
 down  20d     303  26.7%     -0.14%
   up   0d     706  30.5%      3.05%
   up  10d     662  30.5%      2.66%

[7] 200일선 필터를 더하면 (200일선 아래 신호는 진입 안 함)
wait  trades   win%  expectancy  med_cum   med_mdd  max_stop_streak
  0d     706  30.5%      3.05%      9.9%   -36.6%      10
 10d     662  30.5%      2.66%     11.6%   -33.9%       8

200일선 아래에서 나온 돌파 신호 343건은 대기 일수와 상관없이 거래당 평균이 −0.08~−0.16%로 손익분기 아래였습니다. 앞의 [6] 표에서도 손절 21거래일 이후 재진입 325건 중 48.6%가 200일선 아래였습니다. 손절이 반복되는 종목은 대개 장기 하락 중인 종목이고, 그런 종목에서는 며칠을 쉬든 다시 사는 것 자체가 손해였습니다. 200일선 필터를 넣으면 대기 없이도 종목별 MDD 중앙값이 −45.2%에서 −36.6%로, 최장 연속 손절이 14회에서 10회로 줄었습니다. 대기 일수보다 "어떤 상태에서 다시 사느냐"가 더 큰 손잡이였습니다.

주의 — 200일선 필터 결과도 같은 데이터로 확인한 것이라 다른 기간에서 버틴다는 보장은 없습니다. 이 글은 필터를 권하려는 것이 아니라, "손절 후 대기"가 겨냥한 문제(반복 손절)가 실제로는 다른 곳에서 생겼다는 점을 보이려는 것입니다. 여러 규칙을 같은 데이터로 계속 시험하면 좋아 보이는 조합이 우연히 나오는 함정은 데이터 스누핑 글에 정리했습니다.

7. 봇에 넣을 때 — 거래일로 세고 상태를 파일에 남긴다

그래도 대기 규칙을 넣기로 했다면 구현에서 백테스트와 어긋나는 곳이 두 군데 있습니다.

import json
from pathlib import Path

STATE = Path("cooldown_state.json")
WAIT_DAYS = 3          # 손절 뒤 쉬는 거래일 수 — 백테스트와 같은 값

def load_state() -> dict:
    return json.loads(STATE.read_text(encoding="utf-8")) if STATE.exists() else {}

def on_stop_filled(stk_cd: str, fill_date: str) -> None:
    """손절 체결 확인 뒤 호출. fill_date = 'YYYYMMDD'"""
    s = load_state()
    s[stk_cd] = {"last_stop": fill_date}
    STATE.write_text(json.dumps(s, ensure_ascii=False, indent=2), encoding="utf-8")

def can_enter(stk_cd: str, trade_dates: list[str]) -> bool:
    """trade_dates = ka10081 응답의 dt 목록(정렬 무관, 오늘 포함). 휴장일은 이미 빠져 있다."""
    last = load_state().get(stk_cd, {}).get("last_stop")
    if not last:
        return True
    passed = sum(1 for d in trade_dates if d > last)   # 손절일 다음 거래일부터 센다
    return passed > WAIT_DAYS

손절 하나가 기록된 뒤의 상태 파일은 이렇게 생깁니다.

{
  "196170": {
    "last_stop": "20261021"
  }
}

이 경우 10월 22·23·26일(3거래일, 주말 제외)은 신호가 나도 can_enter가 False를 돌려주고, 10월 27일 종가 신호부터 매수 주문 kt10000으로 넘어갑니다. passed > WAIT_DAYS는 백테스트의 i > blocked_until과 같은 조건이라 대기 0일이면 손절 다음 날 신호부터 받습니다. 주문 함수 쪽 처리는 키움 kt10000 주문 글을, 일봉 조회는 키움 일봉·분봉·틱 차트 글을 참고하세요.

8. 재현 코드와 한계

위 표 전체를 만드는 스크립트는 stop_reentry_cooldown_backtest.py로 받을 수 있습니다. ASOF를 2026-10-23으로 고정했기 때문에 지금 실행해도 글과 같은 숫자가 나옵니다. 최신 데이터로 보려면 ASOF = None으로 바꾸면 되고 숫자는 달라집니다. 대기를 거는 핵심은 두 줄입니다.

prev_stop = why == "stop"
blocked_until = j + wait if why == "stop" else j   # 손절일 때만 wait 거래일 동안 신호 무시
...
if i > blocked_until and c[i] > hi20[i]:           # 신호(종가 확인) -> 다음 날 시가 진입

한계 — 지금 상장돼 있는 22종목만 썼으므로 생존 편향이 있습니다(생존 편향 실측). 진입 규칙 1개, 손절 −5% 1개만 시험했고 대기 일수는 0·3·5·10·20 다섯 개만 봤습니다. 평균은 소수의 큰 거래에 크게 좌우되며(에코프로 1건이 전체 차이를 거의 다 설명), 2025~2026년 상승 구간이 포함돼 있습니다. 같은 날 진입·손절은 불리하게 처리했고(일봉 손절 체결 순서), 비용은 왕복 0.3% 근사, 배당 미포함입니다. 어떤 수치도 미래 수익을 예측하지 않으며 특정 종목·전략을 권하지 않습니다. 과거 성과는 미래를 보장하지 않습니다.

같은 전략을 시작일만 바꿨을 때의 흔들림은 백테스트 시작일 민감도에서, 백테스트 점검 순서 전체는 자동매매 백테스트 완전 가이드에서 볼 수 있습니다.

9. 자주 묻는 질문

손절하고 바로 다시 사면 손해가 커지나요?

이 실험에서는 평균적으로 그렇지 않았습니다. 22종목 10년, 같은 20일 돌파 진입과 −5% 손절에서 재진입 대기만 0·3·5·10·20거래일로 바꿨더니, 가장 큰 거래가 나온 에코프로를 빼면 거래당 기대값이 1.60~1.82%로 대기 일수와 상관없이 비슷했습니다. 대기가 줄인 것은 연속 손절 횟수와 고변동 종목의 MDD였습니다. 과거 결과는 미래를 보장하지 않습니다.

재진입 대기는 며칠이 적당한가요?

정답 일수는 없습니다. 수익만 보면 이 데이터에서 대기 일수는 차이를 만들지 못했습니다. 연속 손절을 견디기 어렵다면 3~10거래일 대기가 최장 연속 손절을 줄였고, 대신 손절 직후 다시 시작된 큰 추세를 놓치는 비용이 있었습니다. 일수를 여러 개 돌려 가장 좋은 값을 고르면 과최적화가 됩니다.

대기 일수는 달력 기준인가요, 거래일 기준인가요?

이 글은 거래일 기준입니다. 달력 기준으로 세면 주말과 연휴가 끼는 주에 실제로 쉬는 기간이 짧아져 백테스트와 봇의 동작이 달라집니다. 봇에서는 키움 ka10081 같은 일봉 조회 결과의 날짜 목록으로 세면 휴장일이 이미 빠져 있어 간단합니다.

재진입 대기보다 효과가 큰 규칙이 있었나요?

같은 데이터에서 신호일 종가가 200일 이동평균 아래인 진입을 빼는 필터가 더 큰 차이를 냈습니다. 200일선 아래 진입 343건은 대기 일수와 상관없이 거래당 평균이 −0.08~−0.16%였고, 이 필터를 넣으면 종목별 MDD 중앙값이 −45.2%에서 −36.6%로 얕아졌습니다. 설명용 실험이며 특정 전략을 권하지 않습니다.

손절·재진입 규칙까지 검증한 봇, 만들어 드립니다

쓰시려는 손절과 재진입 규칙을 종목군에 맞춰 백테스트로 먼저 보여 드리고, 재시작해도 규칙이 유지되게 만듭니다. 24시간 빠른 답변 가능합니다.

무료 상담 시작하기