본문 바로가기
프로젝트/코인 자동매매

파이썬 코인 자동매매 봇 만들기#10 - 웹소켓을 사용하여 급등주를 찾아보자

by 큰공 2021. 10. 12.
728x90
반응형

들어가며

2021.08.19 - [IT/파이썬] - 파이썬 코인 자동매매 봇 만들기#1 - pybitumb 모듈 설치하기

2021.08.21 - [IT/파이썬] - 파이썬 코인 자동매매 봇 만들기#2 - 24시간 변동률 정렬하기

2021.08.24 - [IT/파이썬] - 파이썬 코인 자동매매 봇 만들기#3 - 급등주를 찾아라

2021.08.25 - [IT/파이썬] - 파이썬 코인 자동매매 봇 만들기#4 - 매수 / 매도 시뮬레이션

2021.08.30 - [IT/파이썬] - 파이썬 코인 자동매매 봇 만들기#5 - 시뮬레이션 첫 수익률은?

2021.09.05 - [IT/파이썬] - 파이썬 코인 자동매매 봇 만들기#6 - STOP LOSS 기능을 추가

2021.09.06 - [IT/파이썬] - 파이썬 코인 자동매매 봇 만들기#7 - NONE TYPE ERROR 수정

2021.09.08 - [IT/파이썬] - 파이썬 코인 자동매매 봇 만들기#8 - 빗썸 API 신청 및 잔고조회 하기

2021.09.10 - [IT/파이썬] - 파이썬 코인 자동매매 봇 만들기#9 - 매도 주문을 해보자

 

파이썬 코인 자동매매 봇 만들기#9 - 매도 주문을 해보자

들어가며 2021.08.19 - [IT/파이썬] - 파이썬 코인 자동매매 봇 만들기#1 - pybitumb 모듈 설치하기 2021.08.21 - [IT/파이썬] - 파이썬 코인 자동매매 봇 만들기#2 - 24시간 변동률 정렬하기 2021.08.24 - [IT/..

coinpipe.tistory.com

 이번 포스팅은 이전 글에 대해서 크게 이어지는 내용은 아니긴합니다만, 이전글을 못 보고 오신분들은 순차적으로 글을 보시고 오시는것을 추천드립니다.

 

 

목표

 지난번 포스팅에서는 빗썸 Private API 를 이용하여, 실질적으로 가지고 있는 종목에 대해서 매도 주문을 넣고 실질 적으로 매도하는거 까지 실습해보았습니다.

 

 지난번 포스팅에서 잠깐 언급드렸듯이, 이번에는 WebSocket API 를 사용하여 급등주를 찾는 로직을 구현해보도로고 하겠습니다.

 

WebSocket API vs REST API

 지난번 포스팅을 유의있게 보셨더라면, Private API와 Public API의 차이점은 다들 아시리라 생각됩니다. 이때까지 사용한 API는 REST API였는데요. WebSocket API를 알기전에 우선 "REST" 가 뭔지 알아보도록 하겠습니다.

 

 REST는 Representational State Transfer라는 용어의 약자로서 2000년도에 로이 필딩 (Roy Fielding)의 박사학위 논문에서 최초로 소개되었습니다. 로이 필딩은 HTTP의 주요 저자 중 한 사람으로 그 당시 웹(HTTP) 설계의 우수성에 비해 제대로 사용되어지지 못하는 모습에 안타까워하며 웹의 장점을 최대한 활용할 수 있는 아키텍처로써 REST를 발표했다고 합니다.
REST API는 HTTP 요청을 통해 통신함으로써 리소스 내에서 레코드(CRUD 라고도 함)의 작성, 읽기, 업데이트 및 삭제 등의 표준 데이터베이스 기능을 수행합니다. 예를 들어, REST API는 GET 요청을 사용하여 레코드를 검색하고, POST 요청을 사용하여 레코드를 작성하며, PUT 요청을 사용하여 레코드를 업데이트하고, DELETE 요청을 사용하여 레코드를 삭제합니다. 모든 HTTP 메소드는 API 호출에서 사용될 수 있습니다. 잘 디자인된 REST API는 HTTP 기능이 내장된 웹 브라우저에서 실행되는 웹 사이트와 유사합니다.

 

 역시나 인용하여 보는 정의 부분은 정확하게 바로 이해하기가 살짝 어렵습니다. REST API 의 핵심 구조는 "요청 -> 응답" 의 구조입니다. 즉, 내가 값을 달라고 요청할때만 현재의 그 값을 전달해주게 됩니다. 

 

 

REST API 의 한계

 REST API를 사용하게 되면, 요청한 시점에서 가격 조회가 이뤄지므로, 예를들어 5분 간격으로 현재 가격을 조회하고자 하는 REST 시스템에서, 12시에 현재가를 얻고, 12시 5분에 현재가를 얻으면, 이 종목의 가격이 0분 ~ 5분 동안 어떻게 변하였는지는 상관없이 5분의 가격만을 얻을 수 있습니다..

 

 또한, 12시 5분의 가격의 체결시점이 12시 1분이라면, 약 4분동안 가격이 안정되어있음에도 불구하고, 급등주를 판단하는 시점이 4분 늦게 됩니다.

 

 이러한 REST API의 한계점으로 인하여, 매우 빠른 시간에 매수/매도를 할 수 있어야 하는 자동매매 프로그램의 장점이 희석되게 됩니다.

출처 : https://wikidocs.net/115649

 

WebSocket API

 그럼 이제 WebSocket 이 뭔지를 살짝 알아보겠습니다.

웹소켓 프로토콜은 HTTP 풀링과 같은 반이중방식에 비해 더 낮은 부하를 사용하여 웹 브라우저 (또는 다른 클라이언트 애플리케이션)과 웹 서버간의 통신을 가능케 하며, 서버와의 실시간 데이터 전송을 용이케 한다. 이는 먼저 클라이언트에 의해 요청을 받는 방식이 아닌, 서버가 내용을 클라이언트에 보내는 표준화된 방식을 제공함으로써, 또 연결이 유지된 상태에서 메시지들을 오갈 수 있게 허용함으로써 가능하게 되었다. 이러한 방식으로 양방향 대화 방식은 클라이언트와 서버 간에 발생할 수 있다.

 WebSocket 의 핵심은 서버와의 실시간 데이터 전송을 가능케 한다는 점입니다. 하나의 종목이 체결이 딱 되면 체결이 되는 그 순간! 클라이언트 (자동매매봇) 으로 역으로 알려주는 기능을 수행합니다.

 

 즉, 특별히 그 시점에 요청하지 않아도, 애초에 나에게 알려줘~ 라고만 등록(구독 - Subscribe) 만 해두게 되면, 그 시점에 알아서 알려주도록 하는 API 입니다.

 

 

WebSocket 이용한 실시간 급등주 알림 코드

import websockets
import asyncio 
import json
import pybithumb
from pandas import DataFrame
from datetime import datetime

# 급상승/급하락 조건 변수
cycle_time = 120 # X초 동안
check_rate = 3 # 0.5% 상승하면 

# 함수
 # 이전가격 대비 상승률 함수
def diff ( prev_price, current_price ) :
    return round( ( float(current_price) - float(prev_price) ) / float(prev_price) * 100 , 3 )

 # X분 이전 가격
def prev_price ( ticker ) :
    return float ( df.at[ticker,'closing_price'] )

 # X분 이전 시간
def prev_time ( ticker ) :
    return df.at[ticker,'time']
    

#초기화
 # DataFrame 초기화
df = DataFrame([ ( 0, datetime.now(), 0 )], columns=['ticker_symbol', 'time', 'closing_price'])
df = df.drop(0)

 # 전체 Symbol 초기데이터 획득
all = pybithumb.get_current_price("ALL") 
ticker_symbol = []

 # DataFrame 베이스 Data 취득
for ticker, data in all.items():
    ticker_symbol.append(ticker+"_KRW")
    df = df.append( { 'ticker_symbol' :  ticker+"_KRW", 'time' : datetime.now().strftime('%Y%m%d%H%M%S'), 'closing_price' : data['closing_price'] }, ignore_index=True)    
df.set_index('ticker_symbol', inplace=True)


#실시간 급등주 찾기 - 전체 Symbol 에서 WebSocket 이용한 실시간 시세 이용
async def bithumb_ws_client():
    uri = "wss://pubwss.bithumb.com/pub/ws"
    
    async with websockets.connect(uri, ping_interval=None) as websocket:
        subscribe_fmt = {
            "type":"ticker", 
            "symbols": ticker_symbol,
            "tickTypes": ["1H"]
        }
        subscribe_data = json.dumps(subscribe_fmt)

        await websocket.send(subscribe_data)

        # 각 Ticker 에 대한 실시간 시세 변동 시 CallBack 
        while True:
            data = await websocket.recv()
            data = json.loads(data)
            if 'content' in data:
                ticker_data = data['content']['symbol'] # 종목
                closePrice_data = data['content']['closePrice'] # 종목의 현재가
                time_data = data['content']['date'] + data['content']['time'] # 종목이 변화한 시간
                
                diff_rate = diff ( prev_price(ticker_data), closePrice_data ) # 이전 가격과 현재 가격의 차이
                time_gap = int ( time_data ) - int ( prev_time(ticker_data) ) # 이전 시간과, 현재 시간의 간격

                # 급등주 출력 ( X 초 동안, Y % 상승한 경우 매수 체결 신호)
                if time_gap > cycle_time and diff_rate > check_rate :
                    print(ticker_data, closePrice_data, prev_price(ticker_data), diff_rate)

                # 시간 갱신 ( 이전 데이터에 현재 데이터로 업데이트 )
                if time_gap > cycle_time : 
                    df.loc[ticker_data] = (time_data, closePrice_data)

async def main():
    await bithumb_ws_client()

asyncio.run(main())

 코드를 세부적으로 이해하기는 어려울거 같고, async와 쓰레드의 개념을 살짝 이해하고 있어야 합니다. 전반적인 FLow는 아래와 같습니다.

 

 1) 전체 종목을 얻기 (180개)

 2) 각 종목, 현재가, 현재가를 얻은 시간를 이전 DataFrame 구조로 저장

 3) 실시간으로 종목의 변동된 현재가를 모니터링

 4) 이전 데이터와 현재 실시간으로 변동된 데이터를 비교

 5) 현재 변동된 데이터가 이전 데이터의 시간보다 X분 뒤고, 이전 데이터의 현재가보다 Y% 상승하였다면 출력.

 6) 현재 변동된 데이터가 이전 데이터의 시간보다 X분 뒤면, 이전 데이터를 현재 변동된 데이터로 치환

 

실행되는 모습 확인하기.

LINA_KRW 71 66.91 6.113
APIX_KRW 70.59 68.24 3.444
SOC_KRW 31.2 30.05 3.827
DAD_KRW 250 241.3 3.605
ADP_KRW 81.82 69.02 18.545
BOA_KRW 138 129.4 6.646
FX_KRW 1805 1714.0 5.309
ADP_KRW 77.93 75.42 3.328
BLY_KRW 36.05 34.0 6.029
FX_KRW 1892 1800.0 5.111
EGG_KRW 6.347 6.162 3.002
EL_KRW 9.82 9.528 3.065
EM_KRW 6.02 5.766 4.405
ARPA_KRW 98.98 95.02 4.168
ARPA_KRW 111.2 107.3 3.635
ARPA_KRW 116 111.2 4.317
ARPA_KRW 120.6 116.0 3.966
ARPA_KRW 127.9 120.3 6.318
ARPA_KRW 139.2 127.9 8.835
ARPA_KRW 145.7 139.2 4.67
ARPA_KRW 138.8 131.1 5.873
EL_KRW 11.04 10.4 6.154
ARPA_KRW 136.3 130.9 4.125
POLA_KRW 138.3 132.6 4.299
BLY_KRW 39 36.53 6.762
BLY_KRW 41.87 39.69 5.493
HIBS_KRW 4.741 4.582 3.47
BURGER_KRW 5650 5485.0 3.008
CTSI_KRW 785 760.0 3.289
ARPA_KRW 129 122.4 5.392
ARPA_KRW 133 129.0 3.101
BURGER_KRW 5910 5630.0 4.973
BURGER_KRW 6295 6010.0 4.742
FX_KRW 2031 1960.0 3.622
BLY_KRW 39 37.39 4.306
FX_KRW 2219 2102.0 5.566
BLY_KRW 38.27 37.03 3.349
ARPA_KRW 133.6 128.6 3.888
BLY_KRW 40.06 37.23 7.601
EL_KRW 10.25 9.918 3.347
ARPA_KRW 119.8 116.3 3.009
BLY_KRW 40.2 39.01 3.05
ARPA_KRW 123.5 119.6 3.261
POLA_KRW 146.7 135.8 8.027
APM_KRW 40.99 39.22 4.513
GHX_KRW 63.19 60.12 5.106
AWO_KRW 21.68 20.65 4.988
ARPA_KRW 123.5 117.8 4.839
ARPA_KRW 128 124.0 3.226
AWO_KRW 21.16 20.45 3.472
ARPA_KRW 133.9 126.5 5.85
APM_KRW 38.9 36.89 5.449
APM_KRW 40.44 39.03 3.613
EL_KRW 10.55 10.11 4.352
POLA_KRW 146.2 141.7 3.176
GOM2_KRW 11.73 11.37 3.166
WOM_KRW 541 525.0 3.048
FLETA_KRW 14.08 13.61 3.453
WOZX_KRW 546.1 529.0 3.233
STRAX_KRW 3015 2885.0 4.506
FX_KRW 1878 1801.0 4.275
FX_KRW 1950 1880.0 3.723
BLY_KRW 36.56 35.4 3.277
EM_KRW 5.61 5.444 3.049
BLY_KRW 36.43 35.04 3.967
WOM_KRW 532.2 513.6 3.621
ARPA_KRW 126.1 122.0 3.361
FX_KRW 1975 1906.0 3.62
WOM_KRW 541.9 517.9 4.634
GOM2_KRW 11.66 11.31 3.095
QTCON_KRW 18.37 17.54 4.732
QTCON_KRW 18.93 18.37 3.048
EM_KRW 5.445 5.267 3.38
QTCON_KRW 18.72 17.9 4.581
OBSR_KRW 7.618 7.177 6.145

 어제 밤 부터 오늘 까지, 2분동안 3% 이상 상승한 급등주를 추려낸 결과입니다.  간 밤에 알파체인, 블로서리, 펀디엑스가 많이 보이는 군요. 오늘 빗썸 기준 변동률 상위 1,2,3위를 한 녀석들입니다.

 

728x90
반응형

댓글