Files
AutoCoinTrader/docs/code_review_report_v2.md

91 lines
7.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# docs/code_review_report_v2.md
## AutoCoinTrader 코드 리뷰 v2 (2025-12-10)
- 리뷰어: GitHub Copilot (GPT-5.1-Codex-Max)
- 관점: Python/시스템 아키텍트 + 코인 트레이더
- 범위: `src/` 전역, 최신 KRW 예산 관리/동시성/신호/주문/설정/지표/상태 저장 로직
### 0) 종합 평가
- 안정성: 7.5/10 → 개선 진행 중이나 일부 동시성·정밀도·리밋 이슈 잔존
- 전략/리스크: 7/10 → 슬리피지·호가단위·분당 Rate Limit 미흡으로 실거래 리스크 존재
- 코드 품질: 7/10 → 타입힌트·예외 구체화·상태 일관성 추가 필요
### 1) 주요 강점
- ✅ KRWBudgetManager로 동일 잔고 중복 사용 방지(Option B) + finally 해제 적용
- ✅ OHLCV 캐시 + 토큰 버킷(초 단위)으로 API 남용 일부 방지
- ✅ holdings 저장의 원자적 쓰기/권한 설정 및 최고가 갱신(StateManager 연동)
- ✅ Telegram 긴 메시지 분할, CircuitBreaker 임계값 강화, 부분 매수 지원
### 2) 크리티컬 이슈 (즉시)
1. **동일 심볼 복수 주문 시 예산 충돌** (`src/common.py:60-150`, `src/order.py` 호출부)
- KRWBudgetManager가 심볼 단일 슬롯만 보유 → 같은 심볼 복수 주문이 동시에 발생하면 후행 주문이 선행 주문 할당액을 덮어쓰기/해제하며 이중 사용 가능.
- 제안: `allocations``{symbol: [allocations...]}` 혹은 누적 수치 + ref-count로 변경하고 `release(symbol, amount)` 지원. 주문 토큰 기반 식별 권장.
2. **분당 Rate Limit 미적용 + Balance/Price 조회 비보호** (`src/common.py:25-80`, `src/holdings.py:get_current_price`, `src/holdings.py:get_upbit_balances`)
- 현재 초당 8회만 제한, 분당 600회 제한/엔드포인트별 제한 미적용. 잦은 현재가/잔고 조회는 제한 우회 없이 직행 → 418/429 위험.
- 제안: 분 단위 토큰 버킷 추가, `get_current_price`·`get_upbit_balances`·주문 모니터링 전역 적용. 모듈 간 공유 RateLimiter 집약.
3. **재매수 쿨다운 기록 레이스/손상 가능** (`src/common.py:160-240`)
- `recent_sells.json` 접근 시 파일 Lock/원자적 쓰기 없음, 예외도 무시 → 동시 매도 시 기록 손상/쿨다운 무시 가능.
- 제안: holdings와 동일한 RLock + temp 파일 교체 사용, JSONDecodeError 처리 추가.
4. **가격/수량 부동소수점 정밀도 손실** (`src/order.py` 전역, 매수/매도 계산)
- Decimal 적용 필요했던 HIGH-006 미완료. 슬리피지 계산·호가 반올림·수량 계산이 float 기반 → 체결 실패/초과주문 리스크.
- 제안: Decimal 기반 `calc_price_amount()` 유틸을 만들어 모든 주문 경로에 적용, tick-size 반올림 포함.
5. **현재가 조회 재시도/캐시 없음** (`src/holdings.py:get_current_price`)
- 단일 요청 실패 시 0 반환 후 상위 로직이 손절/익절 판단에 잘못된 가격 사용 가능. RateLimiter도 미적용.
- 제안: 짧은 backoff + 최대 N회 재시도, 실패 시 None 반환하고 상위에서 스킵 처리. 짧은 TTL 캐시(예: 1~2s)로 API 부하 완화.
### 3) High 이슈 (1주)
1. **예산 할당 최소 주문 금액 미검증** (`src/common.py:100-140`)
- 부분 할당이 5,000원 미만일 수 있음 → 이후 주문 경로에서 실패. allocate 시 `MIN_KRW_ORDER` 적용 또는 할당 거부 필요.
2. **상태 동기화 불일치 가능성** (`src/holdings.py:update_max_price`, `src/state_manager.py`)
- StateManager와 holdings.json을 이중 관리하지만, holdings 저장 실패 시 상태 불일치 남음. 반대 방향 동기화 루틴 부재.
- 제안: 단일 소스(STATE_FILE) → holdings는 캐시용, 주기적 리빌드/검증 함수 추가.
3. **Pending/Confirm 파일 기반 워크플로 취약** (`src/order.py:40-120`)
- JSON append + rename 기반으로 손상/유실 가능, 만료/청소 로직 없음. confirm 파일 폴링이 무한 대기 가능.
- 제안: TTL 기반 클린업, 예외 안전한 atomic append(append-only log) 또는 sqlite/JSONL 대체.
4. **OHLCV 캐시 TTL 고정·지표 시간대 미고려** (`src/indicators.py:20-120`)
- 5분 TTL 고정, 타임프레임/거래소 홀리데이/서버 시간 불일치 고려 없음. 실패 시 캐시 미기록으로 연속 호출 폭증 가능.
- 제안: 타임프레임별 TTL(캔들 주기의 0.5~1배), 실패 시 단기 negative-cache 추가.
5. **예외 타입·로깅 불균일** (전역)
- 일부 함수 `except Exception` 광범위, 로깅 레벨 혼재. 거래 결정 경로에서 `raise` 누락되어 조용한 실패 위험.
- 제안: 표준 예외 계층(예: TradingError)과 레벨 매핑 가이드 채택.
6. **스레드 수/재시도 기본값 과도** (`src/indicators.py:60-120`)
- 최대 재시도 5, 누적 대기 300s는 메인 루프 정지 유발 가능. max_threads 기본 3은 I/O 바운드 대비 낮음.
- 제안: 재시도 횟수/누적 대기 환경변수 검증, 타임아웃 후 상위에 명시적 실패 반환.
### 4) Medium/Low 이슈 (요약)
- **타입 힌트 미완**: signals/order/notifications 일부 public 함수 미타이핑.
- **테스트 갭**: 현재가 실패/분당 리밋/재매수 쿨다운 레이스/Decimal 수량 계산 등 미커버.
- **보안/권한**: `recent_sells.json`, `pending_orders.json` 등 다른 상태 파일에 권한 0o600 미적용.
- **로그 노이즈**: KRWBudgetManager 할당 성공 로그가 INFO → 대량 스레드 시 로그 부하. DEBUG로 하향 권장.
- **환경설정 검증**: `auto_trade` 하위 값(슬리피지, fee_safety_margin_pct, cooldown_hours) 범위 검증 없음.
### 5) 개선 권고안
1. **예산 관리자 리팩토링**: 다중 주문 토큰 기반 allocate/release, 최소 주문 검증, context manager 지원.
2. **이중 RateLimiter**: 초/분 이중 버킷 + 전역 훅을 `get_current_price`, balances, 주문 모니터에 적용.
3. **Decimal 유틸 도입**: `calculate_order_amount()` + tick-size 반올림 공통화, 모든 주문 경로 치환.
4. **상태 파일 일관성**: StateManager 단일 소스화, holdings.json은 캐시/백업; 주기적 검증/리빌드 스케줄러 추가.
5. **파일 기반 큐 정비**: pending/confirm/recent_sells에 원자적 쓰기+TTL+락 적용, JSONL 또는 sqlite로 마이그레이션.
6. **관측 가능성**: Rate-limit 대기, 예산 할당 실패, 재매수 쿨다운 거부 등 주요 이벤트에 메트릭/카운터 추가 (prometheus textfile 등).
7. **테스트 플랜**: 분당 리밋 초과 시나리오, Decimal 계산 경계, 동일 심볼 복수 주문, 상태 파일 손상/복구 테스트 추가.
### 6) 제안 테스트
- `pytest src/tests/test_concurrent_buy_orders.py -k multi_symbol_same_time` (동일 심볼 중복 주문 케이스 추가 후)
- `pytest src/tests/test_order_improvements.py::test_decimal_amount_precision`
- 인수 테스트: 10개 심볼 × 5분봉, dry-run, 초/분 RateLimiter 로그 확인
### 7) 우선순위 정리
- **P0**: 예산 다중 할당 안전화, 분당 RateLimit 적용, 재매수 쿨다운 파일 락/원자쓰기
- **P1**: Decimal 주문 계산, 현재가 재시도/캐시, 상태 소스 단일화
- **P2**: pending/confirm 스토리지 정비, 설정값 검증 확장, 로깅 레벨 정리
- **P3**: 메트릭/모니터링, 테스트 커버리지 확장