Programming for trading

[Python] 바이낸스API로 비트코인 1분봉 가져오기

quantoasis 2023. 1. 19. 10:20
반응형

오늘은 binance api로 비트코인 1분봉을 가져오는 코드를 작성하려고 합니다.

코드들은 여러 블로그 글들을 참고했는데, 레퍼런스를 못남겼네요 ㅠㅠ

import된 패키지들입니다. 우선 api요청을 위한 requests 모듈이 보이고, time관련 패키지와 pandas가 보이네요.

concurrent.futures라는 모듈도 import했는데, 이건 chatGPT가 멀티프로세싱을 제안하며 추가해주는 것입니다.

요새 코딩할때 chatGPT에게 최종 코드점검을 맡기는데 여러분도 꼭 이용해보시기바랍니다.

import requests
from datetime import timedelta
import pandas as pd
import datetime  as dt
from datetime import datetime
import concurrent.futures
import time


아래는 upbit와 binance의 코드를 반환해주는 함수입니다. BTC와 binance를 넣으면 BTCUSDT를 반환합니다. BTC upbit을 넣으면 KRW-BTC를 반환하죠.

def ticker_listmapping(ticker, exchange):
    if exchange == 'upbit':
        result = "KRW-" + ticker
    elif exchange == 'binance':
        result= ticker + 'USDT'
    return result



다음은 바이낸스로 데이터를 요청하는 함수입니다. 'https://api.binance.com/api/v3/klines' 에 데이터를 request하는데, params안에 요청할 데이터를 넣어주면 됩니다. 이 경우엔 interval에 '1m'을 넣어 1분봉을 가져왔습니다.


코드 중간에 retries를 이용한 에러처리와, ThreadPoolExecutor를 이용한 멀티프로세싱은 chatGPT가 처리해주었습니다.

아래 코드를 실행하면 시고저종, 거래량 등 데이터들을 받을 수 있습니다.

저는 날짜/시간 에서 Datettime형식보다는 date 와 time을 각각 int형식으로 나누는 것을 선호하기 때문에 각각 컬럼을 나눠주었습니다.

그리고 마지막에는 duplicates를 통해 중복을 제거해주어 혹시나 있을 오류를 방지하였습니다.

def binance_get_data(start_date, end_date, symbol):

    COLUMNS = ['Open_time', 'Open', 'High', 'Low', 'Close', 'Volume', 'Close_time', 'quote_av', 'trades',
               'tb_base_av', 'tb_quote_av', 'ignore']
    URL = 'https://api.binance.com/api/v3/klines'
    data = []
    start = int(time.mktime(datetime.strptime(start_date + ' 00:00', '%Y-%m-%d %H:%M').timetuple())) * 1000
    end = int(time.mktime(datetime.strptime(end_date + ' 23:59', '%Y-%m-%d %H:%M').timetuple())) * 1000
    params = {
        'symbol': symbol,
        'interval': '1m',
        'limit': 1000,
        'startTime': start,
        'endTime': end
    }
    retries = 3
    while start < end:
        params['startTime'] = start
        while retries>0:
            try:
                with concurrent.futures.ThreadPoolExecutor() as executor:
                    result = executor.submit(requests.get, URL, params=params)
                js = result.result().json()
                if not js:
                    break
                data.extend(js)  # result에 저장
                start = js[-1][0] + 60000  # 다음 step으로
                time.sleep(1)
                break
            except Exception as e:
                print(f'Attempt {retries} failed: {e}')
                retries-=1
                time.sleep(60)
        if retries==0:
            raise Exception('API call failed after 3 attempts')

    df = pd.DataFrame(data)
    df.columns = COLUMNS
    df['symbol'] = symbol
    df['Open_time'] = df.apply(lambda x: datetime.fromtimestamp(x['Open_time'] // 1000), axis=1)
    df = df.drop(columns=['Close_time', 'ignore'])
    df.loc[:, 'Open':'tb_quote_av'] = df.loc[:, 'Open':'tb_quote_av'].astype(float)  # string to float
    df['trades'] = df['trades'].astype(int)
    df['logdate'] = df['Open_time'].apply(lambda x: x.strftime('%Y%m%d'))
    df['logtime'] = df['Open_time'].apply(lambda x: x.strftime('%H%M%S')).astype(int)/100
    df = df[['logdate', 'logtime', 'symbol', 'Open', 'High', 'Low', 'Close', 'Volume', 'quote_av', 'trades', 'tb_base_av', 'tb_quote_av']]
    df = df.drop_duplicates(['logdate', 'logtime', 'symbol'], keep='first')


    print(symbol, ' / binance 완료')
    return df


이제 코드를 실행해보면 됩니다. start_date와 end_date에 날짜를 넣고, tickerlist에 다운받을 ticker를 넣으면 반복문을 돌면서 해당 날짜의 1분봉을 가져오게됩니다.

df_bi=pd.DataFrame()
tickerlist = ['BTC','ETH']


start_date = '2023-01-16'
end_date = '2023-01-19'

print('다운로드시작 ',start_date,'to',end_date)

for ticker in tickerlist:
    symbol_bi =ticker_listmapping(ticker,'binance')
    df_bi_temp = binance_get_data(start_date, end_date, symbol_bi)
    df_bi = pd.concat([df_bi,df_bi_temp])
    time.sleep(1)
    
print(df_bi)


감사합니다.

반응형