from __future__ import annotations from abc import ABC, abstractmethod from dataclasses import dataclass import pandas as pd from app.core.logger import setup_logger logger = setup_logger("strategy") @dataclass class Signal: action: str # buy / sell / hold stock_code: str qty: int = 0 price: int = 0 reason: str = "" confidence: float = 0.0 strategy_id: int | None = None class BaseStrategy(ABC): def __init__(self, stock_code: str, params: dict, strategy_id: int = 0) -> None: self.stock_code = stock_code self.params = params self.strategy_id = strategy_id self.name = self.__class__.__name__ @abstractmethod def evaluate(self, current_price: dict, price_history: list[dict], holding_qty: int) -> Signal: ... @staticmethod def _to_dataframe(prices: list[dict]) -> pd.DataFrame: if not prices: return pd.DataFrame() df = pd.DataFrame(prices) for col in ["open", "high", "low", "close", "volume"]: if col in df.columns: df[col] = pd.to_numeric(df[col], errors="coerce") return df