From 87bf67bac771181aeb4f4c5bb11fae8f343c12bb Mon Sep 17 00:00:00 2001 From: TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com> Date: Thu, 2 Apr 2026 09:56:42 +0900 Subject: feat: wire sentiment into engine + add EMA/bullish candle entry filters --- .../strategy-engine/strategies/asian_session_rsi.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'services/strategy-engine/strategies/asian_session_rsi.py') diff --git a/services/strategy-engine/strategies/asian_session_rsi.py b/services/strategy-engine/strategies/asian_session_rsi.py index 741cd63..1874591 100644 --- a/services/strategy-engine/strategies/asian_session_rsi.py +++ b/services/strategy-engine/strategies/asian_session_rsi.py @@ -36,6 +36,9 @@ class AsianSessionRsiStrategy(BaseStrategy): self._max_trades_per_day: int = 3 self._max_consecutive_losses: int = 2 self._use_sentiment: bool = True + self._ema_period: int = 20 + self._require_bullish_candle: bool = True + self._prev_candle_bullish: bool = False # Sentiment (updated externally before each session) self._sentiment: SentimentData | None = None # State @@ -63,6 +66,8 @@ class AsianSessionRsiStrategy(BaseStrategy): self._max_trades_per_day = int(params.get("max_trades_per_day", 3)) self._max_consecutive_losses = int(params.get("max_consecutive_losses", 2)) self._use_sentiment = bool(params.get("use_sentiment", True)) + self._ema_period = int(params.get("ema_period", 20)) + self._require_bullish_candle = bool(params.get("require_bullish_candle", True)) if self._quantity <= 0: raise ValueError(f"Quantity must be positive, got {self._quantity}") @@ -89,6 +94,7 @@ class AsianSessionRsiStrategy(BaseStrategy): self._in_position = False self._entry_price = 0.0 self._sentiment = None + self._prev_candle_bullish = False def update_sentiment(self, sentiment: SentimentData) -> None: """Update sentiment data. Call before each trading session.""" @@ -130,6 +136,14 @@ class AsianSessionRsiStrategy(BaseStrategy): avg = sum(self._volumes) / len(self._volumes) return self._volumes[-1] >= avg + def _price_above_ema(self) -> bool: + """Check if current price is above short-term EMA.""" + if len(self._closes) < self._ema_period: + return True # Not enough data, allow by default + series = pd.Series(list(self._closes)) + ema_val = series.ewm(span=self._ema_period, adjust=False).mean().iloc[-1] + return self._closes[-1] >= ema_val + def on_candle(self, candle: Candle) -> Signal | None: self._update_filter_data(candle) @@ -137,6 +151,9 @@ class AsianSessionRsiStrategy(BaseStrategy): self._closes.append(close) self._volumes.append(float(candle.volume)) + # Track candle direction for bullish confirmation + is_bullish = float(candle.close) >= float(candle.open) + # Daily reset day = candle.open_time.strftime("%Y-%m-%d") if self._today != day: @@ -218,7 +235,9 @@ class AsianSessionRsiStrategy(BaseStrategy): if rsi is None: return None - if rsi < self._rsi_oversold and self._volume_above_average(): + if rsi < self._rsi_oversold and self._volume_above_average() and self._price_above_ema(): + if self._require_bullish_candle and not is_bullish: + return None # Wait for bullish candle confirmation self._in_position = True self._entry_price = close self._trades_today += 1 -- cgit v1.2.3