피보나치 되돌림 자동매매 전략

피보나치 되돌림이란?

피보나치 되돌림(Fibonacci Retracement)은 가격이 추세 방향으로 움직인 뒤, 일정 비율만큼 되돌아오는 지점을 예측하는 기술적 분석 도구입니다. 23.6%, 38.2%, 50%, 61.8%, 78.6% 수준이 핵심 되돌림 레벨로, 전 세계 트레이더들이 지지·저항 판단에 활용합니다.

이 글에서는 파이썬으로 피보나치 되돌림 레벨을 자동 계산하고, 해당 레벨에서 매매 신호를 생성하는 자동매매 전략을 단계별로 구현합니다. 백테스트 결과까지 포함해 실전에 바로 적용할 수 있도록 안내합니다.

피보나치 되돌림 핵심 레벨

레벨 비율 의미
Level 1 23.6% 얕은 되돌림, 강한 추세 지속 시 첫 지지
Level 2 38.2% 일반적인 되돌림, 건강한 조정 구간
Level 3 50.0% 심리적 중간 지점, 많은 트레이더가 주시
Level 4 61.8% 황금 비율, 가장 강력한 되돌림 지지선
Level 5 78.6% 깊은 되돌림, 추세 전환 가능성 경고

전략 개요: 피보나치 되돌림 매매 로직

자동매매 전략의 핵심 로직은 다음과 같습니다:

  • 스윙 하이·로우 자동 탐지: 일정 기간(lookback) 내 최고점과 최저점을 자동으로 찾습니다.
  • 피보나치 레벨 계산: 스윙 포인트 기반으로 되돌림 레벨을 실시간 산출합니다.
  • 매수 신호: 가격이 38.2%~61.8% 레벨에 도달하고 반등 캔들이 확인되면 매수합니다.
  • 매도 신호: 가격이 스윙 하이 근처 또는 0% 레벨에 도달하면 익절합니다.
  • 손절: 78.6% 레벨 하향 돌파 시 손절로 리스크를 관리합니다.

파이썬 구현: 스윙 포인트 탐지

먼저 가격 데이터에서 스윙 하이(Swing High)와 스윙 로우(Swing Low)를 자동으로 찾는 함수를 구현합니다.

import pandas as pd
import numpy as np

def find_swing_points(df, lookback=20):
    """스윙 하이·로우를 자동 탐지"""
    highs = df['high'].rolling(window=lookback, center=True).max()
    lows = df['low'].rolling(window=lookback, center=True).min()

    swing_high_mask = df['high'] == highs
    swing_low_mask = df['low'] == lows

    # 가장 최근 스윙 포인트 반환
    last_swing_high = df.loc[swing_high_mask, 'high'].iloc[-1]
    last_swing_low = df.loc[swing_low_mask, 'low'].iloc[-1]

    return last_swing_high, last_swing_low

lookback 파라미터를 조절하면 단기(10~15)·중기(20~30)·장기(50+) 스윙 포인트를 탐지할 수 있습니다.

피보나치 되돌림 레벨 계산

def calc_fib_levels(swing_high, swing_low):
    """피보나치 되돌림 레벨 계산"""
    diff = swing_high - swing_low
    levels = {
        '0.0%': swing_high,
        '23.6%': swing_high - diff * 0.236,
        '38.2%': swing_high - diff * 0.382,
        '50.0%': swing_high - diff * 0.500,
        '61.8%': swing_high - diff * 0.618,
        '78.6%': swing_high - diff * 0.786,
        '100.0%': swing_low,
    }
    return levels

# 사용 예시
swing_high, swing_low = find_swing_points(df)
fib = calc_fib_levels(swing_high, swing_low)
for level, price in fib.items():
    print(f"{level}: {price:,.2f}")

매매 신호 생성 로직

피보나치 레벨과 가격 액션을 결합해 실제 매매 신호를 생성합니다. 단순히 레벨 터치만으로 진입하면 위험하므로, 확인 캔들(confirmation candle) 조건을 추가합니다.

def generate_signals(df, fib_levels, tolerance=0.005):
    """피보나치 레벨 기반 매매 신호 생성"""
    signals = pd.Series(0, index=df.index)

    fib_382 = fib_levels['38.2%']
    fib_618 = fib_levels['61.8%']
    fib_786 = fib_levels['78.6%']
    fib_0 = fib_levels['0.0%']

    for i in range(2, len(df)):
        price = df['close'].iloc[i]
        prev_close = df['close'].iloc[i - 1]
        prev_open = df['open'].iloc[i - 1]

        # 매수: 38.2%~61.8% 구간 + 양봉 확인
        in_buy_zone = fib_618 * (1 - tolerance) <= price <= fib_382 * (1 + tolerance)
        bullish_candle = prev_close > prev_open  # 이전 봉이 양봉

        if in_buy_zone and bullish_candle:
            signals.iloc[i] = 1  # 매수

        # 매도: 0% 레벨(스윙 하이) 근처 도달
        elif price >= fib_0 * (1 - tolerance):
            signals.iloc[i] = -1  # 매도

        # 손절: 78.6% 하향 돌파
        elif price < fib_786 * (1 - tolerance):
            signals.iloc[i] = -2  # 손절

    return signals

백테스트 구현

생성된 신호를 기반으로 간단한 백테스트를 수행합니다. 포지션 관리와 수익률 계산을 포함합니다.

def backtest_fib_strategy(df, signals, initial_capital=10_000_000):
    """피보나치 되돌림 전략 백테스트"""
    capital = initial_capital
    position = 0
    entry_price = 0
    trades = []

    for i in range(len(df)):
        sig = signals.iloc[i]
        price = df['close'].iloc[i]

        if sig == 1 and position == 0:
            # 매수 진입
            position = capital / price
            entry_price = price
            capital = 0

        elif sig in [-1, -2] and position > 0:
            # 매도 또는 손절
            capital = position * price
            pnl_pct = (price - entry_price) / entry_price * 100
            trades.append({
                'entry': entry_price,
                'exit': price,
                'pnl_pct': pnl_pct,
                'type': '익절' if sig == -1 else '손절'
            })
            position = 0

    # 결과 요약
    final_value = capital if position == 0 else position * df['close'].iloc[-1]
    total_return = (final_value - initial_capital) / initial_capital * 100

    trade_df = pd.DataFrame(trades)
    win_rate = (trade_df['pnl_pct'] > 0).mean() * 100 if len(trades) > 0 else 0

    return {
        'total_return': total_return,
        'num_trades': len(trades),
        'win_rate': win_rate,
        'avg_pnl': trade_df['pnl_pct'].mean() if len(trades) > 0 else 0,
        'trades': trade_df
    }

RSI 필터로 신호 정확도 높이기

피보나치 되돌림 단독으로 사용하면 허위 신호가 발생할 수 있습니다. RSI(상대강도지수)를 보조 필터로 추가하면 승률을 크게 개선할 수 있습니다.

def add_rsi_filter(df, period=14):
    """RSI 계산 후 필터 적용"""
    delta = df['close'].diff()
    gain = delta.where(delta > 0, 0).rolling(window=period).mean()
    loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
    rs = gain / loss
    df['rsi'] = 100 - (100 / (1 + rs))
    return df

def enhanced_signals(df, fib_levels, tolerance=0.005):
    """RSI 필터 적용된 강화 신호"""
    df = add_rsi_filter(df)
    base_signals = generate_signals(df, fib_levels, tolerance)

    for i in range(len(df)):
        # 매수 신호 + RSI 30~50 구간만 허용 (과매도 반등)
        if base_signals.iloc[i] == 1:
            if not (30 <= df['rsi'].iloc[i] <= 50):
                base_signals.iloc[i] = 0  # 필터링

    return base_signals

RSI가 30~50 구간일 때만 매수를 허용하면, 과매도 반등 타이밍과 피보나치 지지가 겹치는 고확률 진입점만 포착할 수 있습니다.

실전 적용 시 주의사항

  • 추세 확인 필수: 피보나치 되돌림은 추세 시장에서만 유효합니다. 횡보장에서는 레벨이 무의미해집니다. 이동평균선이나 MACD 신호로 추세를 먼저 확인하세요.
  • 다중 시간대 분석: 일봉 피보나치 레벨과 4시간봉 레벨이 겹치는 구간(confluence)은 더 강력한 지지·저항이 됩니다.
  • 포지션 사이징: 한 번의 거래에 전체 자산의 1~2%만 리스크로 설정하세요. 포지션 사이징 전략을 함께 참고하면 리스크 관리가 훨씬 수월해집니다.
  • 슬리피지 고려: 실제 거래에서는 호가 스프레드와 슬리피지가 수익률을 깎습니다. 백테스트 결과에 0.05~0.1% 슬리피지를 반영하세요.
  • 과최적화 경계: lookback, tolerance 등 파라미터를 과도하게 튜닝하면 과거 데이터에만 맞는 전략이 됩니다. 아웃오브샘플 테스트를 반드시 수행하세요.

전체 코드: 피보나치 자동매매 봇

import ccxt
import pandas as pd
import time

def run_fib_bot(symbol='BTC/USDT', timeframe='4h', lookback=20):
    """피보나치 되돌림 자동매매 봇 메인 루프"""
    exchange = ccxt.binance({'enableRateLimit': True})

    while True:
        # 1. OHLCV 데이터 수집
        ohlcv = exchange.fetch_ohlcv(symbol, timeframe, limit=100)
        df = pd.DataFrame(ohlcv, columns=['ts','open','high','low','close','vol'])

        # 2. 스윙 포인트 + 피보나치 계산
        sh, sl = find_swing_points(df, lookback)
        fib = calc_fib_levels(sh, sl)

        # 3. RSI 강화 신호
        signals = enhanced_signals(df, fib)
        latest = signals.iloc[-1]

        # 4. 주문 실행
        current_price = df['close'].iloc[-1]
        if latest == 1:
            print(f"[매수] {symbol} @ {current_price:,.2f}")
            print(f"  목표: {fib['0.0%']:,.2f} | 손절: {fib['78.6%']:,.2f}")
            # exchange.create_market_buy_order(symbol, amount)
        elif latest in [-1, -2]:
            action = '익절' if latest == -1 else '손절'
            print(f"[{action}] {symbol} @ {current_price:,.2f}")
            # exchange.create_market_sell_order(symbol, amount)

        # 5. 대기
        time.sleep(60 * 15)  # 15분 대기

if __name__ == '__main__':
    run_fib_bot()

마무리

피보나치 되돌림은 단순하면서도 강력한 기술적 분석 도구입니다. 파이썬으로 자동화하면 감정 없이 일관된 매매가 가능해지고, RSI 같은 보조지표와 결합하면 승률을 더 높일 수 있습니다. 핵심은 38.2%~61.8% 골든 존에서의 확인 매수와, 78.6% 레벨의 엄격한 손절입니다. 백테스트로 전략을 검증한 뒤 소액으로 실전 테스트를 거쳐 안정적인 자동매매 시스템을 구축해 보세요.

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