summaryrefslogtreecommitdiff
path: root/services/strategy-engine/strategies
diff options
context:
space:
mode:
Diffstat (limited to 'services/strategy-engine/strategies')
-rw-r--r--services/strategy-engine/strategies/asian_session_rsi.py21
-rw-r--r--services/strategy-engine/strategies/config/asian_session_rsi.yaml2
2 files changed, 22 insertions, 1 deletions
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
diff --git a/services/strategy-engine/strategies/config/asian_session_rsi.yaml b/services/strategy-engine/strategies/config/asian_session_rsi.yaml
index 21d7715..bc7c5c9 100644
--- a/services/strategy-engine/strategies/config/asian_session_rsi.yaml
+++ b/services/strategy-engine/strategies/config/asian_session_rsi.yaml
@@ -10,3 +10,5 @@ session_start_utc: 0 # UTC 0시 = KST 9시
session_end_utc: 2 # UTC 2시 = KST 11시
max_trades_per_day: 3 # 하루 최대 3회
max_consecutive_losses: 2 # 2연패 시 중단
+ema_period: 20
+require_bullish_candle: true