본문 바로가기
파이썬/가상화폐

Python Upbit Websocket 업비트 비트코인 실시간 체결가격 데이터 조회하는 방법

by 행복론자 2022. 10. 28.

 

요청을 주고 받는 API가 아니라 Websocket을 이용한 실시간 데이터 처리가 필요한 경우가 더러 있습니다.

오늘은 시시각각 변하는 코인의 가격데이터를 확인하는 방법을 알아보겠습니다.

 

대상 거래소는 업비트이며 사용 언어는 파이썬입니다.

먼저 전종목코드를 얻어오는 함수를 만들어보겠습니다.

# encoding: utf-8
import pyupbit
import uuid
import json
import asyncio
import websockets
import traceback


def get_all_ticker():
    """
    데이터 수신할 TICKER 목록
    """
    krw_ticker = pyupbit.get_tickers(fiat="KRW")
    return krw_ticker

 

 

다음으로 실행해보면 전체 종목목록이 리스트로 나옵니다. 

if __name__ == "__main__":   
    print(get_all_ticker())
    
 # ['KRW-BTC', 'KRW-ETH', 'KRW-NEO', 'KRW-MTL', 'KRW-XRP', 'KRW-ETC', 'KRW-OMG', 'KRW-SNT', 'KRW-WAVES', 'KRW-XEM', 'KRW-QTUM', 'KRW-LSK', 'KRW-STEEM', 'KRW-XLM', 'KRW-ARDR', 'KRW-ARK', 'KRW-STORJ', 'KRW-GRS', 'KRW-REP', 'KRW-ADA', 'KRW-SBD', 'KRW-POWR', 'KRW-BTG', 'KRW-ICX', 'KRW-EOS', 'KRW-TRX', 'KRW-SC', 'KRW-ONT', 'KRW-ZIL', 'KRW-POLY', 'KRW-ZRX', 'KRW-LOOM', 'KRW-BCH', 'KRW-BAT', 'KRW-IOST', 'KRW-RFR', 'KRW-CVC', 'KRW-IQ', 'KRW-IOTA', 'KRW-MFT', 'KRW-ONG', 'KRW-GAS', 'KRW-UPP', 'KRW-ELF', 'KRW-KNC', 'KRW-BSV', 'KRW-THETA', 'KRW-QKC', 'KRW-BTT', 'KRW-MOC', 'KRW-ENJ', 'KRW-TFUEL', 'KRW-MANA', 'KRW-ANKR', 'KRW-AERGO', 'KRW-ATOM', 'KRW-TT', 'KRW-CRE', 'KRW-MBL', 'KRW-WAXP', 'KRW-HBAR', 'KRW-MED', 'KRW-MLK', 'KRW-STPT', 'KRW-ORBS', 'KRW-VET', 'KRW-CHZ', 'KRW-STMX', 'KRW-DKA', 'KRW-HIVE', 'KRW-KAVA', 'KRW-AHT', 'KRW-LINK', 'KRW-XTZ', 'KRW-BORA', 'KRW-JST', 'KRW-CRO', 'KRW-TON', 'KRW-SXP', 'KRW-HUNT', 'KRW-PLA', 'KRW-DOT', 'KRW-SRM', 'KRW-MVL', 'KRW-STRAX', 'KRW-AQT', 'KRW-GLM', 'KRW-SSX', 'KRW-META', 'KRW-FCT2', 'KRW-CBK', 'KRW-SAND', 'KRW-HUM', 'KRW-DOGE', 'KRW-STRK', 'KRW-PUNDIX', 'KRW-FLOW', 'KRW-DAWN', 'KRW-AXS', 'KRW-STX', 'KRW-XEC', 'KRW-SOL', 'KRW-MATIC', 'KRW-NU', 'KRW-AAVE', 'KRW-1INCH', 'KRW-ALGO', 'KRW-NEAR', 'KRW-WEMIX', 'KRW-AVAX', 'KRW-T', 'KRW-CELO', 'KRW-GMT', 'KRW-APT']

 

 

 

이상태에서 Websocket 을 사용하는 코드는 다음과 같습니다.

async def connect_socket():
    """
    UPBIT 소켓연결(샘플)
    :return: None
    """
    while True:
        try:
            async with websockets.connect('wss://api.upbit.com/websocket/v1', ping_interval=None, ping_timeout=30, max_queue=10000) as websocket:
                subscribe_fmt = [
                    {'ticket':  str(uuid.uuid4())[:6]},
                    {
                        'type': 'ticker',
                        'codes': get_all_ticker(),
                        'isOnlyRealtime': True
                    },
                ]
                subscribe_data = json.dumps(subscribe_fmt)
                await websocket.send(subscribe_data)

                while True:
                    try:
                        data = await websocket.recv()
                        data = json.loads(data)

                        if 'code' not in data:  # 응답 데이터(딕셔너리)에 code가 없는 경우 제외
                            print("[Data error]", data)
                            continue

                        # base_ticker = data['code'].split('-')[0]  # KRW-BTC > KRW(기준통화)
                        ticker = data['code'].split('-')[1]  # KRW-BTC > BTC(시세조회대상 코인)

                        print(ticker, data)  # 결과출력 테스트(주석)

                    except (asyncio.TimeoutError, websockets.exceptions.ConnectionClosed):
                        try:
                            pong = await websocket.ping()
                            await asyncio.wait_for(pong, timeout=30)
                        except:
                            await asyncio.sleep(30)
                            break
                    except:
                        traceback.print_exc()
        except:
            await asyncio.sleep(30)

 

 

connect_socket 함수를 보면 while문을 이용해 무한루프를 만들었습니다. 혹시 Websocket의 연결이 끊어지더라도 다시 재연결하도록 만들기 위해서입니다.

upbit의 Websocket server 주소는 다음과 같습니다. 

wss://api.upbit.com/websocket/v1

 

with 구문을 이용해 연결한 websocket에 구독할 데이터 포멧(subscribe_fmt)을 전달합니다.

subscribe_fmt = [
    {'ticket':  str(uuid.uuid4())[:6]},
    {
        'type': 'ticker',
        'codes': get_all_ticker(),
        'isOnlyRealtime': True
    },
]
subscribe_data = json.dumps(subscribe_fmt)
await websocket.send(subscribe_data)

 

 

해외거래소를 사용하면 하나의 정보당 한번씩 요청해야해서 websocket.send를 여러번해야할 때도 있지만 upbit는 한번에 끝나서 편합니다. codes 필드에는 get_all_ticker 함수의 결과를 전달합니다. 

이후부터는 다시 무한루프 while문을 이용해 계속 데이터를 수신(websocket.recv)합니다. 

while True:
    try:
        data = await websocket.recv()
        data = json.loads(data)

        if 'code' not in data:  # 응답 데이터(딕셔너리)에 code가 없는 경우 제외
            print("[Data error]", data)
            continue

        # base_ticker = data['code'].split('-')[0]  # KRW-BTC > KRW(기준통화)
        ticker = data['code'].split('-')[1]  # KRW-BTC > BTC(시세조회대상 코인)

        print(ticker, data)  # 결과출력 테스트(주석)

    except (asyncio.TimeoutError, websockets.exceptions.ConnectionClosed):
        try:
            pong = await websocket.ping()
            await asyncio.wait_for(pong, timeout=30)
        except:
            await asyncio.sleep(30)
            break
    except:
        traceback.print_exc()

 

try-except를 사용해 에러가 나더라도 잠시 대기 후 재연결하도록 되어있습니다.

마지막으로 run 함수를 이용해 create_task를 만들고 run해줍니다. 

async def run():
    """
    :return:
    """
    await asyncio.wait([
        asyncio.create_task(connect_socket()),
    ])


if __name__ == "__main__":
    asyncio.run(run())    

 

그 결과는 다음과 같습니다.

 

결과를 보면 다음과 같습니다.

앞에 ticker는 제가 출력한 것이고 뒤에 딕셔너리가 Websocket을 이용해 수신한 데이터의 원본(?)입니다.

WEMIX {'type': 'ticker', 'code': 'KRW-WEMIX', 'opening_price': 2545, 'high_price': 2630, 'low_price': 1870, 'trade_price': 1895, 'prev_closing_price': 2545.0, 'acc_trade_price': 179061621306.1007, 'change': 'FALL', 'change_price': 650.0, 'signed_change_price': -650.0, 'change_rate': 0.2554027505, 'signed_change_rate': -0.2554027505, 'ask_bid': 'ASK', 'trade_volume': 518.13471502, 'acc_trade_volume': 79932981.81375916, 'trade_date': '20221027', 'trade_time': '160539', 'trade_timestamp': 1666886739097, 'acc_ask_volume': 49742376.32154966, 'acc_bid_volume': 30190605.49220951, 'highest_52_week_price': 13490.0, 'highest_52_week_date': '2022-01-11', 'lowest_52_week_price': 1865.0, 'lowest_52_week_date': '2022-05-12', 'market_state': 'ACTIVE', 'is_trading_suspended': False, 'delisting_date': None, 'market_warning': 'CAUTION', 'timestamp': 1666886739154, 'acc_trade_price_24h': 181321633451.3138, 'acc_trade_volume_24h': 80807551.9126393, 'stream_type': 'REALTIME'}

 


같이 읽어보면 좋은 글

2022.12.27 - [파이썬/가상화폐] - [전자책] 바이낸스 코인선물자동매매 시스템 개발 방법을 담은 책이 출시되었습니다.

 

[전자책] 바이낸스 코인선물자동매매 시스템 개발 방법을 담은 책이 출시되었습니다.

🎁 바이낸스 자동매매 시스템 개발 방법을 담은 책이 출시되었습니다. "나 대신 일해주는 코인선물자동매매 프로그램 개발, 노하우 및 소스를 모두 공개합니다" ✔️ Q: 무슨 내용인가요? Python

jsp-dev.tistory.com

 

2022.11.05 - [파이썬/가상화폐] - [공지] 코인거래소별 프리미엄 체크봇 개발 가이드와 풀소스 전자책 | binance bybit | 업비트 김치프리미엄

 

[공지] 코인거래소별 프리미엄 체크봇 개발 가이드와 풀소스 전자책 | binance bybit | 업비트 김치프

https://kmong.com/gig/417785 거래소별 코인 프리미엄 알림봇 개발 가이드를 드립니다 | 36000원부터 시작 가능한 총 평점 5점의 3개 총 작업 개수 완료한 총 평점 5점인 JSDEV의 전자책, 투잡·재테크 전자

jsp-dev.tistory.com

 

2022.07.26 - [파이썬/가상화폐] - Python Binance Websocket 비트코인 실시간 데이터 조회

 

Python Binance Websocket 비트코인 실시간 데이터 조회

Kiwoom API나 pyupbit를 이용한 주식, 코인 데이터를 받아오는 과정은 '클라이언트의 요청 > 서버의 응답 > 데이터 수신'이라는 일련의 단계를 거쳤습니다. 이런 요청은 1일, 4시간, 1시간 캔들 데이터

jsp-dev.tistory.com

 

반응형
이 포스팅은 쿠팡파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

댓글