7 분 분량

“손실은 짧게 자르고 수익은 길게 가져가라.” 투자 격언 가운데 가장 자주 듣는 말일 겁니다. 틀린 말처럼 들리지도 않습니다. 떨어지는 것을 붙들고 있지 말고 일찍 잘라내면 큰 손실은 피할 수 있을 것 같습니다.

앞 글에서는 얼마나 크게 거느냐가 파산을 가른다는 것을 봤습니다. 이번에는 언제 빠져나오느냐의 문제입니다. 질문은 하나입니다. 손절 규칙은 정말 손실을 줄일까요, 아니면 비용만 늘릴까요.

실험 설계

코스피 지수 일별 종가 31.4년치(1995년 5월~2026년 9월 17일, FinanceDataReader)에 규칙 세 종류를 돌렸습니다.

규칙 빠져나오는 조건 다시 들어가는 조건
매수 후 보유 없음 없음
200일 이동평균 종가가 200일 평균 아래로 종가가 200일 평균 위로
추적 손절 X% 들어간 뒤 최고 종가에서 X% 하락 나온 뒤 최저 종가에서 X% 반등

추적 손절(trailing stop)은 손절선을 한곳에 고정하지 않고 가격이 오를 때마다 따라 올리는 방식입니다. 한 번 나왔으면 언제 다시 들어갈지도 정해야 하는데, 여기서는 같은 폭만큼 반등하면 다시 사게 했습니다. 이렇게 짝지은 규칙은 1961년 시드니 알렉산더(Sidney Alexander)가 검증한 필터 규칙과 같은 꼴입니다. 200일 이동평균은 입문 ⑤의 12개월 절대 모멘텀을 일별로 옮긴 추세추종 규칙이라고 보면 됩니다.

조건은 이렇게 두었습니다.

  • 판단은 그날 종가로 하고, 바뀐 포지션은 다음 날 수익률부터 반영합니다. 미래 참조가 끼지 않게 하기 위해서입니다.
  • 매매 한 번(편도)마다 0.1%를 뺍니다. 지수 ETF를 사고파는 정도의 비용입니다. 거래 비용 글에서 쓴 0.3%로 바꾼 결과도 뒤에 붙였습니다.
  • 현금으로 있는 동안 이자는 0으로 둡니다. 지수는 배당이 빠진 가격지수입니다. 이 두 가지의 영향은 마지막에 따로 짚습니다.

핵심 코드는 짧습니다.

import numpy as np
import pandas as pd
import FinanceDataReader as fdr

close = fdr.DataReader('KS11', '1995-01-01', '2026-09-17')['Close']   # 본문 표와 같은 기간(1995-05~2026-09-17)
ret = close.pct_change().fillna(0).to_numpy()
years = (close.index[-1] - close.index[0]).days / 365.25

def pos_trailing(close, x):
    """최고가에서 x만큼 빠지면 매도, 매도 후 최저가에서 x만큼 오르면 재매수"""
    c = np.asarray(close, dtype=float)
    pos = np.empty(len(c))
    inside, ref = True, c[0]
    for t, p in enumerate(c):
        if inside:
            ref = max(ref, p)
            if p <= ref * (1 - x):
                inside, ref = False, p
        else:
            ref = min(ref, p)
            if p >= ref * (1 + x):
                inside, ref = True, p
        pos[t] = 1.0 if inside else 0.0
    return pos

def pos_ma(close, n=200):
    ma = close.rolling(n).mean()
    return np.where(ma.isna(), 1.0, (close > ma).astype(float))

def run(ret, pos, cost=0.001):
    held = np.r_[1.0, pos[:-1]]                 # 오늘 종가로 정하고 내일부터 반영
    trades = np.abs(np.diff(np.r_[1.0, held]))  # 포지션이 바뀐 날 비용
    return held * ret - trades * cost

for name, pos in [('200일선', pos_ma(close)), ('손절 10%', pos_trailing(close, 0.10))]:
    strat = run(ret, pos)
    cagr = (1 + strat).prod() ** (1 / years) - 1
    print(name, f'{cagr:.2%}')

연환산은 거래일 수가 아니라 달력 햇수로 했습니다. 1998년까지는 토요일에도 장이 열려서, 1년을 250거래일로 치면 기간이 실제보다 길게 잡힙니다. 전체 스크립트는 stop_loss.py에 있고, 다른 글의 스크립트는 코드 페이지에 모아 두었습니다.

31년 전체 결과

규칙 CAGR 변동성 MDD 보유 비율 연 매매 횟수
매수 후 보유 6.59% 26.3% −72.5% 100% 0
200일 이동평균 6.67% 17.6% −48.3% 58% 7.8
추적 손절 5% 3.70% 18.3% −54.9% 64% 12.5
추적 손절 10% 2.86% 19.8% −76.3% 73% 4.4
추적 손절 15% 6.90% 19.6% −66.9% 69% 2.0
추적 손절 20% 6.68% 20.1% −64.5% 74% 1.2

코스피 매수 후 보유, 200일선, 추적 손절 누적 수익률

변동성은 모든 규칙이 확실히 줄였습니다. 시장에 있는 시간이 짧으니 당연합니다. 수익률은 경우에 따라 갈렸습니다. 200일선과 15%·20% 손절은 보유와 비슷한 수익률을 냈고, 5%·10% 손절은 한참 뒤처졌습니다.

그리고 표에서 가장 이상한 숫자가 있습니다. 추적 손절 10%의 MDD가 −76.3%로, 아무것도 안 한 보유(−72.5%)보다 깊습니다. 손실을 줄이려고 만든 규칙이 손실을 키웠습니다.

손절이 손실을 키운 때

주요 하락 구간을 따로 떼어 봤습니다.

구간 보유 200일선 손절 10%
외환위기 (1997.6~1998.6) −60.6% −7.0% −36.5%
IT 버블 붕괴 (2000.1~2001.9) −53.3% −28.2% −70.5%
금융위기 (2007.11~2008.10) −46.1% −20.6% −31.6%
코로나 (2020.1~2020.3) −20.2% −6.9% −1.7%
2021~22 하락 (2021.7~2022.9) −34.6% −6.1% −21.2%
코로나 이후 반등 (2020.4~2021.6) +87.9% +53.4% +87.9%

한 방향으로 쭉 떨어진 하락장에서는 두 규칙 모두 손실을 크게 줄였습니다. 문제는 IT 버블 붕괴 구간입니다. 2000년부터 2001년 9월까지 코스피는 떨어지면서도 10~20%짜리 반등을 여러 번 했습니다. 손절 10%는 이 구간에서만 매매를 25번 했습니다. 10% 빠지면 팔고, 바닥에서 10% 오르면 다시 사고, 또 10% 빠지면 팝니다. 한 번 헛돌 때마다 판 가격보다 10% 가까이 비싸게 되사는 셈입니다. 결국 가만히 있었던 것보다 17%p를 더 잃었습니다. 모멘텀 글에서 말한 휩쏘가 손절 규칙에서 가장 아프게 나타난 경우입니다.

200일선의 최대 낙폭 −48.3%도 들여다보면 비슷합니다. 이 낙폭은 폭락장이 아니라 2011년 5월부터 2020년 6월까지 9년에 걸쳐 쌓였습니다. 그 사이 코스피는 거래일의 97%를 1,800~2,600 사이에서 보냈고, 보유는 이 9년 동안 −6.1%였습니다. 200일선 규칙은 추세가 생긴 것 같으면 들어갔다가 꺾이면 나오기를 반복하며 매매를 130번 했고, 거의 반토막이 났습니다. 2011년 5월의 고점을 다시 넘은 것은 2026년 1월, 14년 반 뒤였습니다.

손절 규칙이 두려워해야 할 것은 폭락이 아니라 방향 없이 크게 흔들리는 시장입니다. 폭락에서는 규칙이 제 몫을 합니다. 박스권에서는 흔들림 하나하나가 비용이 됩니다.

반대쪽 비용도 표 마지막 줄에 있습니다. 코로나 직후 반등에서 200일선은 +53.4%에 그쳤습니다. 보유는 +87.9%였습니다. 바닥에서 평균선 위로 올라설 때까지 기다리는 동안 반등의 앞부분을 놓쳤습니다. 큰 상승일이 폭락 직후에 몰려 있어서 생기는 이 비용은 코스피 최고의 날 10일을 놓치면에서 따로 계산했습니다.

시대에 따라 뒤집힌 결과

31년을 둘로 나누면 그림이 더 분명해집니다.

  1995~2008 CAGR 2009~2026 CAGR
매수 후 보유 1.6% 10.4%
200일 이동평균 9.8% 5.3%
추적 손절 10% −0.1% 5.1%
추적 손절 20% 2.5% 9.8%

앞의 14년은 외환위기, IT 버블, 금융위기가 이어진 시기였습니다. 200일선은 보유를 연 8%p 넘게 이겼습니다. 뒤의 18년은 급락 뒤 빠르게 회복하는 V자 반등이 많았고, 200일선은 연 5%p를 졌습니다. 31년 전체에서 두 결과가 거의 같게 나온 것은 이 둘이 우연히 상쇄된 결과에 가깝습니다.

코스닥도 같은 패턴이었습니다. 30년 전체로는 보유가 연 −0.6%로 가장 나빴고 모든 규칙이 이겼습니다. 하지만 그 차이는 거의 다 2000년 닷컴 버블 붕괴에서 나왔습니다. 2009년 이후만 보면 보유가 연 5.1%, 규칙들은 연 −0.3%~1.6%로 모두 졌습니다.

추세가 없는 세상에서 돌려 보면

규칙이 정말 추세를 잡아낸 것인지 확인하려고 몬테카를로 글의 방법을 다시 썼습니다. 코스피 일별 수익률을 그대로 두고 순서만 무작위로 섞은 가상의 역사를 1,000개 만들었습니다. 섞인 역사에는 추세가 없습니다. 오늘의 수익률이 어제와 아무 관계가 없습니다. 보유의 CAGR은 순서를 섞어도 똑같으므로, 규칙이 보유보다 얼마나 낫거나 못한지만 비교하면 됩니다.

순서를 섞은 역사에서 규칙의 초과 CAGR 분포

규칙 실제 코스피 섞은 역사 평균 실제가 섞은 역사보다 나은 비율
200일 이동평균 +0.07%p −3.86%p 94%
추적 손절 5% −2.89%p −4.24%p 71%
추적 손절 10% −3.73%p −3.45%p 45%
추적 손절 15% +0.31%p −2.98%p 91%
추적 손절 20% +0.09%p −2.59%p 87%

추세가 없는 세상에서 규칙들은 평균적으로 보유보다 연 2.6~4.2%p씩 졌습니다. 이유는 간단합니다. 주식은 평균적으로 오르는 자산이고, 규칙은 시간의 26~42%를 현금으로 보냅니다. 방향을 맞히는 능력이 없다면 그 시간만큼 주식의 기대수익을 버리는 셈입니다. 캐민스키와 로(Kaminski & Lo, 2014)가 “손절 규칙은 언제 손실을 막는가”라는 논문에서 수식으로 보인 결론도 같습니다. 수익률이 무작위 보행을 따르면 손절은 기대수익을 반드시 깎습니다. 손절이 득이 되는 것은 수익률에 추세, 즉 모멘텀이 있을 때뿐입니다.

실제 코스피에서 200일선은 섞은 역사의 94%보다 나았습니다. 코스피에 추세가 있긴 했다는 뜻입니다. 월간 수익률의 1차 자기상관도 +0.09로 양수입니다. 하지만 그 추세로 벌어들인 것은 시장 밖에 있던 비용을 겨우 메우는 정도였습니다. 규칙 덕분에 보유보다 더 번 것은 아닙니다.

추적 손절 10%는 실제 결과가 섞은 역사의 한가운데에 있습니다. 추세가 없는 세상에서 기대할 수 있는 성적과 구별이 안 됩니다. 이 폭에서는 규칙이 추세를 잡은 것이 아니라 잡음에 반응했다는 뜻입니다.

비용과 빠진 항목

편도 비용을 바꾸면 이렇게 됩니다.

규칙 0% 0.1% 0.3%
200일 이동평균 7.50% 6.67% 5.02%
추적 손절 5% 5.00% 3.70% 1.15%
추적 손절 15% 7.12% 6.90% 6.46%
추적 손절 20% 6.81% 6.68% 6.42%

손절 폭이 좁을수록 매매가 잦고, 비용에 크게 흔들립니다. 5% 손절은 개별 종목 수준의 비용(0.3%)이면 연 1%대로 내려갑니다. 200일선도 연 8번 가까이 매매하므로 편도 0.1%와 0.3% 사이에서만 연 1.7%p가 벌어집니다.

이 실험에서 빠진 두 가지는 방향이 서로 반대입니다.

  • 현금 이자: 200일선은 시간의 42%를 현금으로 보냅니다. 그동안 받은 금리를 연 3%로만 쳐도 대략 0.42 × 3% ≈ 연 1.3%p가 규칙 쪽에 더해집니다. 1990년대 후반처럼 금리가 높던 때는 더 큽니다.
  • 배당: 가격지수라 배당이 빠져 있습니다. 배당수익률을 연 1.5%로 잡으면 보유는 그만큼을 다 받지만 규칙은 시장에 있던 58%만큼만 받습니다. 대략 연 0.6%p가 보유 쪽에 더해집니다.

둘을 합치면 규칙 쪽이 연 0.5~1%p쯤 나아질 것으로 봅니다. 결론이 뒤집힐 만큼은 아니지만, 200일선이 보유와 “비슷했다”는 결과는 “조금 나았다”로 읽는 것이 맞겠습니다.

하나 더, 손절 규칙이 막지 못하는 손실이 있습니다. 2026년 3월 4일 코스피는 하루에 12.1% 빠졌습니다. 그날 두 규칙 모두 주식을 들고 있었습니다. 종가를 보고 판단하든, 장중에 손절 주문을 걸어 두든, 하루 만에 벌어진 갭은 그대로 맞습니다. 손절선을 −5%에 걸어 두었다고 손실이 −5%에서 멈추는 것은 아닙니다.

정리

손절은 손실을 줄여 주는 장치가 아니라 손실의 모양을 바꾸는 장치에 가깝습니다. 한 번의 큰 낙폭을, 박스권에서 반복되는 작은 손실들과 반등 초입을 놓치는 비용으로 바꿉니다. 그 거래가 이득인지는 앞으로의 시장이 1997~2008년처럼 길고 깊은 하락이 이어질지, 2009년 이후처럼 V자로 회복할지에 달려 있습니다. 그리고 그것은 미리 알 수 없습니다.

이번 실험에서 비교적 분명했던 것은 세 가지입니다. 폭이 좁은 손절은 잡음에 반응해 비용만 늘렸습니다. 넉넉한 손절(15~20%)과 200일선은 수익률을 크게 해치지 않으면서 변동성과 큰 하락장의 손실을 줄였습니다. 그리고 어떤 규칙이든 박스권에서 오래 고생하는 기간을 각오해야 합니다. 200일선은 14년 반 동안 전 고점을 되찾지 못했습니다.

손절 규칙을 쓸 이유가 있다면, 수익률을 올려서가 아니라 버틸 수 있게 해 줘서일 겁니다. 위험 지표 글에서 말했듯이 MDD −72%를 실제로 견디는 사람은 드뭅니다. 그 대신 치르는 값이 박스권에서의 긴 부진이라는 것만 알고 고르면 됩니다.

다음 글에서는 백테스트와 실제 계좌 사이에 남은 마지막 간극, 세금과 거래 현실을 다룹니다.

2026-10-22 수정: 본문 코드와 전체 스크립트(stop_loss.py)에 종료일이 없어 9월 17일 뒤에 돌리면 표와 다른 숫자가 나오던 것을, 종료일 2026-09-17을 넣어 표와 같은 기간의 데이터를 쓰도록 고쳤습니다. 이 기간으로 다시 돌린 스크립트 출력에 맞춰 보유 CAGR(6.60%→6.59%) 등 몇몇 값을 0.01%p 안팎 차이에 맞춰 고쳤고(소수 첫째 자리로 적은 2009~2026년 보유 CAGR 10.5%→10.4%, 규칙들이 진 폭 “연 2.6~4.3%p”→”2.6~4.2%p” 포함)(경위는 같은 코드가 다른 숫자를 낸 날에 적었습니다), 2011~2020년 박스권에서 200일선의 매매 횟수를 125번에서 130번으로, 코스닥 30년 보유 CAGR을 연 −0.7%에서 −0.6%로 바로잡았습니다.

참고 자료

  • Alexander, S. S. (1961). Price Movements in Speculative Markets: Trends or Random Walks. Industrial Management Review, 2(2).
  • Kaminski, K. M., & Lo, A. W. (2014). When do stop-loss rules stop losses? Journal of Financial Markets, 18.

이 글은 학습과 정보 공유 목적으로 작성되었으며, 특정 종목이나 상품에 대한 투자 권유가 아닙니다. 본문의 수익률은 과거 지수 데이터로 계산한 것이며 미래 성과를 보장하지 않습니다. 투자의 판단과 책임은 투자자 본인에게 있습니다.

최종 수정: