볼린저 밴드를 활용한 변동성 돌파 전략을 구현합니다. 볼린저 밴드는 가격 변동성을 측정하는 지표입니다. 밴드 상단을 돌파할 때 매수하고 하단을 돌파할 때 매도합니다. 이 전략은 추세 추종 전략과 변동성 매매 전략을 결합합니다.
3.7.4.1 전략 로직 설명
볼린저 밴드는 중심선과 상/하단 밴드로 구성됩니다. 중심선은 일반적으로 20일 이동평균선(SMA)을 사용합니다. 상/하단 밴드는 중심선에서 표준편차의 2배만큼 떨어져 있습니다. 가격이 밴드 밖으로 벗어나는 것은 이례적인 변동성을 의미합니다.
변동성 돌파 전략은 다음과 같은 로직으로 작동합니다.
- 가격이 볼린저 밴드 상단을 돌파하면 매수 신호로 간주합니다.
- 가격이 볼린저 밴드 하단을 돌파하면 매도 신호로 간주합니다.
- 매수 후 가격이 하락하여 중심선을 하향 돌파하면 손절합니다.
- 매도 후 가격이 상승하여 중심선을 상향 돌파하면 손절합니다.
이 전략은 변동성이 커지는 시점을 포착하여 수익을 얻습니다. 손절매 규칙을 통해 리스크를 관리합니다. 볼린저 밴드 기간, 표준편차 배수, 손절매 기준 등은 최적화할 수 있습니다.
3.7.4.2 파이썬 코드 구현
볼린저 밴드 활용 변동성 돌파 전략을 파이썬으로 구현합니다. Pandas와 TA-Lib 라이브러리를 사용합니다. 업비트 API를 통해 가상화폐 데이터를 가져옵니다. 백테스팅을 통해 전략의 성능을 평가합니다.
1단계: 필요한 라이브러리 임포트
필요한 라이브러리를 임포트합니다. pandas
는 데이터 처리를 위한 라이브러리입니다. talib
은 볼린저 밴드 계산을 위한 라이브러리입니다. pyupbit
은 업비트 API를 사용하기 위한 라이브러리입니다.
import pandas as pd
import talib
import pyupbit
2단계: 데이터 획득 및 볼린저 밴드 계산
업비트 API를 사용하여 가상화폐 데이터를 가져옵니다. pyupbit.get_ohlcv()
함수를 사용합니다. 데이터프레임의 컬럼명을 통일합니다. 볼린저 밴드를 계산합니다. talib.BBANDS()
함수를 사용합니다. 기본 설정값은 기간 20, 표준편차 2배입니다.
# 업비트 API를 통해 데이터 가져오기
df = pyupbit.get_ohlcv("KRW-BTC", interval="minute60", count=500)
# 컬럼명 변경 (필요한 경우)
df.rename(columns={'open': 'Open', 'high': 'High', 'low': 'Low', 'close': 'Close', 'volume': 'Volume'}, inplace=True)
# 볼린저 밴드 계산
df['BB_UPPER'], df['BB_MIDDLE'], df['BB_LOWER'] = talib.BBANDS(df['Close'], timeperiod=20, nbdevup=2, nbdevdn=2, matype=0)
3단계: 매매 신호 생성 함수 정의
볼린저 밴드를 활용하여 매매 신호를 생성하는 함수를 정의합니다. 상단 밴드를 돌파하면 매수 신호를 생성합니다. 하단 밴드를 돌파하면 매도 신호를 생성합니다. 중심선을 기준으로 손절매 신호를 생성합니다.
def generate_bb_signals(df):
"""볼린저 밴드 활용 변동성 돌파 전략 매매 신호 생성
Args:
df (pd.DataFrame): OHLCV 데이터프레임, BB_UPPER, BB_MIDDLE, BB_LOWER, Close 컬럼 필요
Returns:
pd.DataFrame: 'signal' 컬럼이 추가된 데이터프레임 (1: 매수, -1: 매도, 0: 유지)
"""
signals = [0] * len(df)
position = 0 # 0: No position, 1: Long, -1: Short
for i in range(1, len(df)):
# 매수 신호 (상단 밴드 돌파 and No Position)
if df['Close'][i] > df['BB_UPPER'][i] and position == 0:
signals[i] = 1
position = 1
# 매도 신호 (하단 밴드 돌파 and No Position)
elif df['Close'][i] < df['BB_LOWER'][i] and position == 0:
signals[i] = -1
position = -1
# 손절매 (Long Position and 중심선 하향 돌파)
elif df['Close'][i] < df['BB_MIDDLE'][i] and position == 1:
signals[i] = -1
position = 0
# 손절매 (Short Position and 중심선 상향 돌파)
elif df['Close'][i] > df['BB_MIDDLE'][i] and position == -1:
signals[i] = 1
position = 0
else:
signals[i] = 0
df['signal'] = signals
return df
df = generate_bb_signals(df)
print(df[['Close', 'BB_UPPER', 'BB_LOWER', 'signal']].tail())
4단계: 백테스팅 함수 정의
생성된 매매 신호를 기반으로 백테스팅을 수행하는 함수를 정의합니다. 초기 자본, 수수료를 설정합니다. 각 신호에 따라 매수 및 매도 시뮬레이션을 진행합니다. 최종 자산을 계산하여 전략의 수익성을 평가합니다.
“`python
def bb_backtest(df, initial_balance=1000000, fee=0.0005):
“””볼린저 밴드 활용 변동성 돌파 전략 백테스팅
Args:
df (pd.DataFrame): OHLCV 데이터프레임, Close, signal 컬럼 필요
initial_balance (float): 초기 자본
fee (float): 거래 수수료
Returns:
float: 최종 자산
"""
balance = initial_balance
position = 0 # 0: No position, 1: Long, -1: Short
buy_price = 0
for i in range(1, len(df)):
if df['signal'][i] == 1 and position == 0: # 매수 신호 and No Position
buy_price = df['Close'][i]
balance *= (1 - fee)
position = 1
print(f"{df.index[i]}: Buy at {buy_price}")
elif df['signal'][i] == -1 and position == 1: # 매도 신호 and Long Position (손절 or 청산)
sell_price = df['Close'][i]
profit = (sell_price - buy_price) / buy_price
balance += balance * profit * (1 - fee)
position = 0
print(f"{df.index[i]}: Sell at {sell_price}, Profit: {profit:.4f}")
elif df['signal'][i] == -1 and position == 0: # 매도 신호 and No Position
buy_price = df['Close'][i]
balance *= (1 - fee)
position = -1
print(f"{df.index[i]}: Short at {buy_price}")
elif df['signal'][i] == 1 and position == -1: # 매수 신호 and Short Position (손절 or 청산)
sell_price = df['Close'][i]
profit = (buy_price - sell_price) / buy_price
balance += balance * profit * (1 - fee)
position = 0
print(f"{df.index[i]}: Cover at {sell_price}, Profit: {profit:.4f}")
if position != 0:
last_price = df['Close'][len(df) - 1]
if position == 1:
profit = (last_price - buy_price) / buy_price
else:
profit = (buy_price - last_price) / buy_price
balance += balance * profit * (1 - fee)
print(f"마지막 청산: {last_price}, 수익률: {profit:.4f}")