From 45d9965638c00a2e165a684037d69aacc36c1ab0 Mon Sep 17 00:00:00 2001 From: Michael Simard Date: Thu, 4 Dec 2025 20:18:08 -0600 Subject: [PATCH] Update stock notifications with company names and new schedule times MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add full company names to stock price notifications displayed alongside tickers. Update scheduled message times from hourly to three specific times: market open (9:30 AM ET), noon (12:00 PM ET), and market close (4:00 PM ET). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- bot.py | 44 ++++++++++++++++++++++++++++------------ stock_api/finnhub_api.py | 10 +++++++++ stock_api/yahoo.py | 10 +++++++++ 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/bot.py b/bot.py index 66b452b..bf53a32 100644 --- a/bot.py +++ b/bot.py @@ -46,13 +46,20 @@ class StockBot(commands.Bot): """Initialize the bot and set up scheduled tasks.""" logger.info("Bot setup initiated") - # Schedule hourly updates during market hours - # Run every hour on the hour, but only post if market is open + # Schedule market open update at 9:30 AM ET on weekdays self.scheduler.add_job( - self.send_hourly_update, - CronTrigger(minute=0, timezone=MarketHours.NYSE_TIMEZONE), - id='hourly_update', - name='Hourly Stock Price Update' + self.send_market_open_update, + CronTrigger(hour=9, minute=30, day_of_week='mon-fri', timezone=MarketHours.NYSE_TIMEZONE), + id='market_open_update', + name='Market Open Update' + ) + + # Schedule noon update at 12:00 PM ET on weekdays + self.scheduler.add_job( + self.send_noon_update, + CronTrigger(hour=12, minute=0, day_of_week='mon-fri', timezone=MarketHours.NYSE_TIMEZONE), + id='noon_update', + name='Noon Update' ) # Schedule market close update at 4:00 PM ET on weekdays @@ -64,7 +71,7 @@ class StockBot(commands.Bot): ) self.scheduler.start() - logger.info("Scheduler started for hourly updates and market close") + logger.info("Scheduler started for market open, noon, and market close updates") async def on_ready(self): """Called when bot successfully connects to Discord.""" @@ -85,13 +92,23 @@ class StockBot(commands.Bot): await self.send_startup_announcement() self.startup_announced = True - async def send_hourly_update(self): - """Send hourly stock price update if market is open.""" - if not MarketHours.is_market_open(): - logger.info("Market is closed, skipping hourly update") + async def send_market_open_update(self): + """Send stock price update at market open on trading days.""" + if not MarketHours.is_trading_day(): + logger.info("Not a trading day, skipping market open update") return - logger.info(f"Sending hourly update for {self.primary_ticker}") + logger.info(f"Sending market open update for {self.primary_ticker}") + for channel_id in self.target_channel_ids: + await self.send_stock_update(self.primary_ticker, channel_id) + + async def send_noon_update(self): + """Send stock price update at noon on trading days.""" + if not MarketHours.is_trading_day(): + logger.info("Not a trading day, skipping noon update") + return + + logger.info(f"Sending noon update for {self.primary_ticker}") for channel_id in self.target_channel_ids: await self.send_stock_update(self.primary_ticker, channel_id) @@ -169,6 +186,7 @@ class StockBot(commands.Bot): Discord embed object """ ticker = stock_data['ticker'] + company_name = stock_data.get('company_name', ticker) current_price = stock_data['current_price'] change_dollar = stock_data['change_dollar'] change_percent = stock_data['change_percent'] @@ -192,7 +210,7 @@ class StockBot(commands.Bot): if ticker == "PYPL": title = f"{change_emoji} Steaks Stablecoin Value" else: - title = f"{change_emoji} {ticker} Stock Price" + title = f"{change_emoji} {company_name} ({ticker}) Stock Price" # Create embed embed = discord.Embed( diff --git a/stock_api/finnhub_api.py b/stock_api/finnhub_api.py index 102fa89..19f7a55 100644 --- a/stock_api/finnhub_api.py +++ b/stock_api/finnhub_api.py @@ -33,6 +33,15 @@ class FinnhubAPI(StockAPIBase): Dictionary with stock data or None if unavailable """ try: + # Get company name from company profile + company_name = None + try: + profile = self.client.company_profile2(symbol=ticker) + company_name = profile.get('name') or ticker.upper() + except Exception as e: + logger.warning(f"Could not fetch company name for {ticker}: {e}") + company_name = ticker.upper() + # Get current quote data quote = self.client.quote(ticker) @@ -56,6 +65,7 @@ class FinnhubAPI(StockAPIBase): return { 'ticker': ticker.upper(), + 'company_name': company_name, 'current_price': round(current_price, 2), 'previous_close': round(previous_close, 2), 'change_dollar': round(change_dollar, 2), diff --git a/stock_api/yahoo.py b/stock_api/yahoo.py index 390a749..136e48e 100644 --- a/stock_api/yahoo.py +++ b/stock_api/yahoo.py @@ -23,6 +23,15 @@ class YahooFinanceAPI(StockAPIBase): try: stock = yf.Ticker(ticker) + # Get company name from info + company_name = None + try: + info = stock.info + company_name = info.get('longName') or info.get('shortName') or ticker.upper() + except Exception as e: + logger.warning(f"Could not fetch company name for {ticker}: {e}") + company_name = ticker.upper() + # Use history() method instead of info to avoid rate limiting # Get last 2 days of data to calculate change hist = stock.history(period="2d") @@ -48,6 +57,7 @@ class YahooFinanceAPI(StockAPIBase): return { 'ticker': ticker.upper(), + 'company_name': company_name, 'current_price': round(current_price, 2), 'previous_close': round(previous_close, 2), 'change_dollar': round(change_dollar, 2),