반응형
데이터를 가져오는 것만으로는 자동매매가 시작되지 않는다.
시세 흐름 속에서 어떤 조건일 때 매수하고, 언제 매도할지를 정해야 한다.
이때 필요한 것이 바로 기술적 지표다.
이번 글에서는 대표적인 기술적 지표인 이동평균선(MA), RSI, 볼린저 밴드를 직접 계산하고,
이를 기반으로 간단한 매수·매도 시그널 생성 로직을 구현해본다.
1. 준비: 캔들 데이터 가져오기
앞선 글에서처럼 fetch_ohlcv()로 최근 100개의 5분봉 캔들 데이터를 가져온다.
import ccxt
import pandas as pd
binance = ccxt.binance({'enableRateLimit': True})
symbol = 'BTC/USDT'
ohlcv = binance.fetch_ohlcv(symbol, timeframe='5m', limit=100)
df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
2. 이동평균선 (Moving Average)
가장 기본적인 지표 중 하나다.
특정 기간의 종가 평균을 내면 된다.
# 20기간 이동평균선
df['ma20'] = df['close'].rolling(window=20).mean()
3. RSI (Relative Strength Index)
RSI는 가격이 과매수(overbought) 또는 과매도(oversold) 상태에 있는지를 나타내는 지표다.
보통 RSI가 70 이상이면 과매수, 30 이하면 과매도로 해석한다.
직접 구현하면 다음과 같다:
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
rsi = 100 - (100 / (1 + rs))
return rsi
df['rsi14'] = calculate_rsi(df['close'], 14)
4. 볼린저 밴드 (Bollinger Bands)
볼린저 밴드는 이동평균선 기준으로 표준편차를 위아래에 더한 밴드를 만든다.
period = 20
std = df['close'].rolling(window=period).std()
df['bb_middle'] = df['close'].rolling(window=period).mean()
df['bb_upper'] = df['bb_middle'] + 2 * std
df['bb_lower'] = df['bb_middle'] - 2 * std
5. 간단한 매수·매도 조건
이제 지표를 활용해서 단순한 매매 조건을 만들어본다.
예를 들어 아래와 같은 조건을 생각해볼 수 있다:
- 매수 조건: 종가가 볼린저 밴드 하단을 하회하고, RSI가 30 미만
- 매도 조건: 종가가 볼린저 밴드 상단을 돌파하고, RSI가 70 초과
last = df.iloc[-1]
if last['close'] < last['bb_lower'] and last['rsi14'] < 30:
print("매수 시그널 발생")
elif last['close'] > last['bb_upper'] and last['rsi14'] > 70:
print("매도 시그널 발생")
else:
print("관망")
6. 결과 확인
위 코드들을 하나의 .py 파일에 모아 실행해보면,
현재 시장 상황에서 매매 시그널이 나오는지 여부를 직접 확인할 수 있다.
이 결과를 기반으로 알림을 보내거나, 실제 주문으로 연결하는 로직을 추가해나가게 된다.
대략적으로 종합한 테스트 파일은 아래와 같다.
이제 기본적인 틀이 갖추어 졌으니 실제 전략이 어떻게 결과를 만들어내는지 알아볼 일이 남아있다.
import ccxt
import pandas as pd
# 바이낸스 객체 생성 (API 키 없음)
binance = ccxt.binance({
'enableRateLimit': True
})
# 심볼과 캔들 간격 설정
symbol = 'BTC/USDT'
timeframe = '5m'
limit = 100
# 캔들 데이터 가져오기
ohlcv = binance.fetch_ohlcv(symbol, timeframe=timeframe, limit=limit)
df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
# 이동평균선 계산 (20기간)
df['ma20'] = df['close'].rolling(window=20).mean()
# 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
rsi = 100 - (100 / (1 + rs))
return rsi
df['rsi14'] = calculate_rsi(df['close'], 14)
# 볼린저 밴드 계산 (20기간, 2표준편차)
period = 20
std = df['close'].rolling(window=period).std()
df['bb_middle'] = df['ma20']
df['bb_upper'] = df['bb_middle'] + 2 * std
df['bb_lower'] = df['bb_middle'] - 2 * std
# 최신 캔들 기준으로 시그널 출력
last = df.iloc[-1]
print(f"현재가: {last['close']:.2f}")
print(f"볼린저밴드 하단: {last['bb_lower']:.2f}, 상단: {last['bb_upper']:.2f}")
print(f"RSI(14): {last['rsi14']:.2f}")
if last['close'] < last['bb_lower'] and last['rsi14'] < 30:
print("📈 매수 시그널 발생")
elif last['close'] > last['bb_upper'] and last['rsi14'] > 70:
print("📉 매도 시그널 발생")
else:
print("⏸️ 관망")
반응형
'코인' 카테고리의 다른 글
[자동매매봇 만들기][6편] 백테스트로 전략 검증하기 – 과거 데이터로 수익률 확인하기 (0) | 2025.06.06 |
---|---|
[자동매매봇 만들기][5편] 텔레그램 봇 연동 – 매매 시그널 알림 보내기 (0) | 2025.05.17 |
[자동매매봇 만들기][3편] 바이낸스에서 실시간 시세와 캔들 데이터 가져오기 (API 키 없이) (2) | 2025.05.14 |
[자동매매봇만들기][2편] 환경 세팅 - 파이썬 & ccxt 설치하기 (PyCharm 기준) (0) | 2025.05.12 |
[자동매매봇만들기][1편] 바이낸스 자동매매봇, 왜 만들까? (8) | 2025.05.11 |