Files
lowkey_backtest/strategies/examples.py

98 lines
2.9 KiB
Python

"""
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