티스토리 뷰

서버 없이, Python 하나로 코인 자동매매를 시작했다

업비트에서 코인을 사고파는 걸 자동화하고 싶었다. 서버 비용은 쓰기 싫고, 복잡한 인프라도 필요 없었다. Python 스크립트 하나가 1분마다 시세를 보고, 조건이 맞으면 사고, 목표가에 도달하면 파는 것. 그게 전부였다.

이 글은 CryptoBot이라는 이름의 자동매매 봇을 처음부터 만든 기록이다. 프로젝트 생성부터 첫 자동매매 루프가 돌아가기까지, MVP 완성의 여정을 정리한다.

프로젝트 세팅

기술 스택은 단순하게 잡았다.

  • Python 3.11 + pyupbit (업비트 API 래퍼)
  • SQLite (서버 없이 파일 하나로 DB)
  • APScheduler (스케줄링)
  • pandas, numpy (지표 계산)

pyproject.toml로 프로젝트를 구성하고, src/cryptobot/ 구조를 잡았다. 포매터는 ruff, 테스트는 pytest. 업비트 API Key는 출금 권한을 제외하고 발급했다. 이건 자동매매 봇을 만들 때 절대 잊으면 안 되는 부분이다.

데이터베이스 설계

SQLite를 선택한 이유는 명확했다. MVP에 PostgreSQL은 과하다. 파일 하나로 끝나고, 별도 프로세스도 필요 없다. 핵심 테이블 5개를 설계했다.

market_snapshots  — 1분마다 수집하는 시세 + 지표 스냅샷
trade_signals     — 전략이 발생시킨 매수/매도 시그널
trades            — 실제 체결된 매매 기록
strategy_params   — 전략 파라미터 (K값, 손절률 등)
daily_reports     — 일일 정산 리포트

ORM은 쓰지 않았다. 직접 SQL을 작성하는 게 이 규모에서는 더 명확하고 빠르다.

기술적 지표 계산

indicators.py에 RSI, 이동평균(MA 5/20/60), 볼린저밴드, ATR을 구현했다. pandas 덕분에 계산 자체는 간단하지만, 실시간 데이터에 적용할 때 주의할 점이 있다. 데이터가 충분히 쌓이기 전에 지표를 계산하면 의미 없는 값이 나온다. 초기 구동 시 최소 데이터 확보 로직을 넣어야 한다.

변동성 돌파 전략

첫 전략으로 변동성 돌파 전략을 선택했다. 래리 윌리엄스가 만든 고전적인 전략인데, 원리가 직관적이다.

# 매수 조건
target_price = 시가 + (전일 고가 - 전일 저가) × K
if 현재가 > target_price:
    매수()

K값은 보통 0.5를 쓰지만, 시장 상태에 따라 조절할 수 있게 strategy_params 테이블에서 읽어오도록 했다. 여기에 트레일링 스탑(최고점 대비 N% 하락 시 매도)과 손절 로직을 붙였다.

시장 상태 필터도 추가했다. MA5 > MA20이면 bullish, MA5 < MA20이면 bearish로 판단해서 bearish일 때는 매수를 아예 안 한다. 단순하지만 효과적인 필터다.

주문 실행

trader.py는 pyupbit을 감싼 주문 실행 모듈이다. 시장가 매수/매도, 잔고 확인, 포지션 관리를 담당한다. 핵심은 실패 처리다. 업비트 API는 가끔 타임아웃이나 일시적 오류를 뱉는데, 단순 재시도로 대부분 해결된다. 매매 결과는 즉시 DB에 기록해서 나중에 분석할 수 있게 했다.

데이터 수집기

collector.py가 1분마다 업비트 API를 호출해서 현재가, OHLCV, 거래량을 가져온다. 가져온 데이터로 기술적 지표를 계산하고 market_snapshots에 저장한다. 시장 상태 판단도 여기서 한다.

메인 루프 — 모든 걸 연결하기

마지막 퍼즐은 스케줄러였다. APScheduler로 전체 파이프라인을 오케스트레이션한다.

# 1분마다: 데이터 수집 → 지표 계산 → 매매 판단 → 주문 실행
scheduler.add_job(tick, 'interval', minutes=1)

# 자정: 일일 정산
scheduler.add_job(daily_settlement, 'cron', hour=0)

봇 시작 시에는 안전 장치를 넣었다. 미체결 주문 전부 취소, 현재 포지션 상태 동기화. 갑자기 봇이 죽었다가 다시 켜져도 일관된 상태에서 시작하도록 했다. Graceful shutdown도 구현해서 SIGTERM을 받으면 현재 틱을 마무리하고 깔끔하게 종료한다.

첫 실행

터미널에서 python -m cryptobot을 치면 봇이 시작된다. 1분마다 로그가 찍히고, 조건이 맞으면 매수하고, 목표가에 도달하면 매도한다. 서버 없이 로컬 Python 프로세스 하나로 돌아가는 자동매매 봇의 MVP가 완성된 순간이었다.

물론 이게 끝이 아니었다. 승률은 처참했고, BTC 하나만으로는 기회가 너무 적었다. 다음 글에서는 Claude Haiku를 붙여서 AI가 시장을 분석하고 파라미터를 자동으로 튜닝하도록 만든 이야기를 쓴다.


반응형
댓글