이전 포스팅에서는 업비트 API를 사용해 차트 데이터를 얻는 방법을 설명했었습니다.
2021.07.07 - [코인/코인 개발] - 업비트 API를 이용한 코인 거래량 급등 알리미 프로그램
해당 API는 REST API로, 만약 실시간으로 변경되는 시세를 확인하기 위해선 주기적인 호출(Polling)이 필요하게 되고 이는 서버에 과부하를 줄 수 있어 업비트에서는 요청 제한을 걸어두고 있습니다.
2021.07.09 - [코인/코인 개발] - 업비트(Upbit) API를 이용해 프로그램 개발 시 주의 사항
때문에 실시간 시세를 확인하기 위해서는 웹소켓(Websocket)을 이용하는 것이 바람직한데, 이번 포스팅에서는 파이썬으로 업비트 실시간 시세를 확인하는 방법을 알아보겠습니다.
* 코드는 Python 3.8에서 테스트되었습니다.
먼저 websockets 라이브러리를 설치합니다.
pip install websockets
업비트 웹소켓 연결이 보안 연결을 필요로 하는데, 요청 측에서는 자기 서명 인증서(Self-Signed Certificate)를 사용할 수 있습니다. 인증서는 openssl을 사용해 다음과 같이 간단히 발급할 수 있습니다.
$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout selfsigned.key -out selfsigned.crt
Generating a RSA private key
........................+++++
.................................................+++++
writing new private key to 'selfsigned.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:KR
State or Province Name (full name) [Some-State]:Seoul
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:coinali.me
Email Address []:
$
먼저 업비트 웹소켓에서 제공하는 데이터 형식 중 OHLCV(Open, High, Low, Close, Volume)만 다음과 같이 가져올 수 있도록 했습니다. 보다 자세한 데이터 제공 사항은 업비트 문서에서 확인하실 수 있습니다.
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['code'],
timestamp=datetime.fromtimestamp(json['trade_timestamp'] / 1000, tz=pytz.timezone('Asia/Seoul')),
open=json['opening_price'],
high=json['high_price'],
low=json['low_price'],
close=json['trade_price'],
volume=json['acc_trade_price']
)
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}>'
업비트 웹소켓 연결, 요청 및 데이터 수신은 다음과 같습니다. 예제에서는 원화 마켓에서 비트코인(KRW-BTC)과 이더리움(KRW-ETH) 데이터를 수신하는 요청을 보냅니다.
import asyncio
import json
import pathlib
import signal
import ssl
import uuid
from datetime import datetime
from functools import partial
import pytz
import websockets
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 def recv_ticker():
uri = 'wss://api.upbit.com/websocket/v1'
markets = ['KRW-BTC', 'KRW-ETH']
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))
req = [{
'ticket': str(uuid.uuid4()),
}, {
'type': 'ticker',
'codes': markets
}]
print(f"> {req}")
await websocket.send(json.dumps(req))
while not var.is_set():
recv_data = await websocket.recv()
res = Ticker.from_json(json.loads(recv_data))
print(f"> {res}")
asyncio.get_event_loop().run_until_complete(recv_ticker())
요청 정보는 다음과 같습니다.
- 연결 URI: wss://api.upbit.com/websocket/v1
- 데이터 요청:
- ticket: 업비트에서 사용하는 요청 식별 값
- type: 수신할 시세 타입 ('ticker': 현재가, 'trade': 체결, 'orderbook': 호가)
- codes: 수신할 시세 종목 정보 (예: KRW-BTC)
또한, SIG_INT 시그널을 받을 때까지 지속적으로 데이터를 수신합니다. 수행 결과는 다음과 같습니다.
> [{'ticket': '5b50a885-c703-4b97-ad26-e9359163bf4e'}, {'type': 'ticker', 'codes': ['KRW-BTC', 'KRW-ETH']}]
> Ticker <code: KRW-BTC, timestamp: 2021-08-03 22:53:31, open: 45451000.0, high: 46150000.0, low: 44440000.0, close: 45145000.0, volume: 252967719495.32422>
> Ticker <code: KRW-ETH, timestamp: 2021-08-03 22:53:29, open: 3024000.0, high: 3057000.0, low: 2865000.0, close: 2951000.0, volume: 255937299191.82175>
...
> Ticker <code: KRW-ETH, timestamp: 2021-08-03 22:53:55, open: 3024000.0, high: 3057000.0, low: 2865000.0, close: 2951000.0, volume: 256085728038.51974>
> Ticker <code: KRW-BTC, timestamp: 2021-08-03 22:53:55, open: 45451000.0, high: 46150000.0, low: 44440000.0, close: 45145000.0, volume: 253102651324.1243>
> Ticker <code: KRW-BTC, timestamp: 2021-08-03 22:53:56, open: 45451000.0, high: 46150000.0, low: 44440000.0, close: 45141000.0, volume: 253102656818.68683>
< recv SIG_INT
> Ticker <code: KRW-BTC, timestamp: 2021-08-03 22:53:56, open: 45451000.0, high: 46150000.0, low: 44440000.0, close: 45141000.0, volume: 253102836675.77878>
Process finished with exit code 0
궁금한 점은 댓글로 문의주세요.
'코인 > 코인 개발' 카테고리의 다른 글
김치 프리미엄(김프) 계산을 위한 다양한 실시간 무료 환율(Exchange) API (0) | 2021.08.05 |
---|---|
바이낸스(Binance) 웹소켓(WebSocket)+파이썬(Python)으로 실시간 데이터 수신하기 (2) | 2021.08.04 |
코인 거래량 급등 텔레그램(Telegram) 알림 봇 파이썬(Python)으로 만들기 (2) (22) | 2021.08.03 |
alert.coinali.me 업데이트: 업비트 RSI 및 출금 수수료 정보 추가 (0) | 2021.07.31 |
업비트 급등 알림 서비스, alert.coinali.me (0) | 2021.07.26 |