
조건에 맞으면 거래를 실행하는 단순한 로직은, 너무나 많은 문제를 일으킨다. 간단히 생각해봐도, 다음과 같은 문제가 발생할 수 있을 것 같다.
예상되는 문제점들
거래 조건에 맞으면→거래 시작에서, 만약 조건에 맞는 코인이 50개면 50개,100개면 100개 를 동시에 거래하게 된다.
a. 서버 cpu 리소스가 감당할 수 있는가?
b. 50개, 100개를 동시에 거래하면 손실 리스크를 잘 관리할 수 있는가?
c. API와 WebSocket이 이런 대량 거래를 실시간으로 처리하는데 요청 수 제한에 걸리지 않을 수 있는가?- 거래중인 코인인데, 단순한 로직으로 인해 거래 대상 코인에 또 추가된다면 같은 거래가 2개 실행되는데 이를 막아야 하지 않을까?
공유자원(자료구조) 추가 및 통신 Sequence 수정
문제를 미연에 방지하기 위해, 실시간으로 거래중인 코인들을 저장할 자료구조들을 추가하였다. active_trade(set 자료형)을 추가하여 현재 거래가 진행중인 코인을 또 거래되는 것을 방지했다. 현재 자료구조는 총 4개이고, 수정된 프로그램 흐름은 다음과 같다.
* 프로그램이 지속적으로 작동함에 따라, 자원이 누적되어 서버의 누적 부하를 해소시켜주기 위해 메모리 할당을 수동으로 해제해줘야 하나 고민했다. 다행이도 파이썬에서는 가비지 컬렉션이 참조 카운트0인 변수, 자원들을 자동으로 메모리 해제 해준다고 한다.
* target_dict 현재가도 1초마다 업데이트 해야 한다고 생각하지만 이를 진행하면, 요청 수 초과 우려가 있음(분당 100회, 2개의 웹소켓에서 1초에 1번씩 가격 업데이트시 분당 120회). trading_dict에서 거래로 넘어가는 도중, trading_dict가 업데이트됨


반복 작업들은 서로 비동기적으로 진행되게 하였다.
따라서 공유 자원들을 탐색하며 존재하면 작업 수행. 존재하지 않으면 1초 대기 후 반복작업 실행하게 된다.
거래 (매수 시작부터 매도 완료까지를 의미)
이제 대망의 거래 부분이다. 위 다이어그램에 명시한 것 처럼, trading_dict에 최대 5개 코인이 거래 대기를 하며, 실제 거래를 진행하는 함수가 1초마다 trading_dict를 탐색하며 5개의 거래를 진행하게 할 것이다. 이는 비동기 Task로 진행된다. 거래 Task가 끝나는 부분에서, trading_dict와 active_tardes에서 거래한 코인을 제거한다. 그러면 조건을 만족하는 다음 코인이 자동으로 trading_dict→active_trades로 추가되며 다음 거래가 시작되게 한다. 이로써 5개 이상 코인을 한번에 거래하지 않게 된다.
아래는 trading.py이다.
import asyncio
from datetime import datetime
async def process_trade(coin, trading_dict, indicators_dict, active_trades):
"""
개별 코인 거래를 처리하는 비동기 함수입니다.
거래 완료 후 active_trades, trading_dict에서 해당 코인을 삭제합니다.
"""
try:
# TODO: 거래 상세 조건 및 실행 로직 구현
finally:
# 거래가 끝나면 active_trades, trading_dict에서 해당 코인을 제거
# 이후에도 동일 코인이 조건을 충족해서 indicators_dict -> target_dict 추가 업데이트 시 재 거래 가능
active_trades.discard(coin)
trading_dict.pop(coin, None)
async def execute_trades(trading_dict, indicators_dict):
"""
trading_dict에 존재하는 코인에 대해 개별 비동기 거래를 실행합니다.
이미 거래 중인 코인(active_trades에 포함된 코인)은 건너뛰며,
거래가 완료되면 각 작업이 trading_dict에서 해당 코인을 삭제합니다.
함수 동작 방식:
1. trading_dict는 외부에서 1초마다 업데이트됩니다.
2. trading_dict에 있는 코인에 대해 거래를 개별 비동기 작업(Task)으로 진행합니다.
3. 각 작업은 완료되면 trading_dict에서 자신의 코인을 삭제합니다.
4. 이후 trading_dict 업데이트 시, 삭제된 코인의 자리는 다시 채워져 추가 거래가 진행됩니다.
"""
active_trades = set() # 현재 거래 중인 코인을 추적하는 집합
while True:
# trading_dict는 매 1초마다 업데이트되므로, 그 시점의 거래 대상 코인 목록을 확인
for coin in list(trading_dict.keys()):
# 이미 거래 중인 코인은 건너뜀
if coin not in active_trades:
active_trades.add(coin)
asyncio.create_task(
process_trade(coin, trading_dict, indicators_dict, active_trades)
)
await asyncio.sleep(1)
[파이썬] 업비트 자동매매 봇 만들기 7 - private websocket, Critical Section, 비동기 Lock (Mutex)
거래 정보를 실시간으로 받기 위한 웹소켓을 알아보던 중, private는 realtime밖에 지원을 안 한다는 것을 알게 되었다. 이를 간략하게 정리하면 다음과 같다.Snapshot과 Realtime 데이터업비트 웹소켓으
chabin37.tistory.com
'API Transaction > Upbit' 카테고리의 다른 글
| [파이썬] 업비트 자동매매 봇 만들기 8 - 1차 완료 후 정리. 예외 사항 처리 및 추후 구현 가능 사항들. (0) | 2025.02.13 |
|---|---|
| [파이썬] 업비트 자동매매 봇 만들기 7 - private websocket, Critical Section, 비동기 Lock (Mutex) (0) | 2025.02.12 |
| [파이썬] 업비트 자동매매 봇 만들기 5 - asyncio, async, await, 비동기 작업 (1) | 2025.02.08 |
| [Python] 업비트 자동매매 봇 만들기 4 - Tulip Indicators (2) | 2025.02.01 |
| [Python] 업비트 자동매매 봇 만들기 3 - Process Flow Diagram과 API요청 수 제한 (0) | 2025.01.30 |