Project Detail

Stock Trading News Alert

Stock Trading News Alert watches a ticker (default: TSLA) every morning, fetches the two most recent closing prices from Alpha Vantage, and calculates the percentage change overnight. If the move clears a threshold, it pulls the top three related headlines from NewsAPI and fires one WhatsApp message per article through Twilio. The advanced build refactors the course script into three single-responsibility classes — StockClient, NewsClient, and SmsSender — wired together by a clean orchestrator, with every constant centralised in config.py and a GitHub Actions workflow running the whole thing on a weekday schedule automatically.

Software API-integration automation OOP python REST-API scripting terminal-ux

Quick Facts

Tech:
Python Twilio Alpha Vantage API NewsAPI python-dotenv GitHub Actions

Overview

Problem

Keeping up with stock movements manually means either staring at a ticker all day or missing a big move entirely. Most retail investors want a simple "something happened, here's why" nudge — not a dashboard to babysit. The course exercise surfaced an extra wrinkle: Twilio trial accounts restrict outbound SMS to a verified number tied to that specific account, so the alert would silently fail for anyone who hadn't pre-registered their number. There also wasn't a guard against hammering the daily message cap, which on a trial account sits at around nine SMS — easy to blow through if you're testing or if the threshold is set to zero.

Solution

The original build chains three REST APIs in a single script: Alpha Vantage for OHLCV data, NewsAPI for recent headlines, and Twilio for delivery. The advanced build splits this into three classes — StockClient handles the Alpha Vantage fetch and returns a (perc_diff, abs_diff) tuple; NewsClient queries NewsAPI and returns a list of article dicts; SmsSender wraps Twilio, enforces a local daily quota via a small JSON file in advanced/data/, and exposes a build_body() classmethod for formatting. The channel switch (SMS vs WhatsApp) lives in config.py as a single CHANNEL constant — main.py reads it and picks the right environment variables and character limit, so flipping between delivery modes is a one-line change. A GitHub Actions workflow runs the script on weekdays at 06:00 UTC with all credentials loaded from repository secrets.

Challenges

The trickiest part was the Twilio trial account restriction — the SMS from-number worked in the course demo but threw a 21660 "number mismatch" error on a different account because trial accounts only allow sending from their own verified number. Switching to the WhatsApp sandbox (whatsapp:+14155238886) solved it cleanly since that number is shared across all Twilio trial accounts. Getting the character limit right for WhatsApp vs SMS also needed care: SMS has a hard UCS-2 segment limit of around 70 characters, but WhatsApp has a 4096-character ceiling, so the same clamp_ucs2() helper needed a configurable limit rather than a hardcoded 65. The local quota guard had a subtle path bug too — QUOTA_FILE was originally set with Path(".sms_quota.json"), which resolves relative to the working directory at runtime; when launched from menu.py with a different cwd, the file landed in the wrong place. Anchoring it to Path(__file__).parent fixed it permanently.

Results / Metrics

The project demonstrates how to wire multiple REST APIs together in a clean, testable architecture — each module owns exactly one concern and could be swapped out without touching the others. It also shows how to handle real-world API friction: trial account restrictions, rate-limit responses, and daily quota management. The GitHub Actions workflow means the alert actually runs automatically every weekday without any manual intervention, which turns a course exercise into a genuinely useful tool. If I were extending it, I'd add a portfolio of tickers (not just TSLA), persist the last-seen percentage change to avoid re-alerting on the same move, and look at NewsAPI's paid tier for same-day articles — the free tier has a 24-hour delay that blunts the relevance of the headlines.

Screenshots

Click to enlarge.

Click to enlarge.

No screenshots available yet.

Videos

No videos available yet.