규도자 개발 블로그

파이썬으로 여러 개의 웹소켓에 동시에 연결하기 본문

Python/Python

파이썬으로 여러 개의 웹소켓에 동시에 연결하기

규도자 (gyudoza) 2021. 4. 20. 16:06

파이썬으로 여러 개의 웹소켓에 동시에 연결하기

토이프로젝트로 퀀트 프로그램을 하나 제작하고 있는데 맨 처음에는 각종 거래소에서 제공하는 api를 사용할까 하다가 초당 요청제한이라는 문턱에 걸렸다. 수학모델에 근거해서 전략의 타당성을 검토해야 하는데 수백종류의 암호화폐 데이터를 1초에 한번씩 api로 요청해 저장하려고 하니 터무니 없는 생각이긴 했다. 그렇다고 1분을 쪼개서 요청을 보내자니 엄청난 변동성의 암호화폐시장에서의 수학모델 분석에는 적절하지 않다는 생각이 들었다. 그래서 웹소켓을 찾아보니 다행스럽게도 거의 모든 거래소에서 웹소켓을 지원하고 있더라.
 만약에 다양한 플랫폼, 혹은 한 플랫폼에서도 다른 웹소켓 라우트에서 필요한 정보가 있으면 여러개의 웹소켓에 연결할 필요가 있다. 그럴 때 사용하기 좋은 코드이다.

import asyncio
import websockets
import json


async def upbit_ws_client(callback):
    uri = 'wss://api.upbit.com/websocket/v1'
    async with websockets.connect(uri) as websocket:
        subscribe_fmt = [
            {'ticket': 'test'},
            {
                'type': 'ticker',
                'codes': ['KRW-BTC'],
                'isOnlyRealtime': True
            },
            {'format': 'SIMPLE'}
        ]
        subscribe_data = json.dumps(subscribe_fmt)
        await websocket.send(subscribe_data)

        while True:
            print('111111111')
            await callback(await websocket.recv())


async def upbit_ws_client2(callback):
    uri = 'wss://api.upbit.com/websocket/v1'
    async with websockets.connect(uri) as websocket:
        subscribe_fmt = [
            {'ticket': 'test'},
            {
                'type': 'ticker',
                'codes': ['KRW-XRP'],
                'isOnlyRealtime': True
            },
            {'format': 'SIMPLE'}
        ]
        subscribe_data = json.dumps(subscribe_fmt)
        await websocket.send(subscribe_data)

        while True:
            print('2222222222')
            await callback(await websocket.recv())


async def response_message(*args, **kwargs):
    print(args)


if __name__ == '__main__':
    tasks = [
        asyncio.ensure_future(upbit_ws_client(response_message)),
        asyncio.ensure_future(upbit_ws_client2(response_message))
    ]
    asyncio.get_event_loop().run_until_complete(asyncio.wait(tasks))

이런식으로 구성하면 된다. 저 주소와 웹소켓으로 보내는 params만 조정하면 원하는 대로 쓸 수 있을 것이다. 사실 업비트에서 저 두 상품의 정보를 받아오는 데에는 그냥 한 개의 함수에 두 개의 params만 추가하면 된다.

 

async def upbit_ws_client2(callback):
    uri = 'wss://api.upbit.com/websocket/v1'
    async with websockets.connect(uri) as websocket:
        subscribe_fmt = [
            {'ticket': 'test'},
            {
                'type': 'ticker',
                'codes': ['KRW-XRP'],
                'isOnlyRealtime': True
            },
            {
                'type': 'ticker',
                'codes': ['KRW-BTC'],
                'isOnlyRealtime': True
            },
            {'format': 'SIMPLE'}
        ]
        subscribe_data = json.dumps(subscribe_fmt)
        await websocket.send(subscribe_data)

        while True:
            print('2222222222')
            await callback(await websocket.recv())

이런식으로 말이다. 하지만 코드를 보는 사람의 이해 + 전략노출을 방지하기 위해 이렇게 예제를 구성했다. 콜백함수가 실행되는 곳의 구분을 위해서도 print함수를 작성했다.

 맨 위에 있는 함수를 그대로 복사해다가 붙여넣기하고 실행해보면 잘 작동되는 코드를 확인할 수 있을 것이다. (패키지 인스톨은 필수)

 

이 사진이 맨 위에 있는 함수를 실행한 모습이다. 각 웹소켓이 11111과 22222로 구분되어 콜백함수가 잘 실행되는 모습을 확인해볼 수 있다.

 

Comments