본문 바로가기

코인/코인 개발

바이낸스(Binance) 웹소켓(WebSocket)+파이썬(Python)으로 실시간 데이터 수신하기

이전 포스팅에서는 업비트 웹소켓을 사용해 실시간 차트 데이터를 얻는 방법을 설명했었습니다.

2021.08.03 - [코인/코인 개발] - 업비트(Upbit) 웹소켓(WebSocket)+파이썬(Python)으로 실시간 데이터 수신하기

 

업비트(Upbit) 웹소켓(WebSocket)+파이썬(Python)으로 실시간 데이터 수신하기

이전 포스팅에서는 업비트 API를 사용해 차트 데이터를 얻는 방법을 설명했었습니다. 2021.07.07 - [코인/코인 개발] - 업비트 API를 이용한 코인 거래량 급등 알리미 프로그램 업비트 API를 이용한 코

blog.coinali.me

 

이번 포스팅에서는 마찬가지로 파이썬으로 바이낸스 실시간 시세를 확인하는 방법을 알아보겠습니다. 동일한 부분은 설명을 생략하도록 하겠습니다.


먼저 다른 점은 첫째로 바이낸스 웹소켓은 URL로 직접 Subscribe 할 수 있어, 데이터 수신 요청 메시지를 미리 보내지 않아도 됩니다. 둘째로는 좀 더 세분화된 요청이 존재합니다. 이번 포스팅에서는 제공하는 모든 종류의 요청에 대해 다루지는 않을 것이므로, 자세한 사항은 바이낸스 문서를 확인해주시기 바랍니다.

 

이전 포스팅과 마찬가지로 USDT 마켓에서의 비트코인과 이더리움에 대한 차트 데이터를 수신하는 예제를 작성하겠습니다.

 

먼저 바이낸스 웹소켓에서 제공하는 데이터 형식 중 OHLCV(Open, High, Low, Close, Volume)만 다음과 같이 가져올 수 있도록 했습니다. 타임존은 Asia/Seoul을 사용했습니다.

class Ticker:

    def __init__(self, code, timestamp, open, high, low, close, volume):
        self.code = code
        self.timestamp = timestamp
        self.open = open
        self.high = high
        self.low = low
        self.close = close
        self.volume = volume

    @staticmethod
    def from_json(json):
        return Ticker(
            code=json['s'],
            timestamp=datetime.fromtimestamp(json['k']['t'] / 1000, tz=pytz.timezone('Asia/Seoul')),
            open=json['k']['o'],
            high=json['k']['h'],
            low=json['k']['l'],
            close=json['k']['c'],
            volume=json['k']['v']
        )

    def __repr__(self):
        return self.__str__()

    def __str__(self):
        return f'Ticker <code: {self.code}, timestamp: {self.timestamp.strftime("%Y-%m-%d %H:%M:%S")}, ' \
               f'open: {self.open}, high: {self.high}, ' \
               f'low: {self.low}, close: {self.close}, volume: {self.volume}>'

 

 

바이낸스 웹소켓 연결 및 데이터 수신은 다음과 같습니다.

 

async def recv_ticker():
    uri = 'wss://stream.binance.com:9443'
    markets = ['BTCUSDT', 'ETHUSDT']
    stream = 'kline_1m'

    params = '/'.join([f'{market.lower()}@{stream}' for market in markets])
    uri = uri + f'/stream?streams={params}'

    ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
    self_signed_cert = pathlib.Path(__file__).with_name("selfsigned.crt")
    ssl_context.load_verify_locations(self_signed_cert)

    async with websockets.connect(uri, ssl=ssl_context) as websocket:
        var = asyncio.Event()

        def sigint_handler(var, signal, frame):
            print(f'< recv SIG_INT')
            var.set()

        signal.signal(signal.SIGINT, partial(sigint_handler, var))

        while not var.is_set():
            recv_data = await websocket.recv()
            res = Ticker.from_json(json.loads(recv_data)['data'])
            print(f"> {res}")


asyncio.get_event_loop().run_until_complete(recv_ticker())

 

먼저 URI는 제공받고자 하는 stream 개수가 2개 이상인 경우 위 예제에서와 같이 조합해서 보낼 수 있습니다. 이 경우에는

wss://stream.binance.com:9443/stream?streams=btcusdt@kline_1m/ethusdt@kline_1m

가 되는데, 각각 BTC-USDT 마켓과 ETH-USDT 마켓의 1분 봉 데이터를 수신받게 됩니다. SSLContext를 구성하는 부분은 이전 포스팅을 참고 바랍니다.

 

SIG_INT 시그널을 받을 때까지 지속적으로 데이터를 수신하는데, 수행 결과는 다음과 같습니다.

 

> Ticker <code: BTCUSDT, timestamp: 2021-08-04 06:36:00, open: 38350.10000000, high: 38350.10000000, low: 38290.35000000, close: 38290.35000000, volume: 12.73687800>
> Ticker <code: ETHUSDT, timestamp: 2021-08-04 06:36:00, open: 2483.66000000, high: 2483.67000000, low: 2479.32000000, close: 2479.42000000, volume: 402.91851000>
> Ticker <code: BTCUSDT, timestamp: 2021-08-04 06:36:00, open: 38350.10000000, high: 38350.10000000, low: 38284.17000000, close: 38287.32000000, volume: 13.32572100>
> Ticker <code: ETHUSDT, timestamp: 2021-08-04 06:36:00, open: 2483.66000000, high: 2483.67000000, low: 2478.73000000, close: 2478.73000000, volume: 413.19828000>
> Ticker <code: ETHUSDT, timestamp: 2021-08-04 06:36:00, open: 2483.66000000, high: 2483.67000000, low: 2478.71000000, close: 2478.82000000, volume: 420.42267000>
> Ticker <code: BTCUSDT, timestamp: 2021-08-04 06:36:00, open: 38350.10000000, high: 38350.10000000, low: 38280.58000000, close: 38282.27000000, volume: 15.27412700>
> Ticker <code: ETHUSDT, timestamp: 2021-08-04 06:36:00, open: 2483.66000000, high: 2483.67000000, low: 2478.02000000, close: 2478.22000000, volume: 427.23472000>
> Ticker <code: BTCUSDT, timestamp: 2021-08-04 06:36:00, open: 38350.10000000, high: 38350.10000000, low: 38276.52000000, close: 38276.54000000, volume: 15.79027700>
< recv SIG_INT
> Ticker <code: ETHUSDT, timestamp: 2021-08-04 06:36:00, open: 2483.66000000, high: 2483.67000000, low: 2478.02000000, close: 2478.65000000, volume: 451.08423000>

Process finished with exit code 0

 

궁금한 점은 댓글 남겨주세요.