summaryrefslogtreecommitdiff
path: root/services/strategy-engine/strategies/bollinger_strategy.py
diff options
context:
space:
mode:
authorTheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com>2026-04-02 09:44:43 +0900
committerTheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com>2026-04-02 09:44:43 +0900
commitb9d21e2e2f7ae096c2f8a01bb142a685683b5b90 (patch)
treea031989228ded9ff1e6d47840124ea5dcc9a9a3c /services/strategy-engine/strategies/bollinger_strategy.py
parentbb2e387f870495703fd663ca8f525028c3a8ced5 (diff)
feat: add market sentiment filters (Fear & Greed, CryptoPanic, CryptoQuant)
- SentimentProvider: fetches Fear & Greed Index (free, no key), CryptoPanic news sentiment (free key), CryptoQuant exchange netflow (free key) - SentimentData: aggregated should_buy/should_block logic - Fear < 30 = buy opportunity, Greed > 80 = block buying - Negative news < -0.5 = block buying - Exchange outflow = bullish, inflow = bearish - Integrated into Asian Session RSI strategy as entry filter - All providers optional — disabled when API key missing - 14 sentiment tests + 386 total tests passing
Diffstat (limited to 'services/strategy-engine/strategies/bollinger_strategy.py')
-rw-r--r--services/strategy-engine/strategies/bollinger_strategy.py40
1 files changed, 22 insertions, 18 deletions
diff --git a/services/strategy-engine/strategies/bollinger_strategy.py b/services/strategy-engine/strategies/bollinger_strategy.py
index a195cb8..ebe7967 100644
--- a/services/strategy-engine/strategies/bollinger_strategy.py
+++ b/services/strategy-engine/strategies/bollinger_strategy.py
@@ -102,27 +102,31 @@ class BollingerStrategy(BaseStrategy):
if price > sma:
# Breakout upward
conv = min(0.5 + squeeze_duration * 0.1, 1.0)
- return self._apply_filters(Signal(
- strategy=self.name,
- symbol=candle.symbol,
- side=OrderSide.BUY,
- price=candle.close,
- quantity=self._quantity,
- conviction=conv,
- reason=f"Bollinger squeeze breakout UP after {squeeze_duration} bars",
- ))
+ return self._apply_filters(
+ Signal(
+ strategy=self.name,
+ symbol=candle.symbol,
+ side=OrderSide.BUY,
+ price=candle.close,
+ quantity=self._quantity,
+ conviction=conv,
+ reason=f"Bollinger squeeze breakout UP after {squeeze_duration} bars",
+ )
+ )
else:
# Breakout downward
conv = min(0.5 + squeeze_duration * 0.1, 1.0)
- return self._apply_filters(Signal(
- strategy=self.name,
- symbol=candle.symbol,
- side=OrderSide.SELL,
- price=candle.close,
- quantity=self._quantity,
- conviction=conv,
- reason=f"Bollinger squeeze breakout DOWN after {squeeze_duration} bars",
- ))
+ return self._apply_filters(
+ Signal(
+ strategy=self.name,
+ symbol=candle.symbol,
+ side=OrderSide.SELL,
+ price=candle.close,
+ quantity=self._quantity,
+ conviction=conv,
+ reason=f"Bollinger squeeze breakout DOWN after {squeeze_duration} bars",
+ )
+ )
# Bandwidth filter: skip sideways markets
if sma != 0 and bandwidth < self._min_bandwidth: