diff --git a/CLAUDE.md b/CLAUDE.md index f980a48..c8fd08b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -22,7 +22,7 @@ 백엔드의 핵심 로직은 `backend/app/` 안에 집약되어 있다. API 엔드포인트는 `api/endpoints/` 아래에 기능별로 분리되어 있으며, 주요 파일로는 시세 조회(`market_data.py`), 포트폴리오 관리 및 ATR 기반 청산(`portfolio.py`), 주문·체결 처리(`trades.py`), 규칙 기반 추천과 자동매매(`recommendations.py`), 매매 규칙 CRUD(`trading_rules.py`), 리스크 관리(`risk_management.py`), ML 앙상블 엔드포인트(`ml_ensemble.py`), 모니터링(`monitoring.py`)이 있다. -전략 로직은 `services/` 아래에 모여 있다. RSI+볼린저 평균회귀 전략은 `mean_reversion_strategy.py`(v2)가 담당하고, 코스닥 전종목 스캐너는 `kosdaq_scanner.py`, 15분봉 단기 전략은 `short_term_strategy.py`가 각각 구현한다. 그 외에 MDD 관리(`mdd_manager.py`), 연속 손실 추적(`loss_tracker.py`), 피처 엔지니어링(`feature_engineering.py`), ML 앙상블(`ml_ensemble.py`), TensorFlow 예측(`tensorflow_predictor.py`)도 같은 디렉터리에 위치한다. +전략 로직은 `services/` 아래에 모여 있다. RSI+볼린저 평균회귀 전략은 `mean_reversion_strategy.py`(v2)가 담당하고, 코스닥 전종목 스캐너는 `kosdaq_scanner.py`, 15분봉 단기 전략은 `short_term_strategy.py`가 각각 구현한다. 그 외에 MDD 관리(`mdd_manager.py`), 연속 손실 추적(`loss_tracker.py`), 피처 엔지니어링(`feature_engineering.py`), ML 앙상블(`ml_ensemble.py`), TensorFlow 예측(`tensorflow_predictor.py`), **DB 락을 방지하는 전용 비동기 워커(`db_worker.py`)**도 같은 디렉터리에 위치한다. MCP 서버는 `mcp-server/` 아래에서 독립적으로 동작한다. `stdio_server.py`가 Claude CLI와의 stdin/stdout 통신을 처리하고, `auto_trade_claude.py`와 `trade_monitor.py`가 실제 매매 판단과 모니터링을 수행한다. @@ -38,12 +38,18 @@ MCP 서버는 `mcp-server/` 아래에서 독립적으로 동작한다. `stdio_se --- -## 4. 코딩 규칙 +## 4. 코딩 규칙 및 아키텍처 원칙 (핵심) 코드 수정 시 가장 중요한 원칙은 기존 함수·클래스의 시그니처를 변경하지 않는 것이다. 새로운 전략이나 기능을 추가할 때는 반드시 별도의 파일이나 클래스로 분리하고, 파일명에 `_v2`, `_v3` 같은 버전 접미사를 붙인다. `json.dumps`는 직접 사용하지 않는다. 코드베이스 전체에서 `_dumps()` 헬퍼 함수(`core/json_helpers.py`)를 통해 JSON을 직렬화해야 한다. 이 헬퍼는 `TOKEN_SAVE_MODE`가 활성화된 경우 자동으로 compact 포맷을 적용하여 Claude API 호출 시 토큰 소비를 줄여준다. +**[아키텍처 원칙: DB I/O와 실시간 API 처리 분리]** +DB 병목, 트랜잭션 충돌, 매매일지 누락을 방지하기 위해 **"실시간 처리/API 응답"과 "DB 영속화"를 철저히 분리**한다. +- 체결 콜백 등 실시간 스레드에서 직접 `AsyncSessionLocal()`을 열어 INSERT/UPDATE 하지 않는다. +- 데이터 삽입/갱신 작업은 `app.services.db_worker`의 `db_task_queue`에 던져서 백그라운드 워커가 순차적으로 처리하게 한다. +- 메인 스케줄러(`auto_trade_scheduler`)는 무거운 DB 조회를 최소화하고 메모리 캐시를 우선 참조해야 한다. + AI 프롬프트는 간결하게 작성한다. 필수 필드만 명시하고, JSON 예시는 최소화해야 한다. 변경 단위는 작게 유지하는 것을 원칙으로 하며, 큰 기능 변경보다 작고 검증 가능한 단위로 나누어 커밋한다. --- @@ -90,7 +96,7 @@ MDD가 -10%를 돌파하면 신규 진입을 일시 중단하고, 기존 포지 ### 청산 조건 -1차 익절은 RSI(14)가 50 이상으로 회복되거나 종가가 볼린저 중앙선을 상회하거나 수익이 2 × ATR_pct 이상일 때 발동한다. 상승장에서는 40%를 익절하고, 하락장에서는 60%를 익절한다. +1차 익절은 RSI(14)가 50 이상으로 회복되거나 종가가 볼린저 중앙선을 상회하거나 수익이 2 × ATR_pct 이상일 때 발동한다. 상승장에서는 40%를 익절하고, 하락장에서는 60% 익절한다. 2차 익절(전량 청산)은 `최고가 - 1.5 × ATR` 트레일링 스탑에 걸리거나, RSI가 65 이상으로 과열되거나, 종가가 볼린저 상단의 99% 이상에 도달할 때 이루어진다. @@ -124,8 +130,16 @@ MDD가 -10%를 돌파하면 신규 진입을 일시 중단하고, 기존 포지 코드를 수정하거나 추가할 때는 반드시 다음 원칙을 지켜야 한다. -첫째, 기존 코드의 함수·클래스 시그니처는 절대 변경하지 않는다. 새 기능은 항상 `_v2`, `_v3` 접미사가 붙은 별도 파일이나 클래스로 추가한다. 둘째, 백테스트를 거치지 않은 코드를 실전 환경에 즉시 적용해서는 안 된다. 워크포워드 테스트를 포함한 충분한 검증이 선행되어야 한다. 셋째, `json.dumps`를 직접 사용하는 코드는 작성하지 않는다. 반드시 `_dumps()` 헬퍼를 경유해야 한다. 넷째, 포지션 크기·손절가·MDD 규칙·가격 필터 등 리스크 규칙은 어떤 전략에도 예외 없이 기본 적용된다. 다섯째, SIDEWAYS 구간에서 발생한 평균회귀 신호는 코드 레벨에서 무시 처리해야 하며, 사용자에게 진입을 유도하는 응답을 해서는 안 된다. 여섯째, 15분봉 단기 전략의 자본 배분은 전체의 25%를 절대 초과할 수 없다. 일곱째, MDD -10% 돌파 시 단기 전략을 즉시 중단하는 로직이 호출 측에 존재하는지 항상 확인한다. 여덟째, 코스닥 스캐너가 종목을 선별할 때 가격 5,000원 이상 + 거래대금 상위 20% 필터가 반드시 적용되어야 한다. +첫째, 기존 코드의 함수·클래스 시그니처는 절대 변경하지 않는다. 새 기능은 항상 `_v2`, `_v3` 접미사가 붙은 별도 파일이나 클래스로 추가한다. +둘째, 백테스트를 거치지 않은 코드를 실전 환경에 즉시 적용해서는 안 된다. 워크포워드 테스트를 포함한 충분한 검증이 선행되어야 한다. +셋째, `json.dumps`를 직접 사용하는 코드는 작성하지 않는다. 반드시 `_dumps()` 헬퍼를 경유해야 한다. +넷째, 포지션 크기·손절가·MDD 규칙·가격 필터 등 리스크 규칙은 어떤 전략에도 예외 없이 기본 적용된다. +다섯째, SIDEWAYS 구간에서 발생한 평균회귀 신호는 코드 레벨에서 무시 처리해야 하며, 사용자에게 진입을 유도하는 응답을 해서는 안 된다. +여섯째, 15분봉 단기 전략의 자본 배분은 전체의 25%를 절대 초과할 수 없다. +일곱째, MDD -10% 돌파 시 단기 전략을 즉시 중단하는 로직이 호출 측에 존재하는지 항상 확인한다. +여덟째, 코스닥 스캐너가 종목을 선별할 때 가격 5,000원 이상 + 거래대금 상위 20% 필터가 반드시 적용되어야 한다. +아홉째, **실시간 처리 로직 내부에서는 DB 세션을 열어 직접 데이터를 넣거나 갱신하지 말 것. 모든 영속성 작업은 전용 비동기 큐(`db_worker.py`)를 통해 우회 처리한다.** --- -*Last updated: 2026-02-22* +*Last updated: 2026-02-24* \ No newline at end of file