파이썬 RSI 자동매매 전략

RSI(상대강도지수)란?

RSI(Relative Strength Index)는 J. Welles Wilder가 1978년 개발한 모멘텀 오실레이터입니다. 0~100 사이의 값으로 자산의 과매수·과매도 상태를 판단하며, 퀀트 자동매매에서 가장 널리 쓰이는 기술적 지표 중 하나입니다.

일반적으로 RSI 70 이상이면 과매수, 30 이하면 과매도로 해석합니다. 하지만 실전 파이썬 자동매매 봇에서는 단순 임계값만으로는 부족합니다. 이 글에서는 RSI 계산부터 다양한 매매 전략, 그리고 파이썬 구현까지 체계적으로 다룹니다.

RSI 계산 공식과 파이썬 구현

RSI는 일정 기간(보통 14봉) 동안의 평균 상승폭과 평균 하락폭의 비율로 계산됩니다.

import pandas as pd

def calculate_rsi(prices: pd.Series, period: int = 14) -> pd.Series:
    """RSI 계산 — Wilder's Smoothing 방식"""
    delta = prices.diff()
    gain = delta.where(delta > 0, 0.0)
    loss = (-delta).where(delta < 0, 0.0)

    avg_gain = gain.ewm(alpha=1/period, min_periods=period).mean()
    avg_loss = loss.ewm(alpha=1/period, min_periods=period).mean()

    rs = avg_gain / avg_loss
    rsi = 100 - (100 / (1 + rs))
    return rsi

핵심은 Wilder's Smoothing(지수이동평균의 변형)을 사용하는 것입니다. 단순이동평균(SMA) 방식과 결과가 달라지므로, 거래소 차트와 일치시키려면 반드시 EWM 방식을 사용해야 합니다.

기본 RSI 자동매매 전략

가장 기본적인 RSI 매매 전략은 과매도 매수, 과매수 매도입니다.

조건 액션 근거
RSI ≤ 30 매수 (롱 진입) 과매도 → 반등 기대
RSI ≥ 70 매도 (숏 진입 또는 청산) 과매수 → 조정 기대
RSI 40~60 관망 중립 구간
import ccxt

exchange = ccxt.binance({
    'apiKey': 'YOUR_API_KEY',
    'secret': 'YOUR_SECRET',
})

def rsi_strategy(symbol: str, timeframe: str = '1h'):
    """기본 RSI 자동매매 전략"""
    ohlcv = exchange.fetch_ohlcv(symbol, timeframe, limit=100)
    df = pd.DataFrame(ohlcv, columns=['ts','open','high','low','close','vol'])
    df['rsi'] = calculate_rsi(df['close'], period=14)

    current_rsi = df['rsi'].iloc[-1]

    if current_rsi <= 30:
        # 과매도: 매수 시그널
        order = exchange.create_market_buy_order(symbol, amount)
        return {'signal': 'BUY', 'rsi': current_rsi}
    elif current_rsi >= 70:
        # 과매수: 매도 시그널
        order = exchange.create_market_sell_order(symbol, amount)
        return {'signal': 'SELL', 'rsi': current_rsi}

    return {'signal': 'HOLD', 'rsi': current_rsi}

RSI 다이버전스 전략

RSI 다이버전스는 가격과 RSI의 방향이 엇갈릴 때 발생하며, 추세 전환의 강력한 신호입니다. 백테스트 과최적화 방지법을 참고하면 다이버전스 전략의 검증 방법도 확인할 수 있습니다.

  • 강세 다이버전스: 가격은 저점 갱신, RSI는 저점 상승 → 매수 신호
  • 약세 다이버전스: 가격은 고점 갱신, RSI는 고점 하락 → 매도 신호
def detect_divergence(prices: pd.Series, rsi: pd.Series, lookback: int = 20):
    """RSI 다이버전스 탐지"""
    recent_prices = prices.iloc[-lookback:]
    recent_rsi = rsi.iloc[-lookback:]

    price_low_idx = recent_prices.idxmin()
    rsi_at_price_low = recent_rsi.loc[price_low_idx]

    # 이전 저점 대비 비교
    prev_prices = prices.iloc[-lookback*2:-lookback]
    prev_low_idx = prev_prices.idxmin()
    prev_rsi_at_low = rsi.loc[prev_low_idx]

    if (recent_prices.min() < prev_prices.min() and
        rsi_at_price_low > prev_rsi_at_low):
        return 'BULLISH_DIVERGENCE'

    price_high_idx = recent_prices.idxmax()
    rsi_at_price_high = recent_rsi.loc[price_high_idx]
    prev_high_idx = prev_prices.idxmax()
    prev_rsi_at_high = rsi.loc[prev_high_idx]

    if (recent_prices.max() > prev_prices.max() and
        rsi_at_price_high < prev_rsi_at_high):
        return 'BEARISH_DIVERGENCE'

    return None

RSI + 이동평균 복합 전략

RSI 단독 사용의 한계를 보완하기 위해 이동평균선(MA)과 결합하면 승률이 크게 향상됩니다. 추세 방향은 MA로 판단하고, 진입 타이밍은 RSI로 잡는 방식입니다.

def rsi_ma_strategy(df: pd.DataFrame):
    """RSI + 이동평균 복합 전략"""
    df['rsi'] = calculate_rsi(df['close'])
    df['ma50'] = df['close'].rolling(50).mean()
    df['ma200'] = df['close'].rolling(200).mean()

    current = df.iloc[-1]
    signals = []

    # 상승 추세 + RSI 과매도 = 강한 매수
    if (current['close'] > current['ma50'] > current['ma200']
        and current['rsi'] <= 35):
        signals.append('STRONG_BUY')

    # 하락 추세 + RSI 과매수 = 강한 매도
    elif (current['close'] < current['ma50'] < current['ma200']
          and current['rsi'] >= 65):
        signals.append('STRONG_SELL')

    return signals

이 전략은 추세 추종 + 평균회귀를 결합한 것으로, 손익비 트레이딩 전략과 함께 적용하면 리스크 관리까지 체계적으로 구현할 수 있습니다.

RSI 기간별 최적화와 주의점

RSI 기간(period)은 자산과 타임프레임에 따라 최적값이 다릅니다.

타임프레임 추천 RSI 기간 과매수/과매도 기준
1분~5분 (스캘핑) 7~9 80/20
1시간 (데이트레이딩) 14 70/30
4시간~일봉 (스윙) 14~21 65/35
주봉 (포지션) 21~28 60/40

주의사항: RSI 기간을 백테스트로 최적화할 때는 반드시 워크포워드 분석을 병행해야 합니다. 과거 데이터에만 맞춘 파라미터는 실전에서 실패할 확률이 높습니다.

실전 자동매매 봇 통합 예제

아래는 RSI 전략을 실제 자동매매 봇으로 구현한 전체 코드입니다. ccxt 라이브러리로 거래소 API와 연동합니다.

import time
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('rsi_bot')

class RSITradingBot:
    def __init__(self, exchange, symbol, timeframe='1h',
                 rsi_period=14, oversold=30, overbought=70):
        self.exchange = exchange
        self.symbol = symbol
        self.timeframe = timeframe
        self.rsi_period = rsi_period
        self.oversold = oversold
        self.overbought = overbought
        self.position = None

    def fetch_rsi(self) -> float:
        ohlcv = self.exchange.fetch_ohlcv(
            self.symbol, self.timeframe, limit=self.rsi_period * 3
        )
        closes = pd.Series([c[4] for c in ohlcv])
        rsi = calculate_rsi(closes, self.rsi_period)
        return rsi.iloc[-1]

    def execute(self):
        rsi = self.fetch_rsi()
        logger.info(f"RSI={rsi:.1f} | Position={self.position}")

        if rsi <= self.oversold and self.position != 'long':
            self.position = 'long'
            logger.info("▶ 매수 진입")
            return 'BUY'

        elif rsi >= self.overbought and self.position == 'long':
            self.position = None
            logger.info("◀ 매도 청산")
            return 'SELL'

        return 'HOLD'

    def run(self, interval_sec=300):
        """메인 루프"""
        while True:
            try:
                signal = self.execute()
                logger.info(f"Signal: {signal}")
            except Exception as e:
                logger.error(f"Error: {e}")
            time.sleep(interval_sec)

# 사용 예시
bot = RSITradingBot(
    exchange=ccxt.binance({'apiKey': '...', 'secret': '...'}),
    symbol='BTC/USDT',
    timeframe='1h',
    rsi_period=14,
    oversold=30,
    overbought=70
)
bot.run(interval_sec=300)

RSI 자동매매 전략 성과 향상 팁

  • 다중 타임프레임 확인: 상위 타임프레임에서 추세를 확인한 뒤 하위 타임프레임에서 진입하면 승률이 올라갑니다.
  • 거래량 필터: RSI 신호 발생 시 거래량이 평균 이상인 경우에만 진입하면 허위 신호를 줄일 수 있습니다.
  • 스톱로스 필수: RSI가 과매도를 찍어도 계속 하락할 수 있습니다. ATR 기반 스톱로스를 반드시 설정하세요.
  • Connors RSI: 기본 RSI에 상승/하락 연속일수 RSI와 ROC 퍼센타일을 결합한 변형으로, 평균회귀 전략에 효과적입니다.
  • RSI 50선 활용: RSI 50을 기준으로 상방이면 매수 우위, 하방이면 매도 우위로 판단하는 추세 필터로 활용할 수 있습니다.

마무리

RSI는 단순하지만 강력한 지표입니다. 단독 사용보다는 이동평균, 거래량, 다이버전스와 결합했을 때 진가를 발휘합니다. 파이썬과 ccxt를 활용하면 아이디어를 빠르게 자동매매 봇으로 구현할 수 있으니, 먼저 소액으로 테스트한 뒤 점진적으로 전략을 고도화해 보세요.

위로 스크롤
WordPress Appliance - Powered by TurnKey Linux