Files
AutoCoinTrader2/docs/code_review_report_v3.md

88 lines
8.9 KiB
Markdown

# AutoCoinTrader Code Review Report (v3)
## 1. 개요 (Overview)
본 보고서는 `AutoCoinTrader` 프로젝트의 전체 코드베이스를 **Python 전문가****전문 암호화폐 트레이더** 관점에서 심층 분석한 결과입니다. 현재 코드의 구조, 안정성, 트레이딩 로직의 건전성, 그리고 잠재적인 위험 요소를 식별하고 개선 방안을 제시합니다.
---
## 2. Python 전문가 관점 분석 (Technical Review)
### 2.1 아키텍처 및 디자인 패턴
* **모듈화 (Good)**: `main.py`, `order.py`, `signals.py`, `holdings.py`, `config.py` 등 역할별로 파일이 잘 분리되어 있습니다. 모듈 간 의존성이 비교적 명확하며, 순환 참조를 방지하기 위한 `TYPE_CHECKING` 사용도 적절합니다.
* **설정 관리 (Good)**: `RuntimeConfig` dataclass를 사용하여 설정값을 객체로 관리하는 방식은 매우 훌륭합니다. 환경변수와 JSON 설정을 결합하고 검증 로직(`build_runtime_config`)까지 갖추어 견고합니다.
* **동시성 제어 (Warning)**:
* `src/holdings.py` 등에서 `threading.RLock`을 사용하여 스레드 안전성을 확보하려는 시도는 좋습니다.
* 그러나 **파일 기반 상태 관리(`holdings.json` 등)는 본질적으로 느리고 경쟁 조건(Race Condition)에 취약**할 수 있습니다. `holdings_lock`이 메모리 상의 접근은 막아주지만, 다중 프로세스(혹은 사용자가 수동으로 파일을 수정하는 경우) 환경에서는 파일 덮어쓰기 등의 문제가 발생할 수 있습니다.
* Windows 환경에서 `os.replace`는 원자적(atomic)이려고 노력하지만, 파일 핸들이 열려있을 경우(백신 프로그램, 인덱싱 등) `PermissionError`가 발생할 가능성이 여전히 존재합니다.
### 2.2 코드 품질 및 스타일
* **타입 힌팅 (Excellent)**: 대부분의 함수에 Type Hinting이 적용되어 있어 가독성이 좋고 IDE 지원을 받기 유리합니다.
* **예외 처리 (Good but Broad)**: `try-except Exception as e` 패턴이 광범위하게 사용되고 있습니다. 프로그램이 죽지 않고 계속 도는 것(Robustness)에는 유리하지만, **어떤 에러가 났는지 정확히 파악하기 어렵게 만들거나(Swallowing errors)**, 의도치 않은 버그를 숨길 위험이 있습니다.
* **로깅 (Excellent)**: `setup_logger``CompressedRotatingFileHandler`를 통해 로그 로테이션과 압축을 구현한 점은 프로덕션 레벨의 훌륭한 구현입니다.
### 2.3 성능 및 리소스
* **IO Bound 처리**: `ThreadPoolExecutor`를 사용한 병렬 처리는 네트워크 요청(API call)이 주된 작업인 봇 특성상 적절합니다.
* **폴링 루프 (Polling Loop)**: `main.py``while` 루프와 `time.sleep` 방식은 단순하지만 효과적입니다. 다만, 루프 내 작업 시간이 길어질 경우 주기가 밀리는(Drift) 현상을 `wait_seconds = max(10, interval_seconds - elapsed)` 로직으로 잘 보정하고 있습니다.
---
## 3. 전문 트레이더 관점 분석 (Trading Logic Review)
### 3.1 진입 및 청산 로직 (Signals)
* **전략 건전성 (Standard)**: MACD, SMA, ADX 조합은 전형적인 추세 추종 전략입니다.
* **MACD**: 추세의 방향과 모멘텀 파악
* **SMA (5/200)**: 골든크로스/데드크로스를 통한 장기/단기 추세 확인
* **ADX**: 추세의 강도 확인 (횡보장 필터링)
* *평가*: 기본기에 충실한 논리입니다. 다만, 4시간봉(`4h`)을 주로 사용하는 것으로 보아 스윙 트레이딩 성향이 강한데, 이는 노이즈를 줄이는 데 효과적입니다.
* **복합 매도 로직 (Advanced)**:
* 단순 손절(-5%) 외에, **트레일링 스탑(Trailing Stop)**과 **분할 매도(Partial Profit Taking)** 로직이 구현된 점이 매우 인상적입니다.
* 특히 수익 구간별(10% 미만, 10~30%, 30% 이상)로 다른 트레일링 스탑 기준(5%, 15% 등)을 적용하는 것은 수익을 극대화하면서 리스크를 관리하는 고급 기법입니다.
### 3.2 리스크 관리 (Risk Management)
* **서킷 브레이커 (Circuit Breaker)**: API 오류 연속 발생 시 주문을 차단하는 로직(`circuit_breaker.py`)은 훌륭한 안전장치입니다.
* **최소 주문 금액 방어**: Upbit의 최소 주문 금액(5,000원) 미만 주문을 `skipped_too_small`로 방어하는 로직은 필수적이며 잘 구현되어 있습니다.
* **슬리피지(Slippage) 관리**: 시장가 주문 위주이나, 설정(`buy_price_slippage_pct`)에 따라 지정가 주문으로 전환하는 로직이 `order.py`에 존재합니다. 급락/급등 시 시장가 주문은 체결 오차가 클 수 있으므로 지정가 변환 옵션은 유용합니다.
### 3.3 주문 집행 (Execution)
* **주문 확인 파일 (Manual Confirmation)**: `confirm_{token}` 파일을 생성해야 매도가 실행되는 로직(`execute_sell_order_with_confirmation`)은 **양날의 검**입니다.
* *장점*: 봇의 오작동으로 인한 대량 매도를 물리적으로 방지합니다.
* *단점*: 급락장(Flash Crash)에서 빠른 대응(손절)을 방해하여 손실을 키울 수 있습니다. 자동매매의 본질인 '감정 배제와 신속성'을 해칠 수 있습니다.
---
## 4. 주요 문제점 및 개선 권장사항 (Findings & Recommendations)
### 🔴 Critical (심각)
1. **Race Condition in `trade_mode="auto_trade"`**:
* `src/signals.py`에서 매수 신호 발생 시 `get_upbit_balances`로 잔고를 확인하고 `execute_buy_order`를 실행합니다. 그러나 멀티 스레드(`max_threads > 1`) 환경에서 여러 심볼이 동시에 매수 신호를 보내면, **서로 같은 KRW 잔고를 바라보고 동시에 주문을 넣어 잔고 부족 오류**가 발생할 수 있습니다.
* **개선안**: `execute_buy_order` 진입 시 KRW 잔고 사용에 대한 전역 Lock(또는 Semaphore)을 걸거나, 할당 가능한 예산을 미리 배분해야 합니다.
### 🟡 High (중요)
2. **보유 상태(Sync)의 불일치 위험**:
* `process_symbols_and_holdings` 함수에서 `fetch_holdings_from_upbit`로 Upbit 잔고를 가져와 로컬 파일(`holdings.json`)을 덮어씁니다.
* 이때 로컬에서 계산된 `max_price`(트레일링 스탑의 기준점)가 Upbit에서 가져온 데이터에는 없으므로, 로직 상 `fetch` 함수가 기존 로컬 파일의 `max_price`를 읽어서 보존하려 노력(`src/holdings.py:376`)합니다.
* 하지만 이 과정이 복잡하여, 만약 API 장애나 파일 읽기 오류 등 예외 상황에서 **`max_price`가 초기화(현재가 또는 매수가)되어버릴 위험**이 있습니다. 이는 트레일링 스탑 로직을 무력화시킬 수 있습니다.
* **개선안**: `max_price` 등의 봇 전용 상태값은 별도 DB(SQLite 등)나 별도 파일로 분리하여 관리하거나, 병합 로직에 대한 강력한 단위 테스트가 필요합니다.
3. **파일 기반 주문 확인 (Confirmation via File)**:
* 위에서 언급했듯, 빠른 손절이 필요한 상황에서 파일 생성 방식은 대응이 느립니다.
* **개선안**: 텔레그램 버튼(Inline Keyboard)을 이용한 승인 방식을 도입하거나, 손절(Stop Loss)에 한해서는 **확인 없이 즉시 실행**하도록 예외를 두는 것이 안전합니다.
### 🟢 Medium/Low (참고)
4. **하드코딩된 전략 파라미터**:
* MACD(12, 26, 9) 등의 상수가 코드 내 기본값으로 박혀 있거나 `config`에서 불러오지만, 전략을 유연하게 변경하기 어렵습니다.
* **개선안**: 전략을 클래스화(`Strategy` 패턴)하여 config에서 전략 이름을 선택하고 파라미터를 통째로 주입받는 구조로 발전시키면 좋습니다.
5. **테스트 커버리지**:
* `test_order.py` 외에 `signals.py`의 복잡한 매도 조건 로직에 대한 단위 테스트가 부족해 보입니다. (예: 수익률 10.1% 찍고 9.9%로 떨어지면 파는가? 등의 경계값 테스트)
* **개선안**: `pytest`를 활용하여 시나리오별 매도 신호 발생 여부를 검증하는 테스트 케이스를 추가하세요.
## 5. 결론 (Conclusion)
`AutoCoinTrader`는 **상당히 완성도 높은 개인용 트레이딩 봇**입니다. 특히 로깅, 설정 관리, 안전장치(서킷브레이커, 드라이런) 등의 엔지니어링 품질이 뛰어납니다.
트레이더 입장에서 가장 우려되는 점은 **'파일 기반 승인 절차'로 인한 손절 지연**과 **멀티 스레드 매수 시 KRW 잔고 경쟁** 문제입니다. 이 두 가지만 해결된다면 실전 운용에 무리가 없을 것으로 판단됩니다.
**추천 우선순위:**
1. KRW 잔고 동시 접근 방어 로직 추가
2. 손절(Stop Loss) 조건 발동 시에는 '사용자 승인'을 건너뛰고 즉시 매도하도록 옵션 추가