# 자동 주식 매매 시스템 — Claude 컨텍스트 가이드 > **핵심 지침 (Core Directive)**: 이 문서는 시스템의 전략, 규칙 및 아키텍처를 정의합니다. 모든 코드 수정 및 분석은 이 가이드라인을 엄격하게 준수해야 합니다. --- ## 1. 프로젝트 개요 ### 1.1 기술 스택 - **백엔드**: Python 3.11, FastAPI, SQLAlchemy 2.0 (Async), PostgreSQL 15, Redis 7, RabbitMQ 3 - **프론트엔드**: React 18, TypeScript, Vite, Recharts, Lightweight Charts - **인프라**: Docker Compose, Nginx, Alembic (DB 마이그레이션) - **AI 계층**: Claude 3.5 Sonnet / Gemini 2.0 Flash (`.env`의 `AI_PROVIDER`로 전환) - **ML**: PyTorch, LightGBM, scikit-learn (앙상블 예측) - **연동 (Integration)**: 한국투자증권(KIS) REST/WebSocket API, MCP Server (stdio) ### 1.2 주요 환경 변수 (`.env`) - **AI_PROVIDER**: `gemini` 또는 `claude` - **KIS_MODE**: `virtual` (모의투자) 또는 `real` (실전투자) - **TOKEN_SAVE_MODE**: `true` (JSON을 압축하고, 차트 데이터를 30일치로 제한함) - **AUTO_TRADE_ENABLED**: 자동 매매 활성화 여부 - **US_TRADING_ENABLED**: 미국 주식 매매 활성화 여부 --- ## 2. 디렉토리 구조 ### 2.1 백엔드 (`backend/app/`) - **API**: `api/endpoints/` — 20개 엔드포인트 모듈 (portfolio, market_data, trades, day_trading, backtest 등) - **코어 (Core)**: `core/config.py` (전역 설정), `core/database.py`, `core/security.py` (API 키 인증), `core/json_helpers.py`, `core/market_schedule.py` - **모델 (Models)**: `models/models.py` — SQLAlchemy ORM (Portfolio, TradeHistory, ActiveTrade, StockAnalysis, StockBan 등) - **실시간 (Realtime)**: `realtime/websocket_client.py`, `realtime/event_handler.py` - **전략 추상화 (Strategy)**: `strategy/base_strategy.py`, `strategy/strategy_manager.py` ### 2.2 서비스 (`backend/app/services/`) - **전략 (Strategies)**: - `mean_reversion_strategy.py` — RSI+BB 평균 회귀 v2 (섹션 6) - `short_term_strategy.py` — 15분봉 단기 전략 (섹션 7.2) - `day_trading_strategy.py` — 5분봉 데이트레이딩 ORB/VWAP/RSI_BB (섹션 7.3) - `kosdaq_scanner.py` — 코스닥 스윙 스캐너 (섹션 7.1) - `us_stock_strategy.py` — 미국 주식 전략 - **데이트레이딩 모듈 (Modular)**: `daytrading/entry_service.py`, `daytrading/exit_service.py`, `daytrading/position_manager.py`, `daytrading/scheduler.py` - **스윙 모듈 (Modular)**: `swing/entry_service.py`, `swing/exit_service.py`, `swing/position_manager.py`, `swing/scheduler.py` - **매매 실행**: `trade_executor.py` — 핵심 매매 엔진 (매수/매도/체결확인/슬리피지) - **분석 (Analysis)**: `feature_engineering.py`, `ml_ensemble.py`, `tensorflow_predictor.py`, `technical_indicators.py` - **리스크**: `mdd_manager.py` (MDD 추적 + 자동 축소 실행), `loss_tracker.py` (연속 손실 ban), `correlation_filter.py` (상관관계 필터) - **아키텍처**: `db_worker.py` (비동기 DB 처리 워커, 재시도 3회) - **데이터**: `korea_investment_api.py` (KIS REST), `kis_realtime_stream.py` (KIS WebSocket), `naver_finance.py` - **유틸**: `websocket_manager.py`, `order_dispatcher.py`, `signal_types.py`, `watchlist.py` ### 2.3 MCP (`mcp-server/`) - `stdio_server.py`, `auto_trade_claude.py`, `claude_client.py`, `gemini_client.py`, `trade_monitor.py`, `risk_validator.py`, `mcp_tools.py` ### 2.4 배치 스크립트 (`backend/`) - `batch_daily_analysis.py` — 일일 분석 배치 - `batch_intraday_analysis.py` — 장중 분석 배치 - `train_ensemble.py` — ML 모델 학습 - `collect_krx_data.py` — KRX 데이터 수집 --- ## 3. 아키텍처 원칙 (필수 준수 사항) ### 3.1 관심사 분리 (Separation of Concerns) - **실시간 계층 (Real-time Layer)**: API 콜백, 웹소켓 브로드캐스트 및 메모리 캐싱을 처리합니다. **DB I/O(데이터베이스 입출력)는 절대 허용되지 않습니다.** - **영속성 계층 (Persistence Layer)**: 백그라운드 워커를 통해 DB INSERT/UPDATE 작업을 처리합니다. - **예외**: `sync_portfolio()`는 SELECT→UPDATE/DELETE→commit이 같은 트랜잭션에서 이뤄져야 하므로 API 엔드포인트 경로에서 직접 DB 접근을 허용합니다. ### 3.2 비동기 DB 워커 규칙 - **직접적인 DB 접근 금지**: API 콜백이나 실시간 스케줄러 내부에서 `AsyncSessionLocal()` 또는 `commit()`을 절대 호출하지 마십시오. - **큐(Queue) 사용**: 모든 데이터 저장(매매 내역, 분석 결과 등)은 `db_worker.py`의 `db_task_queue`로 보내야 합니다. - **워커 (Worker)**: 백그라운드 워커가 큐를 처리하고 안전한 DB 트랜잭션을 순차적으로 수행합니다. - **재시도**: 실패한 task는 최대 3회까지 지수 백오프(1→2→4초)로 재시도합니다. - **지원 task 타입**: `insert_trade_history`, `update_trade_history`, `update_trade_history_by_order_id`, `upsert_stock_analysis`, `bulk_upsert_stock_analysis`, `upsert_stock_ban`, `upsert_portfolio`, `upsert_active_trade`, `close_active_trade`, `insert_trade_journal`, `log_mcp_deny` ### 3.3 동시성 안전 - **종목별 세마포어**: `trade_executor.py`의 `_order_semaphores`로 동일 종목 동시 주문 방지. - **Redis 분산 락**: 여러 워커 프로세스간 동일 종목 동시 매도 방지. - **loss_tracker 락**: `asyncio.Lock`으로 `_tracker` 딕셔너리 보호. 동시 접근 경로에서는 `is_banned_safe()`, `record_trade_result_safe()` 사용. - **MDD 매니저 락**: `asyncio.Lock`으로 MDD 업데이트 및 축소 실행 보호. --- ## 4. 코딩 가이드라인 ### 4.1 안정성 - **기존 코드 파괴 금지 (No Breaking Changes)**: 기존 함수나 클래스의 시그니처를 절대 변경하지 마십시오. - **버전 관리**: 새로운 전략 구현 시 `_v2`, `_v3` 등의 접미사를 사용하십시오. - **안전 래퍼**: 기존 동기 API를 비동기로 확장할 때 `_safe` 접미사의 새 메서드를 추가하십시오 (예: `is_banned_safe()`). ### 4.2 최적화 - **JSON 처리**: `json.dumps` 대신 항상 `core.json_helpers._dumps()`를 사용하십시오. - **프롬프트 엔지니어링**: 토큰 사용을 최소화하고 컴팩트한 포맷을 사용하십시오. ### 4.3 보안 - **API 인증**: 쓰기/삭제 엔드포인트에는 반드시 `Depends(require_api_key)`를 적용하십시오. - **SSL 검증**: 외부 API 호출 시 `verify=True` 유지 (KIS API 포함). - **비밀키**: `.env`의 `SECRET_KEY`는 64자 이상 랜덤 문자열 사용. --- ## 5. 리스크 관리 규칙 ### 5.1 포지션 사이징 (Position Sizing) - **최대 비중**: 종목당 총 자본의 **6%** (`config.py: MAX_POSITION_SIZE = 0.06`, 백테스트 검증 반영). - **최대 보유 종목 수**: **20개** (`config.py: MAX_HOLDINGS_COUNT = 20`). - **레버리지**: 인버스/레버리지 ETF의 경우 총 자본의 최대 **20%**로 제한 (`config.py: LEVERAGE_ETF_MAX_RATIO = 0.20`). ### 5.2 손절(SL) 및 익절(TP) — 일봉/스윙 기준 - **기본 손절 (SL Base)**: -7% (안정적 종목), -10% (변동성 종목). (백테스트 검증: 기존 -6% → -7%) - **ATR 손절**: `진입가 - (2.5 * ATR)` (`config.py: ATR_STOP_MULTIPLIER = 2.5`). **기본 손절과 ATR 손절 중 타이트한(더 작은) 쪽 적용** — 코드에서 `min(stop_loss, atr_stop_pct)` 사용. - **익절 (TP)**: +2R 수익(리스크 대비 2배 수익) 도달 시 50% 분할 매도. - **트레일링 스탑 (Trailing Stop)**: 나머지 50% 물량에 대해 `고점 - (1.5 * ATR)` 적용. ### 5.3 MDD(최대 낙폭) 관리 - **MDD -10%**: 신규 진입을 중단합니다. 포지션 규모를 30% 축소합니다. **단기 매매 전략 및 데이트레이딩을 중단합니다.** (`mdd_manager.py: REDUCE_AND_PAUSE`) - **MDD -20%**: 모든 포지션을 강제로 50% 축소합니다. 레버리지/인버스 ETF부터 우선 청산합니다. (`mdd_manager.py: FORCE_REDUCE`) - **자동 실행**: `mdd_manager.execute_reduction()`이 `portfolio.py`와 `swing/scheduler.py`에서 자동 호출됩니다. 중복 실행 방지 플래그가 내장되어 있습니다. - **복구**: 잔고가 peak를 갱신하면 모든 MDD 플래그가 리셋됩니다. ### 5.4 필터 (Filters) - **가격**: 5,000원 초과 (국내), $4 초과 (미국). (예외: ETF, 리츠). (`config.py: MIN_PRICE_KRW = 5000, MIN_PRICE_USD = 4.0`) - **상관관계 (Correlation)**: 섹터당 최대 3종목 (`correlation_filter.py: max_per_sector = 3`). 기존 포트폴리오와의 상관계수가 0.7을 초과하면 진입을 거부합니다. ### 5.5 연속 손실 관리 - 동일 종목에서 **3회 연속 손실 시 42캘린더일(≈30거래일) 진입 금지** (`loss_tracker.py`). - DB 영속화: `save_to_db()` → `db_worker`의 `upsert_stock_ban` 경유. - 앱 재시작 시 `load_from_db()`로 ban 상태 복원. --- ## 6. 전략 A: RSI + 볼린저 밴드 평균 회귀 v2 > **구현 파일**: `mean_reversion_strategy.py`, `swing/` 모듈 > **자산 배분**: 스윙 포트폴리오 (코스닥 스캐너 25% 외 나머지) ### 6.1 시장 국면 (일봉 기준) - **상승장 (BULL)**: 코스피200 > 200일 이동평균선(MA200) AND MA200 기울기 > 0. - **하락장 (BEAR)**: 코스피200 < MA200 AND MA200 기울기 < 0. - **횡보장 (SIDEWAYS)**: ADX < 20 OR 기울기 ≈ 0. **(이 국면에서는 모든 진입 신호를 무시합니다)** - `market_analyzer.py`에서 `position_multiplier=0.0`, `max_trades=0` 반환. ### 6.2 진입 조건 - **상승장**: RSI(14) < 40 (기본값, `.env`에서 `MEAN_REVERSION_RSI_THRESHOLD`로 조정 가능), 가격이 볼린저 밴드(BB) 하단 부근 (-3% ~ +1.5%), 거래량 > 20일 평균 거래량(20MA). - **하락장**: RSI(14) < 30, 가격 < 볼린저 밴드 하단, 거래량 > 1.5배 × 20MA, 반전 캔들(Reversal candle) 필수. - **선제 진입 (Pre-emptive)**: 일봉 RSI < 40 AND 60분봉 RSI < 30 AND 5일 이동평균선(MA5) 상향 돌파. ### 6.3 청산 조건 - **부분 매도 (50%)**: RSI >= 50 OR 가격 > 볼린저 밴드 중앙선 OR 수익 > 2×ATR. - **전량 매도**: RSI >= 65 OR 가격 > 볼린저 밴드 상단 (99%) OR 트레일링 스탑 도달 (`고점 - 1.5×ATR`). --- ## 7. 전략 B: 공격적 성장 (Aggressive Growth) ### 7.1 코스닥 스캐너 (스윙 매매) > **구현 파일**: `kosdaq_scanner.py` - **대상 (Scope)**: 코스닥 전 종목 (약 1,600개). - **필터 (Filter)**: 가격 > 5,000원, 거래량 상위 20%. - **점수 (Score)**: `0.5×RSI_score + 0.3×BB_score + 0.2×Vol_score`. 최소 점수 0.15 이상인 종목 중 상위 20개 선정. - **자산 배분 (Allocation)**: 전체 자본의 25%. ### 7.2 단기 전략 (15분봉) > **구현 파일**: `short_term_strategy.py` - **타겟 (Target)**: 일봉 RSI < 40 인 종목. - **진입 (Entry)**: 15분봉 RSI < 30, 가격이 볼린저 밴드 하단 부근, 종가 > MA5 (상향 돌파 확인), 거래량 > 1.3배 × 20MA (`config.py: SHORT_TERM_VOLUME_MULTIPLIER = 1.3`). - **최소 변동성**: ATR/close ≥ 0.8% (`config.py: SHORT_TERM_MIN_ATR_RATIO = 0.008`) — 거래비용 커버 보장. - **청산 (Exit)**: 15분봉 RSI > 55 OR 수익 > 1.5 × ATR(15분봉). - **손절 (SL)**: `진입가 - 1.0 × ATR(15분봉)` 또는 `-2% 하드 스탑` 중 **타이트한(더 높은 stop_price) 쪽** — 코드에서 `min(atr_stop, hard_stop)` 사용. *(15분봉 단기전략 전용 — 섹션 5.2 ATR 2.5×는 일봉/스윙 기준)* - **자산 배분 (Allocation)**: 전체 자본의 최대 25%. **MDD가 -10% 미만이면 비활성화합니다.** ### 7.3 데이트레이딩 (5분봉, ORB/VWAP/RSI_BB) > **구현 파일**: `day_trading_strategy.py`, `daytrading/` 모듈 #### 전략 3종 | 전략 | 진입 조건 | 손절 기준 | |------|----------|----------| | **ORB** | 시초가 레인지 돌파 + 거래량 ≥ 1.5× 평균분당거래량 + 직전 5분봉 양봉 | `max(ORB 저점, 현재가×(1-ORB_SL%))` + ATR 하한, 상한 -2.5% 클램프 | | **VWAP** | VWAP 지지 반등 + RSI(14) < 40 + 거래량 ≥ 1.3× + 양봉 | `min(ATR×1.5 기반, 하드스탑 -2.5%)` + 최소 1원 보장 | | **RSI_BB** | RSI(14) ≤ 30 + 종가 ≤ BB 하단 + 거래량 ≥ 1.3× + 양봉 | `min(ATR×1.5 기반, 하드스탑 -2.5%)` + 최소 1원 보장 | #### 포지션 사이징 - 종목당 최대 4% (섹션 5.1 준수, `config.py: DAY_TRADE_MAX_CAPITAL_RATIO = 0.04`). - 동시 최대 3종목 (`config.py: DAY_TRADE_MAX_POSITIONS = 3`). - confidence 기반 동적 조정: `예산 × (signal.confidence / 0.7)`. #### 자산 배분 - 전체 자본의 최대 25% (`config.py: DAY_TRADE_MAX_RATIO_DT = 0.25`). #### 청산 규칙 - **분할 매도**: 목표가(+2R) 달성 시 50% 분할 매도, 잔량은 트레일링 스탑(ATR × 1.0) 적용. - **시간 손절**: 진입 후 30분(6봉)간 +0.3% 미달 시 청산 (기회비용 관리). - **과매수 청산**: 5분봉 RSI ≥ 70 AND 수수료 이상 수익 시 청산. - **EOD 강제 청산**: 15:20 이후 전량 청산 (`config.py: DAY_TRADE_EOD_FLAT_HOUR/MIN`). #### 필터 및 제한 - **시장 국면**: SIDEWAYS 국면에서 진입 차단 (섹션 6.1 준수). - **시간대 제한**: 점심시간(11:30~13:00) VWAP/RSI_BB 진입 제한, **14:30 이후 신규 진입 마감**. - **일일 손실 한도**: -3% 초과 시 당일 신규 진입 중단 (`config.py: DAY_TRADE_DAILY_LOSS_LIMIT = -0.03`). - **쿨다운**: 당일 3연패 시 신규 진입 차단 (`daytrading/position_manager.py`). - **loss_tracker 연동**: 전량 매도 시 `loss_tracker.record_trade_result()` + `save_to_db()` 호출. - **MDD -10% 미만이면 비활성화합니다.** --- ## 8. Claude에 대한 지침 ### 8.1 주요 점검 사항 (Critical Checkpoints) 1. **아키텍처**: 모든 DB 쓰기 작업이 `db_worker.py`를 사용하는지 확인하십시오. 예외: `sync_portfolio()`. 2. **안전성 (Safety)**: 모든 매매에 리스크 규칙(섹션 5)을 항상 적용하십시오. 3. **시장 국면 (Regime)**: 횡보장(SIDEWAYS) 국면에서는 진입을 제안하지 마십시오. 4. **테스트**: 백테스트 및 전진 분석(Walk-forward validation) 없이는 실전 투자를 하지 마십시오. 5. **손절 방향**: 손절가 선택 시 항상 `min()` (타이트한 쪽)을 사용하십시오. `max()`는 절대 사용하지 마십시오. 6. **loss_tracker 영속화**: `record_trade_result()` 호출 후 반드시 `save_to_db()` 호출을 확인하십시오. 7. **인증**: 쓰기/삭제 API에는 반드시 `require_api_key` 의존성을 적용하십시오. ### 8.2 응답 형식 (Response Format) - JSON 출력 시 `_dumps()`를 사용하십시오. - 새로운 기능 개발 시 새 파일을 생성하십시오. - 기존 시그니처를 수정하지 마십시오. ### 8.3 주요 설정값 참조 (`config.py`) — 백테스트 검증 완료 | 설정 | 값 | 설명 | 백테스트 변경 | |------|---|------|------------| | `MAX_POSITION_SIZE` | 0.06 | 종목당 최대 6% | 기존 0.04 → 0.06 | | `MAX_HOLDINGS_COUNT` | 20 | 동시 보유 최대 | 유지 | | `LEVERAGE_ETF_MAX_RATIO` | 0.20 | 레버리지 ETF 최대 | 유지 | | `ATR_STOP_MULTIPLIER` | 2.5 | 스윙 ATR 손절 배수 | 유지 | | `STOP_LOSS_PERCENT` | 7.0 | 기본 손절 7% | 기존 6.0 → 7.0 | | `MEAN_REVERSION_RSI_THRESHOLD` | 46.0 | 평균회귀 RSI 임계값 | 기존 40.0 → 46.0 | | `MEAN_REVERSION_BEAR_RSI_THRESHOLD` | 35.0 | BEAR RSI 임계값 | 기존 30.0 → 35.0 | | `MEAN_REVERSION_RSI_EXIT_THRESHOLD` | 55.0 | 1차 익절 RSI | 기존 50.0 → 55.0 | | `MEAN_REVERSION_RSI_FULL_EXIT` | 70.0 | 전량 청산 RSI | 기존 65.0 → 70.0 | | `DAY_TRADE_MAX_POSITIONS` | 3 | 데이트레이딩 동시 최대 | 유지 | | `DAY_TRADE_ENTRY_CUTOFF` | 14:30 | 데이트레이딩 마감 | 기존 15:00 → 14:30 | | `CONSECUTIVE_LOSS_BAN_COUNT` | 3 | 연속 손실 ban 횟수 | 유지 | ### 8.4 듀얼 전략 (백테스트 검증: 2023-03 ~ 2026-03) 스윙 전략은 3가지 진입 전략을 병행합니다: | 전략 | 조건 | 청산 방식 | 기여도 | |------|------|----------|--------| | **평균회귀** | RSI 과매도 + BB 하단 | RSI 55 부분익절 → RSI 70 전량 | 베이스 수익 | | **모멘텀 돌파** | 20일 신고가 + 거래량 2x + RSI 50~70 | +10% 30%매도 → +20% 30%매도 → 트레일링 | 큰 이익 | | **눌림목 매수** | MA20>MA60 + MA20 근처 조정 + RSI 반등 | 평균회귀와 동일 | 안정 수익 | ### 8.5 적응형 모드 (4단계) 시장 상황에 따라 파라미터가 자동 전환됩니다 (`adaptive_strategy.py`): | 모드 | RSI 진입 | 포지션 | 손절 | 트리거 | |------|---------|--------|------|--------| | **Aggressive** | 50 | 7% | -9% | ATR백분위<30 + ADX>25 + 5일수익>+2% | | **Normal** | 46 | 6% | -7% | 기본 | | **Defensive** | 38 | 4% | -6% | ATR백분위>70 또는 5일수익<-3% | | **Crisis** | 25 | 1.5% | -3% | ATR백분위>90 또는 5일수익<-5% | *마지막 업데이트: 2026-03-25 (백테스트 검증 반영)*