trading/shared/strategies/mean_reversion.py

56 lines
1.5 KiB
Python

"""Mean reversion strategy — buy oversold, sell overbought using RSI."""
from datetime import datetime, timezone
from shared.schemas.trading import MarketSnapshot, SentimentContext, SignalDirection, TradeSignal
from shared.strategies.base import BaseStrategy
class MeanReversionStrategy(BaseStrategy):
"""Trade on the assumption that extreme RSI readings will revert to the mean.
**Buy signal** (LONG):
RSI < 30 (oversold).
**Sell signal** (SHORT):
RSI > 70 (overbought).
Signal strength is proportional to how far the RSI is from its
threshold, clamped to [0, 1].
* Buy strength = ``(30 - rsi) / 30``
* Sell strength = ``(rsi - 70) / 30``
"""
name: str = "mean_reversion"
async def evaluate(
self,
ticker: str,
market: MarketSnapshot,
sentiment: SentimentContext | None = None,
) -> TradeSignal | None:
if market.rsi is None:
return None
rsi = market.rsi
if rsi < 30:
direction = SignalDirection.LONG
raw_strength = (30 - rsi) / 30
elif rsi > 70:
direction = SignalDirection.SHORT
raw_strength = (rsi - 70) / 30
else:
# RSI in neutral territory — no opinion.
return None
strength = max(0.0, min(1.0, raw_strength))
return TradeSignal(
ticker=ticker,
direction=direction,
strength=strength,
strategy_sources=[self.name],
timestamp=datetime.now(tz=timezone.utc),
)