주식 HTS나 MTS 차트 창을 열면 투자자들이 가장 널리 활용하는 대표적인 기술적 보조지표 중 하나가 있습니다. 바로 J. 웰스 와일더가 창안한 상대강도지수(RSI, Relative Strength Index)입니다.
증권 서적과 실전 매매 강의에서는 약속이라도 한 듯 다음 공식을 기본 상식처럼 가르칩니다.
남들이 공포에 던질 때 싸게 사서 환호할 때 파는 완벽한 역발상 투자 전략처럼 들립니다.
지난 1편에서 ‘골든크로스(20-60일선)’를 10년 치 돌려보았을 때, 승률 29%에 누적 수익률이 단순 보유의 3분의 1 토막에 그쳤던 씁쓸한 결과를 확인했습니다.
그렇다면 가장 대표적인 역추세 반등 전략인 RSI 과매도 매수 전략은 과연 시장을 이겼을까요?
소문과 심리적 환상을 배제하고, 대한민국 대표 지수 ETF인 KODEX 200(069500)의 약 15.7년(2009년 4월 ~ 2024년 12월, 총 3,845거래일) 전 구간 데이터를 파이썬 코드로 직접 검증해 보았습니다.
1️⃣ 정량 백테스트 설계 및 엄격한 체결 원칙
투자자의 감정과 사후 확증편향을 원천 배제하기 위해, 1편과 동일한 엄격한 퀀트 규칙을 적용했습니다.
KODEX 200
* 지표 세팅: Wilder의 정통 14일 RSI 공식(alpha=1/14, min_periods=14) 적용.
원칙 매매
🟢 매수 조건: 일봉 기준 14일 RSI 지표가 30선 이하로 진입 확정 시, 익일 종가에 전량 매수.
🔴 매도 조건: 주가가 반등하여 14일 RSI 지표가 70선 이상으로 돌파 확정 시, 익일 종가에 전량 매도 (현금화).
2️⃣ 15.7년 백테스트 결과: 단순 보유 vs RSI 30 전략
2009년 4월부터 2024년 12월까지 약 15.7년 동안 아무것도 건드리지 않고 묻어둔 단순 보유(Buy & Hold)와, RSI 신호에 따라 매매한 RSI 30 전략의 실제 성적표입니다.
[김과장의 팩트체크 카툰 1] ‘공포에 사라’ 격언의 상식 vs 16년 실제 데이터의 배신
압도적 승리
대패
가만히 들고 있던 단순 보유(+142.6%)가 부지런히 타이밍을 쟀던 RSI 전략(+33.2%) 대비 누적 수익률 기준 4배 이상 앞섰습니다. (원금 대비 최종 자산 기준 약 2.43배 vs 1.33배로 약 1.8배 차이)
특히 주목할 점은 완결 거래 횟수가 15.7년간 총 12건(10승 2패)이었다는 점입니다. 승률 자체는 83%로 높아 보이지만, 정작 계좌의 총자산은 시장의 자연스러운 성장에 크게 뒤처졌습니다.
3️⃣ 왜 RSI 과매도 매수는 시장에 참패했을까?
“승률 80%가 넘는 고승률 매매”라는 환상 뒤에 숨겨진 정량적 패배 원인은 다음 2가지입니다.
RSI 30 전략의 시장 노출도(Market Exposure)는 38.8%에 그쳤습니다.
즉, 3,845거래일이라는 긴 시간 중 무려 61.2%의 기간 동안 주식을 전혀 들고 있지 않고 현금만 쥔 채 관망했다는 뜻입니다.
지수가 바닥에서 반등해 RSI 70에 도달하면 전략은 전량 매도하고 현금화합니다. 그러나 강세장에서 주가는 70을 찍고 바로 꺾이는 것이 아니라, 그 이후에도 수개월 동안 신고가를 경신하며 폭등하는 ‘대세 상승 랠리’를 이어갑니다.
RSI 전략은 이 가장 폭발적인 복리 수익 구간을 “과열 구간”이라며 현금으로 구경만 하다가 대부분 놓쳐버렸습니다.
현금을 61.2%나 쥐고 있었음에도, 전략의 최대 낙폭(MDD)은 -33.1%로 단순 보유(-38.1%)와 고작 5.0%p밖에 차이 나지 않았습니다.
즉, 폭락장의 하락 위험(MDD)은 거의 고스란히 짊어지면서, 대세 상승장의 폭발적인 수익 기회만 4배 손해 보는 치명적으로 불리한 비대칭적 구조였던 셈입니다.
여기에 행동경제학적 함정도 치명적입니다.
과거 코스피 200의 RSI가 30선, 나아가 25선 밑으로 폭락했던 시점은 2011년 8월(유럽 재정위기), 2015년 8월(중국 블랙먼데이), 2018년 10월(미중 무역전쟁), 2020년 3월(코로나 쇼크), 2022년 6월(연준 빅스텝 쇼크)이었습니다.
온 세상 뉴스가 “금융 시스템 붕괴”와 “제2의 IMF”를 외치던 공포의 정점에서, 실제 살아있는 인간 투자자가 기계처럼 매수 버튼을 누르기란 불가능에 가깝습니다. 대다수는 바닥 공포를 이기지 못하고 패닉 셀을 던집니다.
[김과장의 팩트체크 카툰 2] 조기 익절과 대세 상승장 소외, 기회비용의 저주
4️⃣ “조건을 바꾸면 어떨까?” 임계치별 심층 비교
진입 기준선을 RSI 25(극단적 공포)와 RSI 35(완화된 조건)로 바꾸어 다각도로 시뮬레이션을 진행했습니다.
시나리오 검증
• 누적 수익률: +54.5% | 시장 노출도: 26.8% | MDD: -31.6% | 완결 거래: 9건
➔ 진짜 대폭락 때만 주워 MDD는 소폭 줄었으나, 매매 기회가 15.7년간 9번에 그쳐 시장 수익률(+142.6%)의 반토막에도 미치지 못했습니다.
• 누적 수익률: +33.2% | 시장 노출도: 38.8% | MDD: -33.1% | 완결 거래: 12건
➔ 가장 널리 쓰이는 세팅이지만, 수익률과 기회비용 측면에서 가장 비효율적인 최하위 수익을 기록했습니다.
• 누적 수익률: +106.1% | 시장 노출도: 56.9% | MDD: -39.5% | 완결 거래: 20건
➔ 시장 노출도가 57%로 늘며 누적 수익률은 +106%까지 올라왔으나, 최대 낙폭(MDD -39.5%)이 단순 보유(-38.1%)보다 오히려 더 커졌습니다.
완결 거래가 12건(RSI < 25는 9건)으로 통계적 표본이 매우 풍부한 것은 아닙니다.
하지만 진입 임계치를 25, 30, 35로 다양하게 변경하여 검증해도 세 조건 모두 단순 보유(+142.6%)의 성과를 넘어서지 못한다는 일관된 방향성을 보입니다.
어설픈 타이밍 매매 시도가 대세 상승장의 복리 효과를 갉아먹는다는 퀀트적 결론은 흔들리지 않습니다.
5️⃣ 독자가 직접 돌려볼 수 있는 파이썬 백테스트 코드
투명한 팩트 확인을 위해, 본문 수치를 100% 동일하게 재현하는 전체 파이썬 코드를 공개합니다. 최신 라이브러리 환경에서도 에러 없이 바로 실행됩니다.
import pandas as pd
import numpy as np
# 1. KODEX 200 (069500.KS) 데이터 로드 (2009~2024 전 구간)
df = yf.download(“069500.KS”, start=”2009-01-01″, end=”2024-12-31″, progress=False)
# 최신 yfinance MultiIndex 컬럼 평탄화
if isinstance(df.columns, pd.MultiIndex):
df = df.droplevel(1, axis=1)
# 2. Wilder 정통 14일 RSI 지표 산출
delta = df[‘Close’].diff()
gain = delta.clip(lower=0)
loss = -delta.clip(upper=0)
avg_gain = gain.ewm(alpha=1/14, min_periods=14, adjust=False).mean()
avg_loss = loss.ewm(alpha=1/14, min_periods=14, adjust=False).mean()
rs = avg_gain / avg_loss
df[‘RSI’] = 100 – (100 / (1 + rs))
# 3. 체결 컨벤션: 당일 종가 신호 확정 -> 익일 종가(Close) 체결 (shift(2))
signal = pd.Series(index=df.index, dtype=float)
signal[df[‘RSI’] < 30] = 1.0
signal[df['RSI'] > 70] = 0.0
pos = signal.ffill().fillna(0.0)
df[‘Position’] = pos.shift(2).fillna(0.0)
# 4. 일별 수익률 및 거래비용 (편도 0.10%, 왕복 0.20% 반영)
df[‘Market_Return’] = df[‘Close’].pct_change().fillna(0.0)
df[‘Trade’] = df[‘Position’].diff().abs().fillna(0.0)
fee = 0.0010 # 편도 0.10%
df[‘Strategy_Return’] = (df[‘Position’] * df[‘Market_Return’]) – (df[‘Trade’] * fee)
# 5. 누적 수익률 및 MDD 산출
df[‘Cum_Market’] = (1 + df[‘Market_Return’]).cumprod()
df[‘Cum_Strategy’] = (1 + df[‘Strategy_Return’]).cumprod()
mdd_market = ((df[‘Cum_Market’] / df[‘Cum_Market’].cummax()) – 1).min() * 100
mdd_strategy = ((df[‘Cum_Strategy’] / df[‘Cum_Strategy’].cummax()) – 1).min() * 100
total_years = (df.index[-1] – df.index[0]).days / 365.25
cagr_market = (df[‘Cum_Market’].iloc[-1] ** (1 / total_years) – 1) * 100
cagr_strategy = (df[‘Cum_Strategy’].iloc[-1] ** (1 / total_years) – 1) * 100
cum_market_pct = (df[‘Cum_Market’].iloc[-1] – 1) * 100
cum_strat_pct = (df[‘Cum_Strategy’].iloc[-1] – 1) * 100
exposure = (df[‘Position’] > 0).mean() * 100
# 6. 완결된 개별 거래(Trade) 추적
trades = []
in_trade = False
for i in range(1, len(df)):
prev_pos = df[‘Position’].iloc[i-1]
curr_pos = df[‘Position’].iloc[i]
if prev_pos == 0 and curr_pos == 1:
in_trade = True
entry_price = df[‘Close’].iloc[i-1]
elif prev_pos == 1 and curr_pos == 0 and in_trade:
in_trade = False
exit_price = df[‘Close’].iloc[i-1]
ret = (exit_price / entry_price) * (1 – fee) * (1 – fee) – 1
trades.append(ret > 0)
n_trades = len(trades)
wins = sum(trades)
print(f”단순 보유: 누적 {cum_market_pct:.1f}% | CAGR {cagr_market:.2f}% | MDD {mdd_market:.1f}%”)
print(f”RSI 전략: 누적 {cum_strat_pct:.1f}% | CAGR {cagr_strategy:.2f}% | MDD {mdd_strategy:.1f}% | 노출도 {exposure:.1f}%”)
print(f”완결 거래: 총 {n_trades}건 (승리 {wins}건, 승률 {(wins/n_trades)*100:.1f}%)”)
백테스트 데이터 질의응답(Q&A)을 나누는 순수 연구 커뮤니티입니다.
(※ 종목 추천, 리딩, 시황 전망 및 매수·매도 조언은 일절 하지 않습니다.)
6️⃣ 마치며: 마켓 타이밍의 환상에서 벗어나라
1편 ‘골든크로스’가 추세 추종 매매의 후행성 덫을 보여주었다면, 이번 2편 ‘RSI 과매도 매수’는 역발상 매매의 기회비용 함정을 데이터로 증명했습니다.
개인 투자자들은 늘 바닥에서 사서 꼭대기에서 팔 수 있다는 유혹에 빠집니다. 하지만 15.7년 치 실증 데이터가 말해주는 결론은 명확합니다.
[김과장의 팩트체크 카툰 3] 완벽한 바닥 타이밍보다 ‘머무는 시간’의 승리
다음 3편에서는 이번 역추세 매매의 반대편에 서 있는 대표적인 모멘텀 기법, ’52주 신고가 돌파 매매법’의 실전 백테스트 결과를 낱낱이 파헤쳐 드리겠습니다.
궁금한 보조지표나 검증을 원하는 매매 속설이 있으시다면 언제든 블로그 이웃 추가 후 비밀댓글로 남겨주세요. 코드로 철저히 팩트체크해 드리겠습니다.
* 단순 보유(Buy & Hold) 수익률(+142.6%)은 분배금(배당) 재투자를 제외한 순수 가격 변동 기준이며, 배당 재투자를 반영할 경우 실질 누적 복리 수익률은 더 높아집니다.
* 모든 매매 시뮬레이션에는 왕복 0.20%의 거래비용(위탁수수료 및 슬리피지)이 차감 반영되었습니다. 과거의 시뮬레이션 성과가 미래의 수익을 보장하지 않습니다.