티스토리 뷰
Phase 2를 실전에 올리자마자 하루 만에 hotfix 6개
AI 분석, 멀티코인, 대시보드까지 완성한 Phase 2. 테스트도 통과했고, 로컬에서도 잘 돌았다. 실전에 올리면 되겠지? 올리고 나서 12시간 동안 6개의 hotfix를 쏟아냈다. 테스트에서 못 잡는 버그들이 있다.
버그 1: DataFrame의 bool 변환 — 새벽 2시 전면 중단
01:56, 전 코인 매매가 중단됐다. 에러 로그를 보니 ValueError: The truth value of a DataFrame is ambiguous.
# 문제 코드
if not df or not s:
return
# pandas DataFrame은 bool 변환이 안 된다
# 수정
if df is None or s is None:
return
Python 기본 문법이지만, pandas를 쓰면 이 함정에 반드시 빠진다. if not df는 빈 DataFrame에도, 데이터가 있는 DataFrame에도 에러를 뱉는다. pytest에서는 mock 데이터가 None이 아니라서 통과했고, 실전에서 API가 빈 DataFrame을 반환하는 순간 터졌다.
버그 2: LLM 스케줄러 — 재시작하면 4시간 대기
APScheduler의 interval=hours=4는 봇 시작 시점 기준이다. 봇을 껐다 키면 4시간 카운터가 리셋된다. 버그 패치하려고 재시작했더니 LLM 분석이 4시간 동안 안 돌았다.
# 수정: interval을 10분으로 줄이고, 실제 실행 여부는 DB에서 판단
scheduler.add_job(llm_analysis, 'interval', minutes=10)
def _should_run(self):
last = db.get_last_analysis_time()
return (now() - last).total_seconds() > 4 * 3600
스케줄러 간격과 비즈니스 로직 간격을 분리한 것. 이렇게 하면 재시작 후에도 4시간이 지났으면 10분 내 즉시 실행된다.
버그 3: LLM 파라미터 머지 누락 — rsi_oversold 4회 연속 고정
LLM이 bb_std: 2.5만 보내면, 기존 코드는 전체 파라미터를 교체해버렸다. 결과적으로 rsi_oversold가 유실되고 기본값 30으로 고정. 4번 연속 매수 기회를 놓쳤다.
# 문제: 전체 교체
strategy.params = llm_response["params"]
# 수정: 기존 값에 머지
strategy.params = {**current_params, **llm_response["params"]}
거기에 _fill_param_defaults에 rsi_oversold, bb_std가 아예 없었다. LLM이 생략하면 복구 불가. 기본값 테이블에 전략 파라미터 전부 추가하고, before/after 스냅샷도 넣어서 뭐가 바뀌었는지 추적할 수 있게 했다.
버그 4: 수수료 가드 통과 후 마이너스 — 0.1%의 함정
XRP를 +0.10%에서 트레일링 스탑으로 매도했다. 수수료 가드(왕복 0.1%)를 통과했으니 수익이어야 하는데, 실제 체결 후 -0.05% 손실.
가격 기준으로는 +0.1007%로 가드를 통과했지만, 시장가 매도 시 슬리피지가 발생한다. 호가창 깊이에 따라 체결 가격이 약간 불리해지는 건 당연한데, 수수료 가드에 이 마진을 안 넣었다.
# 수정: 수수료 0.1% + 슬리피지 마진 0.05%
ROUND_TRIP_FEE_PCT = 0.15 # 기존 0.1
버그 5: 트레일링 스탑 오발동 — 46만원이 XRP에 적용되다
이게 가장 황당했다. TAO를 460,800원에 모니터링하다가 XRP 체크로 넘어갔는데, _highest_price가 TAO 값(460,800)으로 남아있었다. XRP 현재가 3,500원과 비교하니 하락률 -99.6%. 트레일링 스탑이 즉시 발동해서 +0.15% 본전에 매도.
원인은 #99에서 예측한 그대로였다. 전략 인스턴스가 코인 간 공유되면서 상태가 오염된 것.
# 수정: 코인별 상태 분리
_coin_highest_prices = {} # {"KRW-XRP": 3510, "KRW-TAO": 460800}
# 틱 시작 시 복원, 종료 시 저장
strategy._highest_price = _coin_highest_prices.get(coin, 0)
버그 6: LLM 프롬프트 빈약 — Haiku가 보수적으로만 판단
LLM이 rsi_oversold를 4회 연속 생략했다. 프롬프트를 다시 봤더니, 매수 로직 설명이 없었다. Haiku는 전체 승률 21%를 보고 위축되어 매수 파라미터를 건드리지 않았던 것.
프롬프트에 전략 매수 로직(bb_rsi_combined의 동작 원리), 현재 적용 중인 파라미터, 전략별 승률 해석 가이드를 추가했다. 그리고 필수 파라미터 누락 시 재시도 프롬프트를 보내서 한 번 더 요청하도록 했다.
12시간의 교훈
6개 버그의 공통점: 전부 테스트에서 못 잡는 종류였다. mock이 실전과 다르고, 재시작 시나리오를 테스트 안 했고, 코인 간 상태 공유는 단일 코인 테스트에서 드러나지 않았다. 수수료 슬리피지는 백테스팅에서도 놓치기 쉬운 부분이다.
실전 투입 후 첫 24시간이 가장 중요하다. 이때 로그를 계속 보면서 잡아야 한다. 다음 글에서는 이 경험을 바탕으로 "사람이 안 봐도 되는 봇"을 만든 이야기를 쓴다.
👉 다음 글 보러가기
'CryptoBot' 카테고리의 다른 글
| 코어 머니 로직 전수 리뷰 — 봇이 흘리는 돈 찾기 (0) | 2026.05.07 |
|---|---|
| 봇이 알아서 돌게 만들기 — 스케줄러, 안전장치, 그리고 웹 사이트 제작 (0) | 2026.04.16 |
| 실전 운영에서 터진 것들 — 리스크 관리와 리팩토링 (0) | 2026.04.11 |
| FastAPI + React로 봇 관리 대시보드 만들기 (0) | 2026.04.10 |
| 승률 22%에서 배운 것 — 멀티코인 + 전략 진화 (0) | 2026.04.09 |
- Total
- Today
- Yesterday
- 일일주간월간스케줄러
- Haiku4096토큰
- DataFramebool
- 코드자체감사
- CDC
- jdbc
- kafka connect
- AnthropicCaching
- 코인별전략배정
- BOJ #JS
- 코인별손익분석
- LLM비용오차
- Kafka
- P0P4우선순위
- CryptoBot
- 비용80%절감
- LLM비활성결정
- 메이저화이트리스트
- 데모모드
- 5중검증
- SlidingWindowTTL
- Page_DownPage_DownPage_Down
- LLM파라미터머지
- 수수료슬리피지
- LLM동적호출
- 한달운영진단
- Telegram알림
- 트레일링스탑버그
- 일경계처리
- 데이터엔지니어링
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |