""" Example trading strategies for backtesting. These are simple strategies demonstrating the framework usage. """ import pandas as pd import vectorbt as vbt from engine.market import MarketType from strategies.base import BaseStrategy class RsiStrategy(BaseStrategy): """ RSI mean-reversion strategy. Long entry when RSI crosses below oversold level. Long exit when RSI crosses above overbought level. """ default_market_type = MarketType.SPOT default_leverage = 1 def run( self, close: pd.Series, period: int = 14, rsi_lower: int = 30, rsi_upper: int = 70, **kwargs ) -> tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame, pd.DataFrame]: """ Generate RSI-based trading signals. Args: close: Price series period: RSI calculation period rsi_lower: Oversold threshold (buy signal) rsi_upper: Overbought threshold (sell signal) Returns: 4-tuple of (long_entries, long_exits, short_entries, short_exits) """ # Calculate RSI rsi = vbt.RSI.run(close, window=period) # Long signals: buy oversold, sell overbought long_entries = rsi.rsi_crossed_below(rsi_lower) long_exits = rsi.rsi_crossed_above(rsi_upper) # No short signals for this strategy (spot-focused) short_entries = BaseStrategy.create_empty_signals(long_entries) short_exits = BaseStrategy.create_empty_signals(long_entries) return long_entries, long_exits, short_entries, short_exits class MaCrossStrategy(BaseStrategy): """ Moving Average crossover strategy. Long entry when fast MA crosses above slow MA. Long exit when fast MA crosses below slow MA. """ default_market_type = MarketType.SPOT default_leverage = 1 def run( self, close: pd.Series, fast_window: int = 10, slow_window: int = 20, **kwargs ) -> tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame, pd.DataFrame]: """ Generate MA crossover trading signals. Args: close: Price series fast_window: Fast MA period slow_window: Slow MA period Returns: 4-tuple of (long_entries, long_exits, short_entries, short_exits) """ # Calculate Moving Averages fast_ma = vbt.MA.run(close, window=fast_window) slow_ma = vbt.MA.run(close, window=slow_window) # Long signals long_entries = fast_ma.ma_crossed_above(slow_ma) long_exits = fast_ma.ma_crossed_below(slow_ma) # No short signals for this strategy short_entries = BaseStrategy.create_empty_signals(long_entries) short_exits = BaseStrategy.create_empty_signals(long_entries) return long_entries, long_exits, short_entries, short_exits