From 6909bc142912177d76b295c5d21507229ed6e2c0 Mon Sep 17 00:00:00 2001
From: TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com>
Date: Thu, 2 Apr 2026 14:14:36 +0900
Subject: feat: add Telegram notification for stock selections
---
shared/src/shared/notifier.py | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
(limited to 'shared/src')
diff --git a/shared/src/shared/notifier.py b/shared/src/shared/notifier.py
index f03919c..9630a18 100644
--- a/shared/src/shared/notifier.py
+++ b/shared/src/shared/notifier.py
@@ -8,6 +8,7 @@ from typing import Optional, Sequence
import aiohttp
from shared.models import Signal, Order, Position
+from shared.sentiment_models import SelectedStock, MarketSentiment
logger = logging.getLogger(__name__)
@@ -123,6 +124,35 @@ class TelegramNotifier:
lines.append(" No open positions")
await self.send("\n".join(lines))
+ async def send_stock_selection(
+ self,
+ selections: list[SelectedStock],
+ market: MarketSentiment | None = None,
+ ) -> None:
+ """Format and send stock selection notification."""
+ lines = [f"📊 Stock Selection ({len(selections)} picks)", ""]
+
+ side_emoji = {"BUY": "🟢", "SELL": "🔴"}
+
+ for i, s in enumerate(selections, 1):
+ emoji = side_emoji.get(s.side.value, "⚪")
+ lines.append(
+ f"{i}. {s.symbol} {emoji} {s.side.value} "
+ f"(conviction: {s.conviction:.0%})"
+ )
+ lines.append(f" {s.reason}")
+ if s.key_news:
+ lines.append(f" News: {s.key_news[0]}")
+ lines.append("")
+
+ if market:
+ lines.append(
+ f"Market: F&G {market.fear_greed} ({market.fear_greed_label})"
+ + (f" | VIX {market.vix:.1f}" if market.vix else "")
+ )
+
+ await self.send("\n".join(lines))
+
async def close(self) -> None:
"""Close the underlying aiohttp session."""
if self._session is not None:
--
cgit v1.2.3