본문 바로가기

Python-Autotrade (Binance)

파이썬(Python) - 바이낸스(Binance) 볼린저 밴드(Bollinger Band)를 사용한 벡 테스팅(Back Testing)

 안녕하세요 요번 시간은 ccxt api를 사용하여 볼린저밴드를 통한 벡 테스팅을 하겠습니다. 

 

거래소는 바이낸스 선물거래를 사용하겠습니다.

 

제가 사용한 코드들에 대한 공부 및 출처는 글 맨아래 남겼습니다.

 

또한 자동매매에 관심있는분이나 코드에 대해 질문이 있으면 댓글 혹은 메일 부탁드립니다.

 

1.  바이낸스(Binance) 선물 ohlcv 불러오기
import ccxt
import pandas as pd

with open('경로//binance_api_key.txt') as f:
    lines = f.readlines()
    api_key = lines[0].strip()
    secret = lines[1].strip()

binance = ccxt.binance(config={
    'apiKey': api_key, 
    'secret': secret,
    'enableRateLimit': True,
    'options': {
        'defaultType': 'future'
    }
})

btc_ohlcv = binance.fetch_ohlcv(symbol='BTC/USDT', timeframe='15m',limit = 4000)
df = pd.DataFrame(btc_ohlcv, columns=['datetime', 'open', 'high', 'low', 'close', 'volume'])
df['datetime'] = pd.to_datetime(df['datetime'], unit='ms')

 

- 필자는 바이낸스 api를 사용하기 위한 api_key 와 secret key를 txt파일에 각각 한줄씩 저장하여 관리하였습니다.

  파일 경로의 경우 txt 파일의 위치로 설정합니다. (코드 4번 줄)

 

- Binacne의 defaultTpye 을 future(선물)로 설정 하였습니다 (코드 14번 줄). 

 

- 불러온 바이낸스 객체에 BTC/USDT, 15분간격, 총 4000개의 ohlcv를 dataframe으로 가공했습니다. (코드 18번 줄)

  여기서 각자 원하는 symbol, timeframe, limit 를 설정하시면 됩니다. ex) ( BTC/ETH, 1h, 500)

 

 

2. 데이터 프레임(Data frame)을 사용한 벡 테스팅(Back Testing)

 

 무료 백 테스팅의 경우,  해외 유투버들이나 깃허브를 통해 다양한 예시를 찾을 수 있었습니다.  

이번 벡 테스팅은 유투버 ThePrincipalComponent 님의 코드를 사용하였고 출처는 맨 아래에 남겨두겠습니다. 

 

이번 벡 테스팅은 볼린저 밴드를 사용하였습니다.  자세한 코드는 아래와 같습니다.

import ccxt
import pandas as pd
import numpy as np

with open('경로//binance_api_key.txt') as f:
    lines = f.readlines()
    api_key = lines[0].strip()
    secret = lines[1].strip()

binance = ccxt.binance(config={
    'apiKey': api_key, 
    'secret': secret,
    'enableRateLimit': True,
    'options': {
        'defaultType': 'future'
    }
})

btc_ohlcv = binance.fetch_ohlcv(symbol='BTC/USDT', timeframe='1h',limit = 500)
df = pd.DataFrame(btc_ohlcv, columns=['datetime', 'open', 'high', 'low', 'close', 'volume'])
df['datetime'] = pd.to_datetime(df['datetime'], unit='ms')

def sma(data,window):
   return(data.rolling(window=window).mean())

def bollinger_bands(data,sma,window,ntsd):
   std = data.rolling(window=window).std()
   upper_band = sma + std * ntsd
   lower_band = sma - std * ntsd
   return upper_band, lower_band

ntsd = 3
df['sma'] = sma(df['open'],20)
df['upper_band'], df['lower_band'] = bollinger_bands(df['close'], df['sma'], 20, ntsd)
df.dropna(inplace=True)

class TradingEnv:
    def __init__(self,balance_amount,balance_unit,trading_fee_multiplier):
        self.balance_amount = balance_amount
        self.balance_unit = balance_unit
        self.check = []
        self.buys = []
        self.sells = []
        self.trading_fee_multiplier = trading_fee_multiplier

    def buy(self,symbol,buy_price,time):
        self.balance_amount = self.balance_amount / buy_price * self.trading_fee_multiplier
        self.buys.append([symbol,'buy',time,buy_price])
        self.check.append('buy')

    def sell(self,sell_price,time):
        self.balance_amount = self.balance_amount * sell_price * self.trading_fee_multiplier
        self.sells.append([self.balance_unit,'sell', time, sell_price])
        self.check.clear()

env = TradingEnv(balance_amount=100,balance_unit='USDT',trading_fee_multiplier = 0.9996)

for i in range(len(df)):
    if len(env.check) == 0:
        if 'buy' not in env.check:
            if df['close'].iloc[i] < df['lower_band'].iloc[i]: #buy_signal
                env.buy('USDT',df['lower_band'].iloc[i],df['datetime'].iloc[i])

    if len(env.check) == 1:
        if df['high'].iloc[i] > df['upper_band'].iloc[i]: #sell_signal
            env.sell(df['upper_band'].iloc[i],df['datetime'].iloc[i])

print(f'num buys: {len(env.buys)}')
print(f'num sells: {len(env.sells)}')
print(f'ending balance: {env.balance_amount} {env.balance_unit}')

 

제가 인용한 유투버(ThePrincipalComponent)님은 다수의 코인의, 시작과 끝 가격이 같은 (횡보장)  ohlcv 자료가 들어가는 하나의 엑셀 파일을 사용하여 볼린저 밴드를 사용해 벡테스팅을 하였습니다.

 

필자의 경우 1.  바이낸스(Binance) 선물 ohlcv 불러오기 를 사용해 BTC/USDT dataframe을 사용합니다.

 

- Dataframe은 symbol = BTC/USDT, timeframe = '1h', limit = 500개 (코드 19줄)을 사용합니다.

 

- 볼린저 밴드의 Middle Bollinger Band (mbb), Upper Bollinger Band (ubb), Lower Bollinger Band (lbb) 구하는 함수는 def    sma(), def bollinger_bands() 입니다.

 

  볼린저 밴드에서 설정하는 숫자는 총 2개입니다. 

  1. 몇개의 평균을 사용하여 mbb, std로 가공할지 (주로 20을 사용, 코드에선 window=20)

  2. 표준편차에 곱하는 상수 (주로 2를 사용 하지만 3을 사용, 코드에선 ntsd)

 

  위의 두 숫자를 사용하여 함수를 통해 mbb, ubb, lbb를 구합니다. 

 

- 다음은 Class를 사용하여  env라는 객체를 생성합니다.  env에는 balance_amount, balance_unit, trading_fee_multipiler      가 들어가게 되고,  __init__ 에 chek, buys, sells 리스트를 생성하여 각 list의 길이(len())을 사용해 시그널을 주어 for loop    를 돌립니다.

 

- 볼린저 밴드 기법은, 종가(close)의 값이 Lower band (lb)보다 작게 되면 매수, Upper band (ub)를 넘게 되면 매도하는 간    단한 원리입니다. 이 원리를 사용하여 수익을 최대화 시킬려면, 볼린저 밴드의 폭이 넓고, 거래 수가 작아야 손실을 최소      로 할수 있기 때문에 ntsd = 3, timeframe = '1h' 로 사용하였습니다. 

 

- 2022.07.31 00:23 기준으로 결과는 다음과 같습니다.

num buys: 4
num sells: 4
ending balance: 106.22011061321444 USDT

 수익률은 약 6퍼센트가 나왔습니다. 선물 거래이기 때문에 레버지를 사용하면 더 좋은 수익을 올릴수 있습니다. (하지만 리크스 또한 올라감)

 

이번 벡 테스팅은 ntst의 값을 기존의 2가 아닌 3으로 설정하여 최대한 신중하게 매매를 할수있도록 하였습니다. 또한 롱 

포지션(가격이 오르면 수익)을 사용하였기 때문에, dataframe의 timeframe을 크게 한다면 ex) 3000,4000 최근의 하락장으로 인하여 수익이 좋지 못합니다. 

 

따라서 위의 벡테스팅 코드 틀을 사용하되, 사용 전략은 좀더 수정하여 사용하면 더 좋은 결과가 나올것 같습니다 !

  

 

3.  출처

바이낸스 api 신청 및 사용법 

[1] https://wikidocs.net/book/1665

 

파이썬을 이용한 비트코인 자동매매 (개정판)

이 책은 최근 인기 있는 프로그래밍 언어인 파이썬을 사용하여 국내 3대 거래소(코빗, 빗썸, 업비트) 및 국외 거래소(바이넨스)에서 비트코인을 자동매매하는 프로그램을 개발하 ...

wikidocs.net

 

파이썬 - 클래스(Class) 사용 법

[2] https://wikidocs.net/28

 

05-1 클래스

초보 개발자들에게 클래스(class)는 넘기 힘든 장벽과도 같은 존재이다. 독자들 중에도 클래스라는 단어를 처음 접하는 이들도 있을 것이다. 그러면 도대체 클래스가 무엇인지 ...

wikidocs.net

 

볼린저 밴드를 사용한 백 테스팅

[3] https://www.youtube.com/watch?v=6H_DLZg2e_M