본문 바로가기
암호화폐 자동매매/모델 개발

[바이비트 (ByBit) 자동매매] pybit 모듈 설치 및 과거 데이터 조회

by EMES_ 2024. 1. 14.

이번 포스팅에서는 pybit 라이브러리를 이용하여 과거 데이터를 조회해 보도록 하겠습니다.

 

pybit 는 바이비트 api를 호출해서 여러 작업을 수행할 수 있게 해주는 파이썬 라이브러리 인데요, pybit를 이용하여 과거 데이터 조회 및 선물/현물 거래 등을 수행할 수 있습니다.

 

pybit는 아래 명령어로 설치 가능합니다.

pip install pybit

저는 아나콘다 가상환경을 사용중이기 때문에 가상환경 안에다가 설치해 주었습니다.

 

pybit 의 여러 함수들의 설명 및 사용법은 아래 링크에서 확인할 수 있습니다. 여러 언어들로 예제도 있어 보고 쉽게 따라할 수 있습니다.

https://bybit-exchange.github.io/docs/v5/intro

 

Introduction | Bybit API Documentation

Overview

bybit-exchange.github.io

 

주가 예측 모델을 만들기 위해서는 과거 데이터가 가장 중요하겠죠. 과거 데이터를 조회하는 코드를 작성해 봅시다.

위 링크에서 Market-Get Kline 탭으로 가면 과거 캔들 데이터를 불러오는 방법을 알 수 있습니다.

 

맨 아래쪽에 가시면 예제 코드가 나와있는데요, python 문법에 맞는 예제 코드를 살펴봅시다.

from pybit.unified_trading import HTTP
session = HTTP(testnet=True)
print(session.get_kline(
    category="inverse",
    symbol="BTCUSD",
    interval=60,
    start=1670601600000,
    end=1670608800000,
))

라고 예제코드가 나와 있는데요, 여기서 session.get_kline 의 입력 인자들은 위 페이지에도 나와있듯 아래와 같습니다.

상품, 코인 이름, 시간간격, 시작시간, 끝시간, 데이터 크기 제한 이렇게 입력이 가능하구요, 리턴값은 아래와 같습니다.

카테고리와 심볼은 입력과 같게 나오구요, 결과값은 list 에 담겨져 나오는데 순서대로 시간, 시가, 고가, 저가, 종가, 거래량, 턴오버 입니다.

위 예제를 그대로 실행시키면 아래와 같이 출력됩니다.

{'retCode': 0, 'retMsg': 'OK', 'result': {'symbol': 'BTCUSD', 'category': 'linear', 'list': [['1705222800000', '42998', '42998', '42982.5', '42984.5', '224', '0.00521086'], ['1705222740000', '42988', '42998', '42980', '42998', '256', '0.00595507'], ['1705222680000', '42973', '42988.5', '42973', '42988', '173', '0.00402493'], ['1705222620000', '42973', '42984.5', '42973', '42973', '206', '0.00479345'], ['1705222560000', '42970.5', '42985.5', '42970.5', '42973', '219', '0.0050952'], ['1705222500000', '42974.5', '42989', '42970.5', '42970.5', '194', '0.00451391'], ['1705222440000', '42971.5', '42983.5', '42971.5', '42974.5', '179', '0.00416495'], ['1705222380000', '42968', '42992', '42968', '42971.5', '194', '0.00451369'], ['1705222320000', '42964.5', '42985', '42964.5', '42968', '138', '0.00321116'], ['1705222260000', '42966', '42968', '42950.5', '42964.5', '126', '0.00293272'], ['1705222200000', '42966', '42976.5', '42954.5', '42966', '203', '0.00472464'], ['1705222140000', '42966', '42983', '42966', '42966', '209', '0.00486384'], ['1705222080000', '42957.5', '42985', '42957.5', '42966', '169', '0.00393251'], ['1705222020000', '42931', '42964', '42931', '42957.5', '185', '0.00430747'], ['1705221960000', '42912', '42931', '42912', '42931', '223', '0.00519523'], ['1705221900000', '42940.5', '42940.5', '42912', '42912', '66372', '1.5462676'], ['1705221840000', '42942.5', '42943', '42927', '42940.5', '206', '0.00479756'], ['1705221780000', '42946', '42951', '42942.5', '42942.5', '114669', '2.67029113'], ['1705221720000', '42924', '42946', '42924', '42946', '156', '0.0036329'], ['1705221660000', '42939.5', '42939.5', '42924', '42924', '171', '0.00398317'], ['1705221600000', '42898.5', '42939.5', '42898.5', '42939.5', '184', '0.00428717'], ['1705221540000', '42910', '42910', '42898.5', '42898.5', '155', '0.00361293'], ['1705221480000', '42899.5', '42910', '42888', '42910', '151', '0.00351951'], ['1705221420000', '42916.5', '42916.5', '42888', '42899.5', '53140', '1.23846514'], ['1705221360000', '42914', '42927.5', '42908', '42916.5', '152984', '3.56496069'], ['1705221300000', '42914', '42925.5', '42914', '42914', '1191', '0.02774669'], ['1705221240000', '42925', '42925.5', '42912.5', '42914', '100108', '2.33216118'], ['1705221180000', '42946', '42946', '42925', '42925', '288992', '6.73221533'], ['1705221120000', '42916.5', '42946', '42916.5', '42946', '300', '0.00698628'], ['1705221060000', '42908.5', '42936', '42902.5', '42916.5', '164679', '3.83761272'], ['1705221000000', '42915', '42924', '42896', '42908.5', '689305', '16.06458758'], ['1705220940000', '42917', '42918', '42910', '42915', '289214', '6.73907143'], ['1705220880000', '42923', '42923', '42911', '42917', '133', '0.00309917'], ['1705220820000', '42932', '42932', '42918', '42923', '100240', '2.33537193'], ['1705220760000', '42946', '42946', '42926.5', '42932', '200254', '4.66444919'], ['1705220700000', '42957.5', '42957.5', '42935.5', '42946', '440983', '10.26738086'], ['1705220640000', '42958.5', '42968', '42952.5', '42957.5', '223', '0.00519091'], ['1705220580000', '42931', '42958.5', '42931', '42958.5', '73384', '1.70890867'], ['1705220520000', '42930', '42932.5', '42926.5', '42931', '63877', '1.48788191'], ['1705220460000', '42906', '42940.5', '42899.5', '42930', '349997', '8.15486311'], ['1705220400000', '42906', '42906', '42905.5', '42906', '100153', '2.33426944'], ['1705220340000', '42920', '42920', '42906', '42906', '100281', '2.33684412'], ['1705220280000', '42930.5', '42930.5', '42919.5', '42920', '242627', '5.65270654'], ['1705220220000', '42927', '42930.5', '42919.5', '42930.5', '188', '0.00437967'], ['1705220160000', '42953', '42958', '42927', '42927', '467694', '10.89261953'], ['1705220100000', '42937.5', '42955.5', '42937.5', '42953', '55285', '1.28747807'], ['1705220040000', '42939', '42940.5', '42937.5', '42937.5', '270', '0.0062881'], ['1705219980000', '42949', '42961.5', '42939', '42939', '200145', '4.65984094'], ['1705219920000', '42956.5', '42956.5', '42949', '42949', '239', '0.00556393'], ['1705219860000', '42966', '42966', '42955', '42956.5', '100146', '2.33137432'], ['1705219800000', '42966', '42966', '42957', '42966', '136', '0.00316546'], ['1705219740000', '42961', '42966', '42952.5', '42966', '206', '0.0047956'], ['1705219680000', '42949', '42973.5', '42949', '42961', '402406', '9.3683823'], ['1705219620000', '42970', '42970', '42949', '42949', '352488', '8.20407416'], ['1705219560000', '42996', '42996', '42961.5', '42970', '703975', '16.37909829'], ['1705219500000', '43010', '43015.5', '42996', '42996', '271976', '6.32490606'], ['1705219440000', '43010.5', '43023.5', '43010', '43010', '206', '0.00478853'], ['1705219380000', '43016', '43016', '43009.5', '43010.5', '76617', '1.78137622'], ['1705219320000', '43022', '43026.5', '43015.5', '43016', '236', '0.00548595'], ['1705219260000', '43027.5', '43027.5', '43010.5', '43022', '112', '0.00260372'], ['1705219200000', '42996', '43027.5', '42996', '43027.5', '184', '0.00427754']]}, 'retExtInfo': {}, 'time': 1705235646124}

가독성이 굉장히 불편하죠. pandas를 통해 위 데이터를 정렬해 봅시다.

 

우선 pandas를 import 해줍니다. 설치되어 있지 않으시다면 pip install pandas 혹은 conda install pandas 로 본인 환경에 설치해 줍니다.

위에서 호출한 session.get_kline 객체를 따로 저장해 준 뒤, results 에서 list 만 따로 뽑아 줍니다.

from pybit.unified_trading import HTTP
import pandas as pd

session = HTTP(testnet=True)
data_getKline = session.get_kline(
    category="linear",
    symbol="BTCUSDT",
    interval=1,
    start=1705219200000,
    end=1705222800000,
)

result = data_getKline['result']['list']

그러면 처음 예제를 그대로 실행시켰을때의 'list': [['~~~]] 부분만 추출됩니다. 이 series 들이 가지는 의미는 위에서 언급했듯이 시간, 시가, 고가, 저가, 종가, 거래량, 턴오버 순입니다. 따라서 아래와 같이 pandas를 이용하여 data frame 객체로 생성해 줍니다.

df = pd.DataFrame(result, columns=['Date','Open', 'High', 'Low', 'Close','Volume','turnover'])

이대로 출력하면 아래와 같은 결과가 나옵니다. 

가독성이 좋아지긴 했습니다만, Date 도 UTC 의 ms 단위라 한눈에 들어오진 않고 우리가 사용하려면 좀 더 손봐야 할것들이 있습니다.

다시한번 리턴 파라미터들을 보시면 출력 데이터타입들이 string 인것을 알 수 있습니다. 데이터를 활용하기 위해서는 실수형으로 바꾸어줄 필요가 있습니다. 이를 위해 astype 이라는 함수를 사용해 줍니다.

df = df.astype(float)

또한 위 출력에서는 0~60 의 인덱스에 7개의 column 이 있는데요, 시계열로 데이터 처리를 하기 위해서는 인덱스를 datetime 으로 설정해 줄 필요가 있습니다. 위 출력에서 나온 Data 열의 series를 datetime 타입으로 바꾸면서 인덱스로 설정해 주겠습니다.

ts = pd.to_datetime(df['Date'], unit='ms')
df.set_index(ts, inplace=True)

Date 열의 수들은 유닉스 시간으로 환산된 ms단위의 시간인데요, 아래 링크에서 변환할 수 있습니다. pd.to_datetime 은 UTC를 년도/시/분 으로 바꾼 뒤 datetime 타입으로 바꿔줍니다.

https://www.unixtimestamp.com/index.php

 

Unix Time Stamp - Epoch Converter

Epoch and unix timestamp converter for developers. Date and time function syntax reference for various programming languages.

www.unixtimestamp.com

Date는 index로 빠졌으니 Date 열을 제외하고 dataframe 을 다시 구성해 줍니다. 또 리턴 파라미터 페이지 설명과 이전 출력을 잘 보시면 'sort in reverse by starttime' 이라고 나와있으며 출력 역시 시간 내림차순으로 정렬되어 있습니다. 편하실대로 해도 좋지만 저는 오름차순이 편하기 때문에 sort_index 함수를 이용하여 다시 정렬해 주었습니다.

df = df[['Open', 'High', 'Low', 'Close','Volume','turnover']]
df = df.sort_index()

여기까지 작업 후 실행해보면 아래와 같이 출력이 나옵니다. data type 도 확인하기 위해서 dtypes 를 이용해 데이터 타입도 출력해 봅니다.

 

2024년 1월 14일 오전 8시부터 9시까지의 BTCUSD 가격을 조회하였습니다. 데이터 타입도 float64로 변환된 것을 볼수 있습니다.

 

제대로 불러와진것 처럼 보이지만 그래도 가독성 좋게 그래프로 확인해보기 위해 캔들 그래프를 그리는 mplfinance 라는 라이브러리를 사용하였습니다. 공식 홈페이지와 설치법은 아래와 같습니다.

https://github.com/matplotlib/mplfinance

 

GitHub - matplotlib/mplfinance: Financial Markets Data Visualization using Matplotlib

Financial Markets Data Visualization using Matplotlib - GitHub - matplotlib/mplfinance: Financial Markets Data Visualization using Matplotlib

github.com

pip install --upgrade mplfinance

 

mplfinance로 plot을 그릴려면 아래와 같은 조건이 필요합니다.

  • dataframe 형태의 변수일 것
  • datatime type으로 index가 설정되어 있을 것
  • Open, High, Low, Close 이름의 column 이 있을 것 (거래량 차트 옵션을 위해서는 Volume 열도 필요)

index 의 데이터타입은 type(df.index) 로 확인할 수 있습니다. column 이름은 대소문자를 구분하니 주의해 주시길 바랍니다.

 

mplfinance 라이브러리를 import 해주고, dataframe 변수를 plot 함수로 그려주면 됩니다.

mplfinance 라이브러리 설명을 살펴보면 여러 옵션이 있는데요, 흔히 우리가 사용하는 캔들차트를 그리기 위해 type 옵션을 candle로 설정해 주고, 거래량과 함께 보기 위해 volume 을 true로 설정해 줍니다. 차트 스타일도 여러가지가 있는데요, 바이낸스 스타일이 있길래 해당 옵션으로 선택해봤습니다.

import mplfinance as mpf
...
mpf.plot(df, type='candle', style='binance',volume=True)

아래와 같이 그려집니다. 실제 차트와 같은지 해당 시간대를 바이비트 홈페이지에서 조회하여 비교해 봅니다.

위: mpl.plot 결과 / 아래: 바이비트 홈페이지 캡쳐 (BTC USDT, testnet)

 

거의 비슷한 그래프 입니다만... 완벽하게 같지는 않네요. 특히나 volume이 조금 다른 값을 보이는데요, 왜그런지 이유를 계속 찾아봤는데 session 을 테스트넷으로 열어서 그랬던것 같습니다. 테스트넷은 모의투자를 위한 것인데요, 발급한 제 api 정보를 입력하여 다시 띄워보았더니 아래와 같이 일치하는 그래프가 나왔습니다.

위: mpl.plot 결과 / 아래: 바이비트 홈페이지 캡쳐 (BTC USDT)

 

가격 예측에 가장 중요한 feature는 과거 데이터이기 때문에 꼼꼼하게 살펴보았습니다. 모델 개발을 위해서 feature 구성과 모델 구성을 어떻게 해야할지 좀 더 고민해 봐야겠네요. 최근 pybit 라이브러리가 V5 로 업데이트 되면서 함수 사용법이 조금씩 달라진 것으로 보입니다. 본 포스팅이 도움이 되었으면 좋겠네요. 다음부턴 본격적으로 모델 개발을 해 볼 예정입니다.