# Strategy Module 매매 전략을 관리하고 실행하는 핵심 모듈 ## 모듈 구조 ``` strategy/ ├── __init__.py # 모듈 내보내기 ├── base_strategy.py # BaseStrategy 추상 클래스 ├── signal.py # Signal 데이터 클래스 ├── strategy_manager.py # 전략 관리자 (등록/실행) ├── indicators.py # 보조지표 (RSI, BB, MACD 등) ├── scanner.py # 종목 스캔 ├── strategies/ # 구체적 전략 구현 │ ├── __init__.py │ └── day_trading.py # 데이트레이딩 전략 └── README.md ``` ## 사용 방법 ### 1. 전략 구현 `BaseStrategy`를 상속받아 `analyze()` 메서드 구현: ```python from app.strategy import BaseStrategy, Signal, SignalType from datetime import datetime import pytz class MyStrategy(BaseStrategy): def __init__(self): super().__init__(name="MyStrategy", config={"param1": 10}) async def analyze(self, stock_code, market_data, portfolio_data=None): current_price = market_data.get("current_price") # 매수 조건 체크 if self._should_buy(market_data): return Signal( stock_code=stock_code, signal_type=SignalType.BUY, strategy_name=self.name, timestamp=datetime.now(pytz.timezone("Asia/Seoul")), price=current_price, confidence=0.8, reason="매수 조건 충족" ) return None def _should_buy(self, market_data): # 실제 로직 구현 return True ``` ### 2. 전략 등록 및 실행 ```python from app.strategy import strategy_manager from app.strategy.strategies import DayTradingStrategy # 전략 인스턴스 생성 day_trading = DayTradingStrategy( name="DayTrading_ORB", config={ "max_positions": 3, "stop_loss_pct": 0.025 } ) # 전략 등록 (priority 낮을수록 먼저 실행) strategy_manager.register_strategy(day_trading, priority=10) # 단일 전략 실행 signal = await strategy_manager.run_strategy( "DayTrading_ORB", stock_code="005930", market_data={ "current_price": 75000, "minute_chart": [...], } ) if signal: print(f"신호 발생: {signal}") # 모든 전략 동시 실행 signals = await strategy_manager.run_all_strategies( stock_code="005930", market_data={...}, parallel=True # 병렬 실행 ) # 신호 충돌 해결 final_signal = strategy_manager.resolve_conflicts( signals, method="highest_confidence" # or "priority", "majority_vote" ) ``` ### 3. Signal 데이터 구조 ```python from app.strategy import Signal, SignalType from datetime import datetime import pytz signal = Signal( stock_code="005930", signal_type=SignalType.BUY, strategy_name="MyStrategy", timestamp=datetime.now(pytz.timezone("Asia/Seoul")), # 주문 정보 quantity=10, price=75000, # None = 시장가 confidence=0.85, # 손익 관리 stop_loss_price=73000, take_profit_price=78000, trailing_stop_pct=0.02, # 2% 트레일링 # 메타데이터 reason="RSI 과매도 반등", metadata={"rsi": 25, "bb_lower": 74000} ) # JSON 변환 data = signal.to_dict() ``` ### 4. 보조지표 사용 ```python from app.strategy.indicators import rsi, bollinger_bands, sma, macd, atr # 종가 리스트 closes = [75000, 75500, 76000, 74500, 75000, ...] # RSI rsi_value = rsi(closes, period=14) if rsi_value and rsi_value < 30: print("과매도 구간") # 볼린저 밴드 bb = bollinger_bands(closes, period=20, std_mult=2.0) if bb: upper, middle, lower = bb if closes[-1] < lower: print("하단 돌파") # SMA sma_20 = sma(closes, 20) sma_60 = sma(closes, 60) if sma_20 and sma_60 and sma_20 > sma_60: print("골든 크로스 발생") # ATR highs = [76000, 76500, ...] lows = [74500, 75000, ...] atr_value = atr(highs, lows, closes, period=14) ``` ### 5. 종목 스캔 ```python from app.strategy.scanner import Scanner, filter_price_range, filter_volume_min # 스캀너 생성 scanner = Scanner() # 필터 추가 scanner.add_filter(filter_price_range(10000, 100000)) # 1만~10만원 scanner.add_filter(filter_volume_min(100000)) # 최소 거래량 10만주 # 커스텀 필터 def custom_filter(data): # 등락률 5% 이상 return data.get("change_rate", 0) >= 5.0 scanner.add_filter(custom_filter) # 스캔 실행 kospi_codes = ["005930", "000660", "035420", ...] # KOSPI 종목 리스트 matched = await scanner.scan(kospi_codes, max_concurrent=10) for stock in matched: print(f"{stock['stock_name']} ({stock['stock_code']}): " f"{stock['current_price']}원, +{stock['change_rate']}%") ``` ## 주요 기능 ### BaseStrategy - ✅ 전략 추상화 (템플릿 메서드 패턴) - ✅ `analyze()` 구현 강제 - ✅ `on_signal_executed()` 콜백 - ✅ `on_error()` 에러 핸들링 - ✅ 설정 관리 (config) - ✅ 활성화/비활성화 ### StrategyManager - ✅ 전략 등록/삭제 - ✅ 우선순위 관리 - ✅ 단일/복수 전략 실행 - ✅ 병렬 실행 지원 - ✅ 신호 충돌 해결 - `highest_confidence`: 가장 높은 신뢰도 - `priority`: 전략 우선순위 - `majority_vote`: 다수결 - ✅ 신호 이력 관리 - ✅ 통계 정보 ### Signal - ✅ 표준화된 신호 데이터 구조 - ✅ 6가지 신호 타입 (BUY/SELL/HOLD/CLOSE/STOP_LOSS/TAKE_PROFIT) - ✅ 손익 관리 필드 - ✅ 신뢰도 평가 - ✅ JSON 직렬화 ### Indicators - ✅ SMA (Simple Moving Average) - ✅ EMA (Exponential Moving Average) - ✅ RSI (Relative Strength Index) - ✅ Bollinger Bands - ✅ MACD - ✅ ATR (Average True Range) - ✅ VWAP (Volume Weighted Average Price) ### Scanner - ✅ 조건 기반 종목 필터링 - ✅ 동시 다중 종목 스캔 - ✅ 사전 정의 필터 - 가격 범위 - 거래량 최소값 - 등락률 범위 - 시가총액 최소값 - ✅ 커스텀 필터 추가 가능 ## 기존 코드 마이그레이션 기존 `services/` 폴더의 전략 파일들을 새 구조로 변환: | 기존 파일 | 새 위치 | |----------|----------| | `day_trading_strategy.py` | `strategy/strategies/day_trading.py` | | `swing_trading_strategy.py` | `strategy/strategies/swing_trading.py` | | `momentum_strategy.py` | `strategy/strategies/momentum.py` | 변환 패턴: ```python # 기존 def check_signal(stock_code, market_data): if condition: return DayTradeSignal(...) return None # 새 구조 class DayTradingStrategy(BaseStrategy): async def analyze(self, stock_code, market_data, portfolio_data=None): if condition: return Signal(...) return None ``` ## Phase 2 완료 체크리스트 - [x] `strategy/base_strategy.py` 생성 - [x] `strategy/signal.py` 생성 - [x] `strategy/strategy_manager.py` 생성 - [x] `strategy/indicators.py` 생성 - [x] `strategy/scanner.py` 생성 - [x] `strategy/strategies/day_trading.py` 예시 생성 - [x] README 문서 작성 ## 다음 단계 (Phase 3) - [ ] WebSocket 모듈 분리 (`realtime/`) - [ ] 실시간 시세 수신 구조 개선 - [ ] 장 스케줄 관리 --- **작성일**: 2026-03-06 **작성자**: 서영우