티스토리 뷰

한 달 운영 결과는 정직했다.

기간:    2026-04-04 ~ 2026-05-06 (33일)
입금:    50만원
잔고:    47만원
손익:    -6%, -3만원
매도:    265건 (일평균 8.0건)

승률은 66.8%였다. 100번 매매하면 67번 이긴다. 그런데 적자다. 어디서 새고 있을까. 백테스트는 흑자였다 — bb_rsi_combined가 메이저(BTC/ETH/XRP) 평균 +7.45%, Buy&Hold -24.75% 약세장에서. 백테는 잘 도는데 실전이 안 되는 것.

한 달 동안 시도한 게 한두 가지가 아니었다. 자금 추적 자동화, 손절-매수 충돌 통합, 동적 stop_loss, ROI 테이블 상향, 시간 구간 확장. 하나씩 다 적어두면 길어지니, 그냥 결과부터 말하자면 이 모든 시도가 핵심을 못 짚고 있었다.

코인별 손익을 처음 봤다

한 달 데이터를 다 모아 코인별 손익을 정렬해봤다. 그동안 전체 지표만 보고 있었지, 코인별로 본 적이 거의 없었다.

최악 5개:
  KRW-NEWT   -31,056원  ← 한 달 손해의 1.5배
  KRW-WLFI    -7,074원
  KRW-TRUMP   -3,519원
  KRW-HUNT    -2,450원
  KRW-WLD     -1,827원

최고 5개:
  KRW-0G      +9,357원
  KRW-TOKAMAK +6,025원
  KRW-BIO     +5,112원
  KRW-WET     +2,846원
  KRW-AAVE    +2,534원

NEWT 한 코인으로 -31,056원. 한 달 전체 손실 -3만원보다 큰 손실을 NEWT 하나가 만들었다. 다른 코인들 합치면 흑자였는데, NEWT가 그걸 다 갉아먹었다.

그제야 보였다. 진짜 적자 원인은 알트 코인 마구잡이 매매였다. bb_rsi_combined 자체는 메이저에선 멀쩡한 흑자 전략이다. 알트(특히 신생 토큰)에 적용하니 비대칭적 큰 손실이 났을 뿐.

백테스트 재검증 — 메이저는 흑자

가설을 백테스트로 확인했다. 122일 데이터(약세장).

티어 1 (시총 상위)
  BTC   +3.42%   (Buy&Hold -22.61%)
  ETH   +3.51%   (Buy&Hold -23.98%)
  XRP  +15.43%   (Buy&Hold -27.65%)
  SOL  ...

티어 2 (시총 5~15위)
  DOGE +18.14%   (Buy&Hold  -5.56%)
  AVAX +14.22%   (Buy&Hold -26.41%)

티어 1만 평균 +7.45%, 티어 1+2 평균 +10.94%. 메이저에선 분명히 흑자 전략이었다. 알트만 빼면 됐다.

메이저 코인 화이트리스트

해결책은 단순했다. 매매 가능 코인을 화이트리스트로 강제 제한.

티어 1 (필수, 4개):  BTC · ETH · XRP · SOL
티어 2 (선택, 4개):  ADA · DOGE · AVAX · LINK

기본값은 티어 1+2 (8개). CoinScanner는 이 화이트리스트 안에서만 후보를 고른다. 보유 중인 코인이 화이트리스트 밖이라도 강제 청산은 안 한다 — 자연스럽게 매도되도록 active_coins에 보존.

이게 진짜 레버였다. 기능 하나 추가하는 데 비해 효과는 가장 컸다. 한 달 동안 ROI 테이블 만지고, stop_loss 동적화하고, LLM 프롬프트 가다듬은 모든 것보다, 알트 빼는 게 압도적으로 효과적이었다.

LLM 비활성화

또 하나 어려운 결정이 있었다. 한 달 데이터를 보니 LLM 활성/비활성 기간이 자연스럽게 비교됐다.

LLM 활성   15일 -31,676원
LLM 비활성  5일  +8,640원

표본은 작지만, 같은 한 달 안에서의 차이라 의미가 있다. 무엇보다 LLM이 수익에 기여하고 있다는 증거를 찾을 수 없었다. 비용은 매달 들고, 효과는 입증 안 되고. bot_config.llm_enabled = false 토글을 추가하고 기본값 false로 뒀다.

완전히 끄는 건 아니다. 코드는 다 살려두고, 언제든 다시 켤 수 있다. 다만 다음 한 달 동안은 LLM 없이 고정 파라미터로 돌리고, 그 결과를 가지고 LLM 재활성화 여부를 다시 판단할 거다.

파라미터 sweep으로 고정값 찾기

LLM 없이 돌리려면 파라미터를 직접 잘 잡아야 한다. bb_rsi_combined를 5코인(BTC, ETH, XRP, DOGE, AVAX) × 100조합으로 sweep했다.

rsi_oversold:    [20, 25, 30, 35, 40]
rsi_overbought:  [55, 60, 65, 70, 75]
bb_std:          [1.5, 2.0, 2.5, 3.0]

최적 결과: rsi_oversold=30, rsi_overbought=70, bb_std=2.0. 흥미롭게도 rsi_overbought는 55~75가 모두 동일했다. 이유는 RSI 정상복귀 매도가 거의 안 일어나고, ROI 테이블/MA 중간선/stop_loss로 먼저 매도되기 때문. RSI 매도는 사실상 사문화된 코드였다.

대시보드도 손봤다

화이트리스트로 매매가 단순해진 김에 public 대시보드도 개편했다. 와이드 레이아웃(1600px), 손익률 Hero 카드(큰 +/-%), 일별 추이 차트(recharts), 모바일 반응형. 백엔드는 KRW 절대값을 비공개로 두고 비율(%)만 노출하는 API(/api/public/account-pnl)를 따로 만들었다.

이 시리즈를 마치며

10편짜리 시리즈가 여기서 끝난다. Python 스크립트 하나로 시작한 봇이, 멀티코인 매매, AI 분석, 웹 대시보드, 자동화된 운영 시스템까지 갖췄다. 그리고 결국 가장 큰 발견은 "코드를 줄이는 결정"이었다. LLM 끄기, 알트 매매 막기. 추가가 아닌 제거가 답이었다.

봇은 아직 돌고 있다. 다음 한 달은 변경 없이 유지하기로 했다. 새 데이터가 쌓이면 다시 결정한다. 그동안의 경험을 한 줄로 요약하면: 실측 데이터 없이는 어떤 추측도 무가치하다. 한 달 운영하고 코인별 손익을 본 5분이 그 전 한 달 분투의 모든 것보다 명확했다.

관심 있는 분은 GitHub 저장소를 확인해봐도 좋다. 시리즈를 끝까지 읽어준 분께 감사를.


📚 CryptoBot 개발일지 완결

시리즈 1편부터 다시 보고 싶다면 [1편] 코인 자동매매 봇, 처음부터 만들기 — Python 하나로 MVP 완성 부터.

반응형
댓글