refactor(phase2): Create strategy module core structure
This commit is contained in:
79
backend/app/strategy/signal.py
Normal file
79
backend/app/strategy/signal.py
Normal file
@@ -0,0 +1,79 @@
|
||||
"""
|
||||
Signal Data Class
|
||||
|
||||
전략이 생성하는 매매 신호 데이터 구조
|
||||
"""
|
||||
from enum import Enum
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional, Dict, Any
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class SignalType(Enum):
|
||||
"""신호 타입"""
|
||||
BUY = "BUY" # 매수
|
||||
SELL = "SELL" # 매도
|
||||
HOLD = "HOLD" # 보유
|
||||
CLOSE = "CLOSE" # 청산
|
||||
STOP_LOSS = "STOP_LOSS" # 손절
|
||||
TAKE_PROFIT = "TAKE_PROFIT" # 익절
|
||||
|
||||
|
||||
@dataclass
|
||||
class Signal:
|
||||
"""
|
||||
매매 신호 데이터 클래스
|
||||
|
||||
전략이 생성한 매매 신호를 표준화된 형식으로 전달
|
||||
"""
|
||||
# 필수 필드
|
||||
stock_code: str # 종목코드
|
||||
signal_type: SignalType # 신호 타입
|
||||
strategy_name: str # 전략 이름
|
||||
timestamp: datetime # 신호 생성 시각
|
||||
|
||||
# 주문 정보
|
||||
quantity: Optional[int] = None # 수량
|
||||
price: Optional[float] = None # 가격 (None = 시장가)
|
||||
confidence: float = 1.0 # 신뢰도 (0.0 ~ 1.0)
|
||||
|
||||
# 손익 관리
|
||||
stop_loss_price: Optional[float] = None # 손절가
|
||||
take_profit_price: Optional[float] = None # 익절가
|
||||
trailing_stop_pct: Optional[float] = None # 트레일링 스탑 %
|
||||
|
||||
# 메타데이터
|
||||
reason: Optional[str] = None # 신호 발생 이유
|
||||
metadata: Optional[Dict[str, Any]] = None # 추가 데이터
|
||||
|
||||
def __post_init__(self):
|
||||
"""유효성 검증"""
|
||||
if self.confidence < 0.0 or self.confidence > 1.0:
|
||||
raise ValueError(f"Confidence must be 0.0~1.0, got {self.confidence}")
|
||||
|
||||
if isinstance(self.signal_type, str):
|
||||
self.signal_type = SignalType(self.signal_type)
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
"""딕셔너리 변환 (DB 저장용)"""
|
||||
return {
|
||||
"stock_code": self.stock_code,
|
||||
"signal_type": self.signal_type.value,
|
||||
"strategy_name": self.strategy_name,
|
||||
"timestamp": self.timestamp.isoformat(),
|
||||
"quantity": self.quantity,
|
||||
"price": self.price,
|
||||
"confidence": self.confidence,
|
||||
"stop_loss_price": self.stop_loss_price,
|
||||
"take_profit_price": self.take_profit_price,
|
||||
"trailing_stop_pct": self.trailing_stop_pct,
|
||||
"reason": self.reason,
|
||||
"metadata": self.metadata,
|
||||
}
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return (
|
||||
f"Signal({self.signal_type.value} {self.stock_code} "
|
||||
f"@{self.price or 'MARKET'} x{self.quantity} "
|
||||
f"[{self.strategy_name}] conf={self.confidence:.2f})"
|
||||
)
|
||||
Reference in New Issue
Block a user