본문 바로가기

투자(기술적분석)

업비트 웹소켓을 이용한 실시간 RSI 출력 코드(python)

저번에는 REST API를 이용해서 실시간 RSI코드를 짜 봤습니다.
그 이후에 websocket으로도 만들어보겠다고 해놓고 무려 9개월이 지나서야 해봤네요. 저번에 한 것은 아래를 참고해주세요

업비트 API를 이용한 실시간 RSI 출력 코드(python)

비트코인 투자를 위해 기술적 분석(CMT)의 지표 중 하나인 RSI를 참고하시는 분들이 많으실 거라고 생각합니다. RSI는 충분히 검증된 지표이며, 보통은 30, 70을 과매도/과매수 구간으로 판단하여 매

primestory.tistory.com


websocket으로 실시간 데이터 자체를 출력하는 것은 어렵지 않습니다. 인터넷에 검색하다 보면 쉽게 나오고... 알고 보니 '펌핑 알람'이라고 하는 앱으로 RSI신호 알림을 설정할 수도 있더군요. 저도 써봤지만 서버에서 주는 응답이 그렇게 real time급으로 빠르지는 않기도 하고, 직접 만들어 놓으면 나중에 필요한 보조지표 함수만 만들면 되니까 좋을 것 같기도 해서 제작해 보았습니다.

먼저 저번에 만든 실시간 출력 코드는 REST API라고 하는 방식을 사용합니다. 이것은 업비트 측에 데이터 요청을 하면 응답을 받고, 응답을 받게 되면 연결이 끊어지는 구조입니다. 따라서, 매번 데이터 요청 시마다 요청과 연결을 해주어야 하기 때문에 실시간으로 분석하는데 어려움이 있습니다. 하지만, websocket기술은 연결이 끊어지지 않고 지속적으로 실시간으로 데이터를 계속 받을 수 있는 기술입니다.

저는 python의 asyncio 라이브러리를 이용하였습니다. 이것을 이용하면 비동기 작업방식을 사용할 수 있어, 두 가지 독립적인 작업을 효율적으로 할 수 있습니다. 한 가지 일을 했다가, 대기하는 동안 다른 일을 했다가 하는 식으로 쉬지 않고 일을 할 수 있습니다.


프로그램 설명 :

1) main함수에서는 멀티 프로세싱을 이용해서 프로세스 4개가 4개로 나눈 원화 코드 리스트에 대해 각각 요청과 RSI계산을 수행합니다. 코인 개수가 많기 때문에, 한 번에 많은 코인 데이터를 요청하고 계산할 경우 하나의 프로세스가 처리해야 할 계산이 너무 많아지기 때문입니다.
2) async과 await로 비동기적으로 데이터 요청과 분석을 진행합니다. 데이터가 서버로부터 쏟아지고, 그것을 지속적으로 계산하게 됩니다.
3) RSI계산은 특정 주기(현재 설정값 10초)로 재귀적(recursive)으로 수행됩니다. 왜냐하면 RSI계산 이후에 최대한 빠르게 그것이 기준치보다 높은지/낮은 지를 판단해야 하기 때문에 200개로 설정된 가격 샘플에 대해 매번 계산하는 것은 엄청난 성능 저하를 일으킬 것이기 때문입니다. 이는 지수 가중평균식의 RSI 재귀적 계산방식을 참고하였습니다. RSI계산 같은 경우 계산량에서 핵심이 되는 부분이라고 생각하여 최적화시켜 O(n) (n = 코인 개수) 정도의 복잡도로 구현하였습니다.
4) 첫 RSI계산은 REST API를 이용해 얻은 데이터를 이용합니다. 왜냐하면 RSI계산을 위해서는 이전의 많은 샘플이 필요한데 프로그램을 막 가동했을 때는 그런 데이터가 존재하지 않기 때문입니다.
5) RSI계산 시마다 upper bound를 넘겼을 때는 +1을, lower bound를 뚫고 하락했을 때는 -1점을 주어 각 코인들이 어떻게 행동하고 있는 알아볼 수 있는(?) 간단한 기능을 넣어보았습니다.
6) 특정 금액 근처에 있는 애들 같은 경우 한틱만 상승/하락해도 RSI가 급변해서 오차가 심하게 나타나는 경향이 있습니다.

개선해야 할 점 :

1) RSI의 계산은 완전한 Real-Time이 아닌, 특정 주기(현재 설정값 10초)로 계산되는데, 이것은 너무 많은 계산이 요구되므로 적절한 타협을 한 것입니다. (심지어 이것도 계산속도가 못 따라가 줘서 약간씩 밀리는 것 같긴 합니다...)
2) RSI의 계산에 오차가 발생합니다. REST API의 경우 RSI계산에 필요한 종가를 정확하게 요구하면 정확한 응답이 나오는데, RealTime으로 여러 코인을 한꺼번에 요청할 경우 응답 속도가 코인에 따라 달라 뒤죽박죽 섞이기도 하고, 종가가 아닌 현재가의 엄청난 응답이 쏟아지기 때문입니다. 제 컴퓨터에서는 이를 감당할 수 없어 정확한 종가를 매번 모든 코인에 대해 정확히 선택하는 것이 너무 어려웠습니다. 그것은 엄청나게 많은 호가창에서의 특정 시간의 거래 중에 정확히 마지막을 집어내는 일이기 때문입니다. 그래서 응답받은 것 중 가장 마지막의 데이터를 종가라고 생각하고 계산하게 되었고, 이것은 명백히 오차를 발생시킵니다.
3) 이전에 작성했던 코드를 최대한 활용하느라 코드가 약간 정리가 안되어있는 느낌이 있습니다... 바빠서 이 부분까진 못했네요

결론 :

real-time급으로 급상승/급하락에 대처를 하고 싶은 트레이더라면 웹소켓을 이용하는 것이 확실히 이점이 있어 보입니다. 정말로 real-time급으로 데이터를 처리하려면 컴퓨터 성능이 더 좋거나 더 나은 병렬 처리 또는 여러 포트를 이용하는 등의 방법이 필요할 것 같긴 합니다. 아직 실력이 부족해서 다른 방법은 잘 모르겠네요... 솔직하게 말해서... 보통사람들은 REST API로 약 몇십 초 정도의 딜레이가 있더라도 안정적으로 데이터를 받아 처리하는 것이 정확도도 높고 더 좋을 것 같습니다.

#
나중에 조금 보완해서 올릴예정이니 글과 코드는 참고만해주세요!

아래는 코드 일부, 출력 예시, 코드 첨부입니다.

def main(): print("#########Analysis Start##########\n") code_list, name_to_code = market_code() divided_codelist = list_chuck(code_list, int(len(code_list)/4)) code_list1 = divided_codelist[0] code_list2 = divided_codelist[1] code_list3 = divided_codelist[2] code_list4 = divided_codelist[3] for i in range(int(len(code_list)/4)*4, len(code_list)): code_list4.append(code_list[i]) proc1 = Process(target = mainprocess, args = (code_list1, name_to_code)) proc2 = Process(target = mainprocess, args = (code_list2, name_to_code)) proc3 = Process(target = mainprocess, args = (code_list3, name_to_code)) proc4 = Process(target = mainprocess, args = (code_list4, name_to_code)) proc1.start() proc2.start() proc3.start() proc4.start() proc1.join() proc2.join() proc3.join() proc4.join()
def mainprocess(code_list, name_to_code): rsi_number = 14 minute = 1 target_up = 70 target_down = 40 rsi_sample = 200 option = "multi" loop = asyncio.get_event_loop() loop.run_until_complete(RSI_analysis_websocket(code_list, name_to_code, minute, rsi_number, target_up, target_down,rsi_sample, option)) loop.close()

RSI14 1분 기준 출력물
Upbit_Analysis2.py
0.01MB