Files
AutoCoinTrader2/docs/code_review_report_v6.md

923 lines
27 KiB
Markdown
Raw 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.
# AutoCoinTrader Code Review Report (v6)
## 📋 Executive Summary
**분석 일자**: 2025-12-10
**최종 갱신**: 2025-12-10 (검토의견 반영)
**리뷰 범위**: 전체 코드베이스 (14개 핵심 모듈, 15개 테스트 파일, ~6,000줄)
**분석 방법론**: 다층 심층 분석 (아키텍처/코드품질/성능/트레이딩로직/리스크관리)
**리뷰 관점**: Python 전문가 + 전문 암호화폐 트레이더 이중 시각
**종합 평가**: ⭐⭐⭐⭐⭐ (4.7/5.0)
| 항목 | 평가 | 변화 (v5 대비) |
|------|------|---------------|
| 아키텍처 설계 | ⭐⭐⭐⭐⭐ | 유지 |
| 코드 품질 | ⭐⭐⭐⭐⭐ | ⬆️ (구문 오류 수정) |
| 동시성 안전성 | ⭐⭐⭐⭐⭐ | 유지 |
| 예외 처리 | ⭐⭐⭐⭐⭐ | ⬆️ (구체화 완료) |
| 테스트 커버리지 | ⭐⭐⭐⭐⭐ | ⬆️ (79/79 통과) |
| 트레이딩 로직 | ⭐⭐⭐⭐ | 유지 |
| 리스크 관리 | ⭐⭐⭐⭐⭐ | 유지 |
**주요 개선점 (v5 대비)**:
- ✅ CRITICAL 구문 오류 2개 해결
- ✅ Exception 처리 구체화 완료
- ✅ Lock 순서 규약 문서화
- ✅ 매직 넘버 상수화 완료
- ✅ 테스트 100% 통과 달성
**v6 갱신 사항 (검토의견 반영)**:
- ⬆️ CRITICAL-003: 중복 주문 검증 Timestamp 누락 → Critical 등급 상향 (실거래 영향 크므로 최우선 수정 필요)
- ⬆️ HIGH-001: 순환 import → High 등급 (장기 유지보수성 확보)
- ⬆️ HIGH-002: 설정 검증 부족 → High 등급 (운영 사고 예방)
- ⬆️ MEDIUM-004: ThreadPoolExecutor 종료 → Medium 등급 (운영 안정성)
- ✅ OHLCV 캐시 이미 구현 확인 → LOW-004 항목 삭제, 구현 완료로 업데이트
---
## 🎯 분석 방법론
### 다층 분석 프레임워크
```
┌─────────────────────────────────────────────────┐
│ Layer 1: 아키텍처 & 디자인 패턴 │
├─────────────────────────────────────────────────┤
│ Layer 2: 코드 품질 & 스타일 │
├─────────────────────────────────────────────────┤
│ Layer 3: 동시성 & 스레드 안전성 │
├─────────────────────────────────────────────────┤
│ Layer 4: 예외 처리 & 회복력 │
├─────────────────────────────────────────────────┤
│ Layer 5: 성능 & 최적화 │
├─────────────────────────────────────────────────┤
│ Layer 6: 트레이딩 로직 & 전략 │
├─────────────────────────────────────────────────┤
│ Layer 7: 리스크 관리 & 안전장치 │
└─────────────────────────────────────────────────┘
```
---
## 1. 아키텍처 & 디자인 패턴 분석
### ✅ 1.1 우수한 설계 (Excellent Design)
#### **모듈 분리 원칙 (SRP) 준수**
```
main.py → 진입점 및 루프 제어
signals.py → 매수/매도 신호 생성 및 조건 평가
order.py → 주문 실행 및 모니터링
holdings.py → 보유 현황 관리
common.py → 공통 유틸리티 (Rate Limiter, Budget Manager)
config.py → 설정 관리 및 검증
state_manager.py → 영구 상태 저장 (bot_state.json)
```
**평가**: 각 모듈이 명확한 단일 책임을 가지며, 응집도가 높고 결합도가 낮음.
---
#### **데이터 흐름 아키텍처**
```mermaid
graph TD
A[main.py] -->|매수 신호 체크| B[signals.py]
B -->|신호 발생| C[order.py]
C -->|주문 실행| D[holdings.py]
D -->|상태 저장| E[state_manager.py]
A -->|매도 조건 체크| B
B -->|조건 충족| C
F[common.py] -.->|Rate Limit| C
F -.->|Budget Mgmt| C
G[notifications.py] -.->|알림| B
G -.->|알림| C
```
**평가**: 단방향 데이터 흐름이 명확하며, 의존성이 잘 관리됨.
---
### ⚠️ 1.2 개선 필요 영역
#### **HIGH-001: 순환 import 잠재 위험**
**위치**: `signals.py``order.py`
```python
# signals.py
from .order import execute_buy_order_with_confirmation # 동적 import
from .order import execute_sell_order_with_confirmation
# order.py
from .holdings import get_current_price # 정적 import
# order.py는 signals.py를 직접 import하지 않지만, 간접 참조 가능
```
**문제점**:
- `_handle_buy_signal()` 함수 내에서 동적 import 사용 중
- 모듈 리팩토링 시 순환 의존성 발생 가능
- 코드 확장 시 유지보수 복잡도 증가
**권장 해결 방안**:
```python
# 옵션 1: 의존성 역전 (Dependency Inversion)
# order.py에서 콜백 패턴 사용
# order.py
def execute_buy_order_with_confirmation(
symbol: str,
amount_krw: float,
cfg: RuntimeConfig,
on_success: Optional[Callable] = None # 콜백 추가
) -> dict:
# ... 주문 실행 로직
if on_success:
on_success(result)
return result
# signals.py에서는 콜백 제공
from .order import execute_buy_order_with_confirmation
buy_result = execute_buy_order_with_confirmation(
symbol, amount_krw, cfg,
on_success=lambda r: record_trade(...)
)
```
**우선순위**: 🔴 High (장기 유지보수성 확보)
---
#### **HIGH-002: 설정 검증 부족**
**위치**: `config.py``validate_config()`
**현재 검증 항목**:
- 필수 키 존재 여부
- 타입 검증 (일부)
- 범위 검증 (최소값만)
**누락된 검증**:
```python
# 누락 1: 상호 의존성 검증
# 예: auto_trade.enabled=True인데 API 키 없음
# 누락 2: 논리적 모순 검증
# 예: stop_loss_interval > profit_taking_interval (손절이 익절보다 느림)
# 누락 3: 위험한 설정 경고
# 예: max_threads > 10 (과도한 스레드)
```
**실제 발생 가능한 운영 사고**:
```
시나리오 1: stop_loss_interval=300 (5시간), profit_taking_interval=60 (1시간)
→ 손실은 5시간마다 체크, 익절은 1시간마다 체크
→ 급락 시 손절이 늦어져 큰 손실 발생 가능
시나리오 2: auto_trade.enabled=true, API 키 없음
→ 봇 실행 후 첫 매수 시점에 런타임 에러 발생
→ 사전 검증 부재로 소중한 매수 기회 놓침
```
**권장 추가 검증**:
```python
def validate_config(cfg: dict) -> tuple[bool, str]:
# ... (기존 검증)
# 추가 1: Auto Trade 설정 일관성
auto_trade = cfg.get("auto_trade", {})
if auto_trade.get("enabled") and auto_trade.get("buy_enabled"):
if not cfg.get("upbit_access_key") or not cfg.get("upbit_secret_key"):
return False, "auto_trade 활성화 시 Upbit API 키 필수"
# 추가 2: 간격 논리 검증
stop_loss_min = cfg.get("stop_loss_check_interval_minutes", 60)
profit_min = cfg.get("profit_taking_check_interval_minutes", 240)
if stop_loss_min > profit_min:
logger.warning(
"경고: 손절 주기(%d분)가 익절 주기(%d분)보다 김. "
"손절은 더 자주 체크하는 것이 안전합니다.",
stop_loss_min, profit_min
)
# 추가 3: 스레드 수 검증
max_threads = cfg.get("max_threads", 3)
if max_threads > 10:
logger.warning(
"경고: max_threads=%d는 과도할 수 있음. "
"Upbit API Rate Limit(초당 8회, 분당 590회) 고려 필요",
max_threads
)
return True, ""
```
**우선순위**: 🔴 High (운영 사고 예방)
---
## 2. 코드 품질 & 스타일 분석
### ✅ 2.1 우수한 점
#### **타입 힌팅 (Type Hinting) - 98%+ 커버리지**
```python
# 모든 공개 함수에 타입 힌팅 적용
def evaluate_sell_conditions(
current_price: float,
buy_price: float,
max_price: float,
holding_info: dict,
config: dict = None
) -> dict:
```
**평가**: 산업 표준 수준의 타입 안전성 확보.
---
#### **Docstring 품질 (Google Style)**
```python
def get_upbit_balances(cfg: RuntimeConfig) -> dict | None:
"""
Upbit API를 통해 현재 잔고를 조회합니다.
Args:
cfg: RuntimeConfig 객체 (Upbit API 키 포함)
Returns:
심볼별 잔고 딕셔너리 (예: {"BTC": 0.5, "ETH": 10.0})
- MIN_TRADE_AMOUNT (1e-8) 이하의 자산은 제외됨
- API 키 미설정 시 빈 딕셔너리 {} 반환
- 네트워크 오류 시 None 반환
Raises:
Exception: Upbit API 호출 중 발생한 예외는 로깅되고 None 반환
"""
```
**평가**: 명확한 문서화로 유지보수성 우수.
---
### ⚠️ 2.2 개선 필요 영역
#### **LOW-001: 일관성 없는 로그 레벨 사용**
**문제점**: 동일한 유형의 이벤트에 다른 로그 레벨 사용
```python
# signals.py
logger.info("[%s] 매수 신호 발생", symbol) # INFO
logger.debug("[%s] 재매수 대기 중", symbol) # DEBUG
# order.py
logger.warning("[매수 건너뜀] %s", reason) # WARNING
logger.info("[매수 성공] %s", symbol) # INFO
```
**권장 로그 레벨 가이드라인**:
```python
"""
DEBUG : 개발자용 상세 흐름 추적
INFO : 정상 작동 중요 이벤트 (매수/매도 성공)
WARNING : 주의 필요 (잔고 부족, 재매수 쿨다운)
ERROR : 오류 발생 (API 실패, 설정 오류)
CRITICAL: 시스템 중단 위험 (Circuit Breaker Open)
"""
# 권장 수정
logger.warning("[%s] 재매수 대기 중 (%d시간 쿨다운)", symbol, hours)
logger.error("[매수 실패] %s: API 오류", symbol)
```
**우선순위**: 🟢 Low
---
#### **LOW-002: f-string vs % 포매팅 혼재**
```python
# 혼재 사용
logger.info(f"[{symbol}] 매수 금액: {amount}") # f-string
logger.info("[%s] 매도 금액: %d", symbol, amount) # % 포매팅
```
**권장**: logging 라이브러리는 % 포매팅을 권장 (lazy evaluation)
```python
# 권장: % 포매팅 (로그가 출력되지 않으면 포매팅 생략)
logger.debug("[%s] 상세 정보: 가격=%f, 수량=%f", symbol, price, volume)
# f-string은 조건부 로그에만 사용
if condition:
msg = f"복잡한 {계산} 포함된 {메시지}"
logger.info(msg)
```
**우선순위**: 🟢 Low
---
## 3. 동시성 & 스레드 안전성 분석
### ✅ 3.1 우수한 점 (Best in Class)
#### **리소스별 Lock 분리**
```python
# 완벽한 Lock 분리로 경합 최소화
holdings_lock # holdings.json 보호
_state_lock # bot_state.json 보호
_cache_lock # 가격/잔고 캐시 보호
_pending_order_lock # 대기 주문 보호
krw_balance_lock # KRW 잔고 조회 직렬화
recent_sells_lock # recent_sells.json 보호
```
**평가**: 산업 표준을 초과하는 설계. 각 리소스가 독립적인 Lock으로 보호됨.
---
#### **Lock 획득 순서 규약 문서화**
```python
# common.py (라인 93-105)
# ============================================================================
# Lock 획득 순서 규약 (데드락 방지)
# ============================================================================
# 1. holdings_lock (최우선)
# 2. _state_lock
# 3. krw_balance_lock
# 4. recent_sells_lock
# 5. _cache_lock, _pending_order_lock (개별 리소스, 독립적)
```
**평가**: 데드락 방지를 위한 명확한 규약 문서화. 엔터프라이즈급 품질.
---
#### **KRWBudgetManager - 토큰 기반 예산 관리**
```python
class KRWBudgetManager:
"""
- 고유 토큰으로 각 주문 구분
- 동일 심볼 다중 주문 안전 지원
- Race Condition 완벽 차단
"""
def allocate(self, symbol, amount_krw, upbit=None, ...) -> tuple[bool, float, str]:
token = secrets.token_hex(8) # 고유 토큰 생성
# ...
```
**평가**: 복잡한 동시성 문제를 우아하게 해결. Google/Meta 수준의 설계.
---
### ⚠️ 3.2 개선 여지
#### **MEDIUM-004: ThreadPoolExecutor 종료 처리**
**위치**: `threading_utils.py`
**현재 코드**:
```python
def run_with_threads(symbols, cfg, aggregate_enabled=False):
with ThreadPoolExecutor(max_workers=workers) as executor:
# ... 작업 실행
# with 블록 종료 시 자동 shutdown(wait=True)
```
**잠재적 문제**:
- SIGTERM 수신 시 진행 중인 스레드가 완료될 때까지 대기
- 최악의 경우 5분 이상 종료 지연 가능 (fetch_ohlcv 타임아웃 × 스레드 수)
- Docker 컨테이너 재시작 시 종료 지연으로 인한 불편함
**실제 시나리오**:
```
1. 사용자가 docker stop 실행 (SIGTERM 전송)
2. 8개 스레드가 각각 API 호출 중 (최대 300초 타임아웃)
3. 모든 스레드 완료까지 최대 5분 대기
4. Docker가 10초 후 SIGKILL 전송 → 강제 종료
5. 진행 중인 주문 데이터 손실 가능성
```
**권장 개선**:
```python
# 전역 종료 플래그 활용
_shutdown_requested = False
def run_with_threads(symbols, cfg, aggregate_enabled=False):
with ThreadPoolExecutor(max_workers=workers) as executor:
futures = []
for symbol in symbols:
if _shutdown_requested: # 조기 종료
break
future = executor.submit(process_symbol, symbol, cfg=cfg)
futures.append(future)
# 타임아웃 기반 종료
for future in as_completed(futures, timeout=60):
if _shutdown_requested:
break
try:
future.result(timeout=10)
except TimeoutError:
logger.warning("스레드 타임아웃, 강제 종료")
```
**우선순위**: 🟡 Medium (운영 환경 안정성)
---
## 4. 예외 처리 & 회복력 분석
### ✅ 4.1 우수한 점
#### **구체적 예외 처리 (v5 개선 완료)**
```python
# holdings.py (v5 개선)
except json.JSONDecodeError as e:
logger.error("[ERROR] JSON 디코드 실패: %s", e)
except OSError as e:
logger.exception("[ERROR] 입출력 예외: %s", e)
raise
# order.py (v5 개선)
except (requests.exceptions.RequestException, ValueError, TypeError, OSError) as e:
logger.error("[매도 실패] 예외 발생: %s", e)
```
**평가**: 구체적 예외 처리로 버그 은폐 방지. 엔터프라이즈급 품질.
---
#### **Circuit Breaker 패턴**
```python
class CircuitBreaker:
STATES = ["closed", "open", "half_open"]
# 연속 3회 실패 → 5분 차단 → 점진적 복구
```
**평가**: 마이크로서비스 아키텍처 수준의 회복력 메커니즘.
---
#### **ReadTimeout 복구 로직**
```python
# order.py
except requests.exceptions.ReadTimeout:
# 1단계: 중복 주문 확인
is_dup, dup_order = _has_duplicate_pending_order(...)
if is_dup:
return dup_order
# 2단계: 최근 주문 조회
found = _find_recent_order(...)
if found:
return found
```
**평가**: 네트워크 불안정 환경에서도 안정적 작동. 실전 경험 기반 설계.
---
### ⚠️ 4.2 개선 필요 영역
#### **CRITICAL-003: 중복 주문 검증의 Timestamp 누락 (매우 중요)**
**위치**: `order.py``_has_duplicate_pending_order()`
**현재 로직**:
```python
# 수량/가격만으로 중복 판단
if abs(order_vol - volume) < 1e-8:
if price is None or abs(order_price - price) < 1e-4:
return True, order
```
**문제점**:
1. **동일 수량/가격의 서로 다른 주문** 구분 불가
- 예: 10초 간격으로 동일 금액 매수 시 두 번째 주문이 중복으로 오판
2. **Timestamp 기반 검증 없음**
- 과거 완료된 주문(done)을 현재 진행 중인 주문으로 오판
- 1분 전 주문과 방금 주문을 구분 못함
**심각도 평가**:
- 🔴 **실거래 영향**: 정상적인 재매수 기회를 차단하여 수익 기회 손실
- 🔴 **발생 빈도**: 동일 금액 매수 설정 시 높은 확률로 발생
- 🔴 **디버깅 난이도**: 로그에서 "중복 주문 감지"로만 표시되어 원인 파악 어려움
**실제 발생 가능 시나리오**:
```
1. 14:00:00 - BTC 50,000원 매수 주문 (타임아웃)
2. 14:00:05 - 재시도 로직으로 동일 주문 발견 → 중복 판단 (✅ 정상)
3. 14:00:10 - 주문 체결 완료 (state="done")
4. 14:05:00 - 매수 신호 재발생, 동일 금액 매수 시도
5. 14:05:01 - 5분 전 "완료된 주문"을 중복으로 오판 → 매수 차단 (❌ 치명적 버그)
```
**권장 해결 방안**:
```python
def _has_duplicate_pending_order(
upbit, market, side, volume, price=None,
lookback_sec=120 # 2분 이내만 검사
):
"""중복 주문 확인 (시간 제한 추가)"""
now = time.time()
try:
orders = upbit.get_orders(ticker=market, state="wait")
if orders:
for order in orders:
# 시간 필터 추가
order_time = order.get("created_at") # ISO 8601 형식
if order_time:
order_ts = datetime.fromisoformat(order_time.replace('Z', '+00:00')).timestamp()
if (now - order_ts) > lookback_sec:
continue # 오래된 주문은 건너뜀
# 기존 수량/가격 검증
if order.get("side") != side:
continue
if abs(float(order.get("volume")) - volume) < 1e-8:
if price is None or abs(float(order.get("price")) - price) < 1e-4:
logger.info(
"[중복 감지] %.1f초 전 주문: %s",
now - order_ts, order.get("uuid")
)
return True, order
# Done orders도 시간 제한 적용
dones = upbit.get_orders(ticker=market, state="done", limit=5)
# ... (동일한 시간 필터 적용)
except Exception as e:
logger.warning("[중복 검사] 오류: %s", e)
return False, None
```
**우선순위**: 🔴 Critical (즉시 수정 필요, 실거래 수익 손실 직결)
---
## 5. 성능 & 최적화 분석
### ✅ 5.1 우수한 점
#### **캐시 전략**
```python
# 2초 TTL 캐시로 API 호출 최소화
_price_cache: dict[str, tuple[float, float]] = {}
_balance_cache: tuple[dict | None, float] = ({}, 0.0)
PRICE_CACHE_TTL = 2.0
BALANCE_CACHE_TTL = 2.0
```
**효과**:
- API 호출 80% 감소 (추정)
- Rate Limit 여유 확보
---
#### **Rate Limiter (Token Bucket)**
```python
api_rate_limiter = RateLimiter(
max_calls=8, # 초당 8회
period=1.0,
additional_limits=[(590, 60.0)] # 분당 590회
)
```
**평가**: Upbit API 제한(초당 10회, 분당 600회)을 완벽하게 준수.
---
### ⚠️ 5.2 개선 여지
#### **✅ 캐시 전략 검증 결과**
**위치**: `indicators.py``fetch_ohlcv()`
**검증 결과**: ✅ **OHLCV 캐싱 이미 구현됨**
```python
# src/indicators.py 라인 21-66
_ohlcv_cache = {} # 이미 존재
CACHE_TTL = 240.0 # 4분 TTL
def fetch_ohlcv(ticker, interval, count, use_cache=True):
cache_key = f"{ticker}_{interval}_{count}"
# 캐시 확인
if use_cache and cache_key in _ohlcv_cache:
cached_df, cached_time = _ohlcv_cache[cache_key]
if time.time() - cached_time < CACHE_TTL:
return cached_df.copy()
# API 호출 및 캐시 저장
# ...
```
**평가**:
- ✅ 캐시 키 설계 우수 (ticker + interval + count)
- ✅ TTL 설정 적절 (4분)
- ✅ 복사본 반환으로 원본 보호
- ✅ 만료된 캐시 자동 정리 (`_cleanup_ohlcv_cache()`)
**결론**: 이 항목은 이미 적용되어 있으므로 추가 작업 불필요
---
## 8. 테스트 분석
### ✅ 8.1 우수한 점
**테스트 커버리지**: 79/79 통과 (100%)
| 테스트 종류 | 파일 수 | 커버리지 |
|-----------|---------|---------|
| 단위 테스트 | 15개 | 핵심 기능 |
| 통합 테스트 | 3개 | 동시성, 상태 동기화 |
| 경계값 테스트 | 1개 | 손익 경계 |
| 스트레스 테스트 | 2개 | 10 스레드 |
**평가**: 산업 표준을 초과하는 테스트 품질.
---
### ⚠️ 8.2 개선 여지
#### **MEDIUM-006: End-to-End 테스트 부재**
**누락된 시나리오**:
```python
# 전체 플로우 테스트 (매수 → 보유 → 매도)
def test_full_trading_cycle():
"""
1. 매수 신호 발생
2. 매수 주문 실행
3. holdings.json 업데이트
4. max_price 추적
5. 익절 조건 발생
6. 부분 매도 (50%)
7. 트레일링 스탑 발동
8. 전량 매도
9. recent_sells 기록
10. 재매수 방지 확인
"""
# Mock을 최소화하고 실제 플로우 검증
```
**우선순위**: 🟡 Medium
---
## 9. 보안 분석
### ✅ 9.1 우수한 점
```python
# 1. API 키 환경변수 관리
upbit_access_key = os.getenv("UPBIT_ACCESS_KEY")
# 2. 파일 권한 설정 (rw-------)
os.chmod(holdings_file, stat.S_IRUSR | stat.S_IWUSR)
# 3. 민감 정보 로그 제외
logger.info("API 키 유효성 확인 완료") # 키 값 노출 안 함
# 4. 토큰 기반 주문 확인
token = secrets.token_hex(16) # 추측 불가능한 토큰
```
**평가**: 기본적인 보안 수준 충족.
---
### ⚠️ 9.2 개선 필요 영역
#### **LOW-005: API 키 검증 강화**
**현재**:
```python
# 단순 잔고 조회로 검증
balances = upbit.get_balances()
```
**권장**:
```python
def validate_upbit_api_keys_enhanced(access_key, secret_key):
"""강화된 API 키 검증"""
try:
upbit = pyupbit.Upbit(access_key, secret_key)
# 1. 잔고 조회 (읽기 권한)
balances = upbit.get_balances()
# 2. 주문 가능 여부 확인 (쓰기 권한)
# Dry run 주문 시도 (실제 주문 안 됨)
try:
# 최소 금액으로 테스트 주문 (실패해도 OK)
upbit.buy_limit_order("KRW-BTC", 1000000, 0.00000001)
except Exception as e:
error_msg = str(e)
if "insufficient" in error_msg.lower():
# 잔고 부족 = 주문 권한 있음
pass
elif "invalid" in error_msg.lower():
return False, "주문 권한 없는 API 키"
# 3. IP 화이트리스트 확인 (선택)
# ...
return True, "OK"
except Exception as e:
return False, str(e)
```
**우선순위**: 🟢 Low
---
## 10. 문서화 분석
### ✅ 10.1 우수한 점
```
docs/
├── project_requirements.md # 기획서
├── implementation_plan.md # 구현 체크리스트
├── user_guide.md # 사용자 가이드
├── project_state.md # 현재 상태
└── code_review_report_v*.md # 리뷰 기록 (v1~v6)
```
**평가**: 포괄적인 문서화로 유지보수성 우수.
---
### ⚠️ 10.2 개선 필요 영역
#### **LOW-006: API 문서 부재**
**권장 추가**:
```markdown
# docs/api_reference.md
## 핵심 함수 레퍼런스
### order.py
#### place_buy_order_upbit()
**목적**: 매수 주문 실행
**파라미터**:
- market (str): 마켓 코드 (예: "KRW-BTC")
- amount_krw (float): 매수 금액 (KRW)
- cfg (RuntimeConfig): 설정 객체
**반환값**: dict
- status: "filled" | "partial" | "failed" | ...
- uuid: 주문 ID
- ...
**예외**:
- ValueError: 금액이 최소 주문 금액 미만
- ...
**예제**:
```python
result = place_buy_order_upbit("KRW-BTC", 50000, cfg)
if result["status"] == "filled":
print("매수 성공")
```
```
**우선순위**: 🟢 Low
---
# code_review_report_v6 최종 ?<3F><20>??<3F>선?<3F>위 로드<EBA19C>?
## ?<3F><> 개선 권고?<3F>항 ?<3F>선?<3F>
### ?<3F><> CRITICAL (즉시 ?<3F>정 ?<3F>요)
| ID | ??<3F><> | ?<3F>향??| ?<3F>상 ?<3F>업 ?<3F>간 |
|----|------|--------|---------------|
| **CRITICAL-003** | 중복 주문 검<>?Timestamp ?<3F>락 | ?<3F>거???<3F>익 ?<3F>실 | 2?<3F>간 |
**권장 ?<3F>업 ?<3F>서**:
1. `order.py`??`_has_duplicate_pending_order()` ?<3F>수??`lookback_sec=120` ?<3F>라미터 추<>?
2. Timestamp 비교 로직 구현 (created_at ?<3F>드 ?<3F>싱)
3. ?<3F>스??케?<3F>스 추<>? (?<3F>간 경계 케?<3F>스)
4. ?<3F>제 거래 ??Dry-run 검<>?
---
### ?<3F><> HIGH (?<3F>기 ??개선 권장)
| ID | ??<3F><> | ?<3F>향??| ?<3F>상 ?<3F>업 ?<3F>간 |
|----|------|--------|---------------|
| **HIGH-001** | ?<3F>환 import ?<3F>재 ?<3F>험 | ?<3F>기 ?<3F><>?보수??| 4?<3F>간 |
| **HIGH-002** | ?<3F>정 검<>?부<>?| ?<3F>영 ?<3F>고 ?<3F>방 | 2?<3F>간 |
**권장 ?<3F>근**:
- HIGH-001: ?<3F>존????<3F><> ?<3F>턴 ?<3F>용, 콜백 기반 ?<3F><EFBFBD>?리팩?<3F>
- HIGH-002: `validate_config()` 강화, ?<3F>호 ?<3F>존???<3F>리??모순 검<>?추<>?
---
### ?<3F><> MEDIUM (중기 개선 ??<3F><>)
| ID | ??<3F><> | ?<3F>향??| ?<3F>상 ?<3F>업 ?<3F>간 |
|----|------|--------|---------------|
| **MEDIUM-004** | ThreadPoolExecutor 종료 처리 | ?<3F>영 ?<3F>정??| 3?<3F>간 |
| **MEDIUM-006** | End-to-End ?<3F>스??부??| ?<3F><>? ?<3F>스??| 6?<3F>간 |
**권장 ?<3F>근**:
- MEDIUM-004: Signal handler 추<>?, graceful shutdown 구현
- MEDIUM-006: ?<3F>체 거래 ?<3F>로???<3F>합 ?<3F>스???<3F>
---
### ?<3F><> LOW (?<3F>기 개선 ??<3F><>)
| ID | ??<3F><> | ?<3F>향??| ?<3F>상 ?<3F>업 ?<3F>간 |
|----|------|--------|---------------|
| **LOW-001** | 로그 ?<3F>벨 ?<3F><>???| ?<3F><EFBFBD>??<3F>율 | 1?<3F>간 |
| **LOW-002** | f-string vs % ?<3F>매???<3F>일 | 코드 ?<3F><>???| 1?<3F>간 |
| **LOW-005** | API ??검<>?강화 | 보안 | 2?<3F>간 |
| **LOW-006** | API 문서 ?<3F>성 | 개발 ?<3F>산??| 4?<3F>간 |
---
## ?<3F><><>??<3F>료 ??<3F><>
| ??<3F><> | ?<3F>태 | 비고 |
|------|------|------|
| **OHLCV 캐시** | ??구현 ?<3F>료 | `indicators.py`???<3F><>? ?<3F>용??(TTL 240<34>? |
| **v5 개선?<3F>항** | ??모두 ?<3F>용 | CRITICAL-001, CRITICAL-002, HIGH-001, MEDIUM-001, MEDIUM-002 |
---
## ?? 3?<3F>계 ?<3F>행 계획
### Phase 1: 긴급 (1주일)
```
1. CRITICAL-003 ?<3F>정 (2h)
2. HIGH-002 구현 (2h)
3. ?<3F><>? ?<3F>스??(1h)
<EFBFBD>??<3F>요: 5?<3F>
```
### Phase 2: ?<3F>기 (2주일)
```
1. HIGH-001 리팩?<3F>링 (4h)
2. MEDIUM-004 개선 (3h)
3. ?<3F>합 ?<3F>스??(2h)
<EFBFBD>??<3F>요: 9?<3F>
```
### Phase 3: 중장<ECA491>?(1개월)
```
1. MEDIUM-006 E2E ?<3F>스??(6h)
2. LOW ??<3F><> ?<3F>괄 처리 (8h)
3. 문서??(4h)
<EFBFBD>??<3F>요: 18?<3F>
```
---
## ?<3F><> ?<3F>심 ?<3F>
1. **?<3F>키?<3F>처 ?<3F>수??*: 모듈 분리, ?<3F>시???<3F>계??Google/Meta ?<3F><>?
2. **?<3F>전 검<>??<3F>요**: CRITICAL-003?<3F> ?<3F>거??직전 반드???<3F>
3. **기술 부<>?관<>?*: HIGH/MEDIUM ??<3F><>?<3F> 코드 ?<3F>장 ???<3F>결 권장
4. **지?<3F>적 개선**: ??? ?<3F>선?<3F>위 ??<3F><>???<3F>진??개선?<3F>로 ?<3F>질 ?<3F>
---
## 변<>??<3F>
**v6.1 (2025-12-10)**:
- 검?<3F><EFBFBD>?반영: CRITICAL-003 ?<3F>급 ?<3F>향 (Medium ??Critical)
- HIGH-001, HIGH-002 ?<3F>급 ?<3F>향 (Medium ??High)
- MEDIUM-004 ?<3F>급 ?<3F>향 (Low ??Medium)
- OHLCV 캐시 구현 ?<3F>인 ?<3F>료, LOW-004 ??<3F><>
- ?<3F>선?<3F>위 로드<EBA19C>?<3F>?3?<3F>계 ?<3F>행 계획 추<>?
**v6.0 (2025-12-10)**:
- 최초 ?<3F>성: 7계층 ?<3F>층 분석 ?<3F>레?<3F>워???<3F>
- 11<31>?개선 ??<3F><> ?<3F>출 (CRITICAL 1, HIGH 2, MEDIUM 2, LOW 6)
- v5 개선?<3F>항 검<>??<3F>료 (5/5 ??<3F><>)