""" Base strategy class for all trading strategies. Strategies should inherit from BaseStrategy and implement the run() method. """ from abc import ABC, abstractmethod import pandas as pd from engine.market import MarketType class BaseStrategy(ABC): """ Abstract base class for trading strategies. Class Attributes: default_market_type: Default market type for this strategy default_leverage: Default leverage (only applies to perpetuals) default_sl_stop: Default stop-loss percentage default_tp_stop: Default take-profit percentage default_sl_trail: Whether stop-loss is trailing by default """ # Market configuration defaults default_market_type: MarketType = MarketType.SPOT default_leverage: int = 1 # Risk management defaults (can be overridden per strategy) default_sl_stop: float | None = None default_tp_stop: float | None = None default_sl_trail: bool = False def __init__(self, **kwargs): self.params = kwargs @abstractmethod def run( self, close: pd.Series, **kwargs ) -> tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame, pd.DataFrame]: """ Run the strategy logic. Args: close: Price series (can be multiple columns for grid search) **kwargs: Additional data (high, low, open, volume) and parameters Returns: Tuple of 4 DataFrames/Series: - long_entries: Boolean signals to open long positions - long_exits: Boolean signals to close long positions - short_entries: Boolean signals to open short positions - short_exits: Boolean signals to close short positions Note: For spot markets, short signals will be ignored. For backward compatibility, strategies can return 2-tuple (entries, exits) which will be interpreted as long-only signals. """ pass def get_indicator(self, ind_cls, *args, **kwargs): """Helper to run a vectorbt indicator.""" return ind_cls.run(*args, **kwargs) @staticmethod def create_empty_signals(reference: pd.Series | pd.DataFrame) -> pd.DataFrame: """ Create an empty (all False) signal DataFrame matching the reference shape. Args: reference: Series or DataFrame to match shape/index Returns: DataFrame of False values with same shape as reference """ if isinstance(reference, pd.DataFrame): return pd.DataFrame(False, index=reference.index, columns=reference.columns) return pd.Series(False, index=reference.index)