문제: 로그가 너무 많아서 로그가 사라졌다
자동매매 전략의 on_candle 함수는 종목마다, 매 틱마다 호출된다. 여기에 MDD(최대 낙폭) 차단이 걸릴 때마다 logger.info로 로그를 무조건 찍는 코드가 있었다. “차단 중”이라는 상태 하나를 매 틱마다 다시 알리는 셈이다.
2026년 7월 30일 실측해보니, 25분 동안 127,141줄이 쌓였다. 초당 약 85줄이다.
127141 MDD severe (-18%+) — 신규 진입 차단
279 LLM 분석 적용(세션 브리지 claude)
1 WS 계좌 스냅샷 갱신 실패
로그가 사라지면 뭘 잃는가
문제는 디스크 용량이 아니었다. 컨테이너 로그 설정이 max-size 10m, max-file 3으로 되어 있었는데, 이 정도 속도로 로그가 쌓이면 로그 보존 기간이 25분으로 줄어든다.
그리고 실제로 그날 있었던 매도 체결 — 한화오션 +38,709원, LG엔솔 +2,778원 — 기록조차 로그에서 찾을 수 없었다. 매매 시스템에서 “무엇을 언제 얼마에 팔았는가”는 사후 검증의 근간인데, 그게 통째로 사라진 것이다. 로그 폭주가 단순한 디스크 낭비를 넘어서 감사 추적(audit trail) 자체의 소실로 이어진 셈이다.
어떻게 고쳤나
로그를 매 틱 찍는 대신, 상태가 바뀌는 순간에만 남기도록 바꿨다.
blocked = mdd_size_factor == 0.0
if blocked != self._mdd_blocked:
... logger.warning(진입 또는 해제)
self._mdd_blocked = blocked
if blocked and not has_position:
return Signal.HOLD, 0.0
몇 가지 세부 판단이 있었다.
- 차단이 풀리는 순간도 기록한다. 언제 다시 정상으로 돌아왔는지를 추적해야 하기 때문이다. 진입만 기록하고 해제를 기록하지 않으면 “언제까지 막혀 있었나”를 알 수 없다.
- 로그 레벨을 info에서 warning으로 올렸다. 매매가 멈추는 상태이니 단순 정보성이 아니라 주목해야 할 사건이라는 판단이다.
- 재시작 후 중복 로그를 막기 위해 이 플래그를 상태 저장/복원(
export_state/import_state)에 포함시켰다. 이미 있던_last_in_cooldown플래그와 같은 방식을 따른 것이다.
곁다리로 발견한 또 다른 문제
로그 문구는 “-18%+”로 하드코딩돼 있었는데, 실제 차단 임계값은 -15%였다(_get_mdd_size_factor 함수에서 mdd <= -0.15일 때 차단). 로그가 스스로 잘못된 정보를 남기고 있었던 것이다. 실제 계산된 DD 값을 그대로 출력하도록 바꿔서 이 불일치도 함께 없앴다.
검증에서 지킨 선
이 작업에서 분명히 하려던 것은 “로그만 줄이고, 차단 로직 자체는 건드리지 않는다”는 경계였다. HOLD를 반환하는 동작은 그대로 두고 로그 출력 빈도만 바꿨다.
추가한 테스트 4건은 정확히 이 경계를 확인하는 것들이었다.
- 차단이 지속되는 동안 로그가 1회만 찍히는지 (30틱을 반복해도 1줄인지)
- 해제될 때도 1회 기록되는지
- 로그를 줄였다고 차단 동작(HOLD 반환) 자체가 흔들리지 않았는지
- 재시작 후에도 플래그가 보존돼 중복 로그가 안 나는지
관련 테스트 103건이 모두 통과했다.
일부러 하지 않은 것
이 작업은 로그 문제만 다뤘다. MDD -18.4%로 신규 진입이 차단된 상태 자체를 풀지는 않았다 — 그건 equity_peak이 종목별로 분산되며 생긴 별개의 설계 결함이었고, 별도로 다뤘다.
남는 교훈
로깅은 “일단 많이 남겨두면 안전하다”고 여기기 쉽다. 하지만 로테이션이 걸린 환경에서는 로그량 자체가 보존 기간을 결정한다. 초당 85줄을 찍는 로거는, 의도와 다르게 “25분 이전 일은 아무것도 몰라도 된다”고 선언하고 있는 것과 같다.
특히 트레이딩처럼 사후 검증이 핵심인 도메인에서는, 로그를 얼마나 남길지도 리스크 관리의 일부다. 상태가 바뀔 때만 기록한다는 원칙 하나로, 로그는 정보를 잃지 않으면서도 양은 극적으로 줄었다.