코인

[자동매매봇 만들기][6편] 백테스트로 전략 검증하기 – 과거 데이터로 수익률 확인하기

stupidsoft 2025. 6. 6. 10:39
반응형

 

 

지금까지는 실시간 데이터를 기반으로 전략을 만들고, 매매 시그널도 만들었다.
하지만 아직 전략의 "신뢰성"은 검증되지 않았다.
그 전략이 과거에도 통했는지, 어느 정도 수익이나 손실을 냈는지를 확인해야 한다.
그게 바로 **백테스트(Backtest)**다.


1. 백테스트 개념 정리

백테스트란?
과거의 시세 데이터에 내 전략을 그대로 적용해보고,
그 전략이 매수/매도 신호를 얼마나 정확하게 냈는지,
얼마의 수익 또는 손실을 냈는지를 계산해보는 작업이다.


2. 준비: OHLCV 데이터 불러오기

이번에는 실시간 API가 아니라, 백테스트용으로 저장된 데이터를 사용할 수도 있다.
하지만 간단히 하기 위해서, 바이낸스에서 가져온 5분봉 최근 500개의 데이터로 테스트하자.

import ccxt
import pandas as pd

binance = ccxt.binance({'enableRateLimit': True})

symbol = 'BTC/USDT'
ohlcv = binance.fetch_ohlcv(symbol, timeframe='5m', limit=500)

df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')

3. 지표 계산

RSI와 볼린저 밴드 중심 전략을 다시 구현한다.

# RSI 계산
def calculate_rsi(series, period=14):
    delta = series.diff()
    gain = delta.where(delta > 0, 0)
    loss = -delta.where(delta < 0, 0)
    avg_gain = gain.rolling(window=period).mean()
    avg_loss = loss.rolling(window=period).mean()
    rs = avg_gain / avg_loss
    return 100 - (100 / (1 + rs))

df['rsi14'] = calculate_rsi(df['close'])

# 볼린저 밴드
period = 20
df['ma20'] = df['close'].rolling(window=period).mean()
std = df['close'].rolling(window=period).std()
df['bb_upper'] = df['ma20'] + 2 * std
df['bb_lower'] = df['ma20'] - 2 * std

4. 전략 로직 (간단한 매수/매도 조건)

  • 매수 진입 조건: 종가가 볼린저 밴드 하단보다 낮고, RSI가 30 미만
  • 청산 조건: 종가가 볼린저 중심선을 회복할 때 매도 (익절 or 손절)
position = None
entry_price = 0
returns = []

for i in range(1, len(df)):
    row = df.iloc[i]
    prev = df.iloc[i-1]

    # 진입
    if position is None:
        if row['close'] < row['bb_lower'] and row['rsi14'] < 30:
            position = 'long'
            entry_price = row['close']

    # 청산
    elif position == 'long':
        if row['close'] > row['ma20']:  # 볼밴 중심선 회복 시 청산
            exit_price = row['close']
            ret = (exit_price - entry_price) / entry_price
            returns.append(ret)
            position = None

5. 수익률 분석

import numpy as np

if returns:
    total_return = np.prod([1 + r for r in returns]) - 1
    win_rate = sum(1 for r in returns if r > 0) / len(returns)
    avg_profit = np.mean(returns)

    print(f"총 거래 횟수: {len(returns)}")
    print(f"승률: {win_rate * 100:.2f}%")
    print(f"평균 수익률: {avg_profit * 100:.2f}%")
    print(f"누적 수익률: {total_return * 100:.2f}%")
else:
    print("거래 없음")

예시 출력:

총 거래 횟수: 8
승률: 62.50%
평균 수익률: 1.12%
누적 수익률: 9.37%

마무리하며

지표를 활용한 전략을 단순히 이론으로 만들고 끝나는 게 아니라,
실제로 수익이 났는지 수치로 확인하는 백테스트는 반드시 필요한 단계다.
지금은 아주 기본적인 전략과 조건으로 테스트했지만,
이걸 기반으로 더 정교한 전략으로 발전시킬 수 있다.

다.

반응형