Last month I missed a 12% move on AMD because I was heads-down in a deploy. My broker’s mobile alerts? Delayed by 3 minutes. Robinhood’s push notifications? Unreliable on Android. I decided to build my own alert system that hits me on Telegram the instant a price crosses my threshold.
The whole thing took 30 minutes, costs $0/month, and runs on a single Python script. Here’s exactly how I set it up using Finnhub’s free WebSocket API.
Why Not Just Use TradingView Alerts?
TradingView’s free tier gives you one alert. One. Their Pro plan is $15/month for more. Yahoo Finance alerts are email-only with 15-minute delays on the free tier. I wanted real-time price crosses delivered to my phone in under 2 seconds, for unlimited tickers, for $0.
Finnhub’s free tier gives you 60 API calls/second and real-time WebSocket access for US stocks. That’s more than enough for a personal alert system watching 20-30 tickers.
The Architecture (It’s Embarrassingly Simple)
The setup is three pieces:
- A Python script that connects to Finnhub’s WebSocket and watches for price crosses
- A JSON config file with your tickers and thresholds
- A Telegram bot that pings your phone
No database. No server framework. No Docker. Just a script running in a tmux session on any Linux box (I use a $5 VPS, but a Raspberry Pi works too).
Setting Up Finnhub WebSocket
First, grab a free API key from finnhub.io/register. No credit card required. Then:
pip install websocket-client requests
The core connection is straightforward:
import websocket
import json
FINNHUB_KEY = "your_api_key"
def on_message(ws, message):
data = json.loads(message)
if data.get("type") == "trade":
for trade in data["data"]:
symbol = trade["s"]
price = trade["p"]
check_alerts(symbol, price)
def on_open(ws):
for symbol in ["AAPL", "AMD", "NVDA", "TSLA"]:
ws.send(json.dumps({"type": "subscribe", "symbol": symbol}))
ws = websocket.WebSocketApp(
f"wss://ws.finnhub.io?token={FINNHUB_KEY}",
on_message=on_message,
on_open=on_open
)
ws.run_forever()
That’s it for the data feed. You’re getting real-time trades within milliseconds of execution.
The Alert Logic
I keep alerts in a simple JSON file:
{
"alerts": [
{"symbol": "AMD", "above": 185.00, "note": "breakout level"},
{"symbol": "NVDA", "below": 800.00, "note": "support break"},
{"symbol": "AAPL", "above": 195.00, "note": "new high"}
]
}
The check function fires once per threshold crossing (not on every tick), then disables itself so you don’t get spammed:
triggered = set()
def check_alerts(symbol, price):
for alert in alerts:
if alert["symbol"] != symbol:
continue
key = f"{symbol}_{alert.get('above', alert.get('below'))}"
if key in triggered:
continue
if "above" in alert and price >= alert["above"]:
send_telegram(f"๐จ {symbol} crossed above ${alert['above']:.2f} - now ${price:.2f}\n๐ {alert['note']}")
triggered.add(key)
elif "below" in alert and price <= alert["below"]:
send_telegram(f"๐จ {symbol} dropped below ${alert['below']:.2f} - now ${price:.2f}\n๐ {alert['note']}")
triggered.add(key)
Telegram Delivery (Sub-Second)
Creating a Telegram bot takes 60 seconds โ message @BotFather, pick a name, get a token. Then:
import requests
BOT_TOKEN = "your_bot_token"
CHAT_ID = "your_chat_id"
def send_telegram(msg):
requests.post(
f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage",
json={"chat_id": CHAT_ID, "text": msg}
)
Average delivery time from price cross to phone buzz: 800ms. I measured it over a week. Compare that to Robinhood’s 2-3 minute delay or Yahoo’s 15-minute email lag.
Production Hardening (15 More Minutes)
The basic script works, but I added three things for reliability:
Auto-reconnect: WebSocket connections drop. Finnhub disconnects idle connections after 5 minutes of no data (weekends, after hours). Add exponential backoff:
import time
def on_close(ws, close_status, msg):
time.sleep(5)
connect() # re-establish
Daily alert reset: I run a cron at 9:25 AM ET that clears the triggered set, so alerts can fire again each trading day.
Health check: A separate cron pings me if the script hasn’t sent a heartbeat in 10 minutes during market hours. Simple touch /tmp/finnhub_alive on each message, then check file age.
What I’d Change
After running this for 6 weeks, a few observations:
- Percentage-based alerts would be more useful than fixed prices for volatile tickers. I’m adding “alert me if TSLA moves 3% in 5 minutes” logic next.
- Volume spikes matter more than price alone. Finnhub’s WebSocket includes volume data โ I should be using it.
- The free tier limits you to US stocks. If you need crypto, their crypto WebSocket is separate but also free.
Cost Comparison
| Service | Real-time alerts | Monthly cost | Delivery speed |
|---|---|---|---|
| TradingView Pro | 20 | $15 | ~5s |
| Yahoo Finance Premium | Unlimited | $35 | 15min (email) |
| This setup | Unlimited | $0 | <1s |
The tradeoff: you need a machine running 24/5. A Raspberry Pi 4 draws 3W and handles this easily. If you already have a homelab or VPS, there’s no additional cost.
Running It
I keep mine in a tmux session on my Beelink mini PC that also runs Home Assistant and a few other services. Total power draw: 15W for my entire home automation + market alerts stack.
If you want something more structured, check out my post on tracking congressional stock trades โ same philosophy of building your own financial tools instead of paying for overpriced SaaS.
The full script (with reconnect logic and config loading) is about 80 lines of Python. Nothing fancy. That’s the point โ financial tools don’t need to be complex to be useful.
Full disclosure: Raspberry Pi and Beelink links are affiliate links.
๐ก Want daily market signals and trading intelligence? Join Alpha Signal on Telegram โ free market narratives, sector analysis, and conviction scores every morning.
๐ง Get weekly insights on security, trading, and tech. No spam, unsubscribe anytime.
Leave a Reply