summaryrefslogtreecommitdiff
path: root/services/strategy-engine/strategies/rsi_strategy.py
diff options
context:
space:
mode:
Diffstat (limited to 'services/strategy-engine/strategies/rsi_strategy.py')
-rw-r--r--services/strategy-engine/strategies/rsi_strategy.py32
1 files changed, 30 insertions, 2 deletions
diff --git a/services/strategy-engine/strategies/rsi_strategy.py b/services/strategy-engine/strategies/rsi_strategy.py
index 490a8a9..0ec6780 100644
--- a/services/strategy-engine/strategies/rsi_strategy.py
+++ b/services/strategy-engine/strategies/rsi_strategy.py
@@ -55,10 +55,34 @@ class RsiStrategy(BaseStrategy):
if self._quantity <= 0:
raise ValueError(f"Quantity must be positive, got {self._quantity}")
+ self._init_filters(
+ require_trend=False,
+ adx_threshold=float(params.get("adx_threshold", 25.0)),
+ min_volume_ratio=float(params.get("min_volume_ratio", 0.5)),
+ atr_stop_multiplier=float(params.get("atr_stop_multiplier", 2.0)),
+ atr_tp_multiplier=float(params.get("atr_tp_multiplier", 3.0)),
+ )
+
def reset(self) -> None:
self._closes.clear()
+ def _rsi_conviction(self, rsi_value: float) -> float:
+ """Map RSI value to conviction strength (0.0-1.0).
+
+ For BUY (oversold): lower RSI = higher conviction.
+ For SELL (overbought): higher RSI = higher conviction.
+ Linear scale from the threshold to the extreme (0 or 100).
+ """
+ if rsi_value < self._oversold:
+ # RSI 0 -> 1.0, RSI at oversold threshold -> 0.0
+ return min(1.0, max(0.1, (self._oversold - rsi_value) / self._oversold))
+ elif rsi_value > self._overbought:
+ # RSI 100 -> 1.0, RSI at overbought threshold -> 0.0
+ return min(1.0, max(0.1, (rsi_value - self._overbought) / (100.0 - self._overbought)))
+ return 0.0
+
def on_candle(self, candle: Candle) -> Signal | None:
+ self._update_filter_data(candle)
self._closes.append(float(candle.close))
if len(self._closes) < self._period + 1:
@@ -71,22 +95,26 @@ class RsiStrategy(BaseStrategy):
return None
if rsi_value < self._oversold:
- return Signal(
+ signal = Signal(
strategy=self.name,
symbol=candle.symbol,
side=OrderSide.BUY,
price=candle.close,
quantity=self._quantity,
+ conviction=self._rsi_conviction(rsi_value),
reason=f"RSI {rsi_value:.2f} below oversold threshold {self._oversold}",
)
+ return self._apply_filters(signal)
elif rsi_value > self._overbought:
- return Signal(
+ signal = Signal(
strategy=self.name,
symbol=candle.symbol,
side=OrderSide.SELL,
price=candle.close,
quantity=self._quantity,
+ conviction=self._rsi_conviction(rsi_value),
reason=f"RSI {rsi_value:.2f} above overbought threshold {self._overbought}",
)
+ return self._apply_filters(signal)
return None