Last month, my friend paid $49/month for a stock tracking tool. I built the same thing for free in 45 minutes using Alpha Vantage API.
Here's exactly how.
Why Alpha Vantage?
Most stock APIs either cost money (Bloomberg Terminal: $24,000/year) or require complex authentication. Alpha Vantage gives you:
- Real-time & historical stock prices (every US stock)
- Technical indicators (RSI, MACD, Bollinger Bands — 50+ indicators)
- Forex & crypto prices
- Fundamental data (earnings, balance sheets, income statements)
- Free tier: 25 requests/day (enough for a personal dashboard)
Step 1: Get Your Free API Key
# Sign up at alphavantage.co (takes 10 seconds)
# Your key looks like: ABCD1234EFGH5678
export ALPHA_VANTAGE_KEY="your_key_here"
pip install requests pandas matplotlib
Step 2: Fetch Real-Time Stock Prices
import requests
import pandas as pd
API_KEY = "your_key_here"
def get_stock_price(symbol):
"""Get current price for any stock ticker."""
url = f"https://www.alphavantage.co/query"
params = {
"function": "GLOBAL_QUOTE",
"symbol": symbol,
"apikey": API_KEY
}
data = requests.get(url, params=params).json()
quote = data["Global Quote"]
return {
"symbol": quote["01. symbol"],
"price": float(quote["05. price"]),
"change": float(quote["09. change"]),
"change_percent": quote["10. change percent"],
"volume": int(quote["06. volume"]),
}
# Check Apple stock right now
apple = get_stock_price("AAPL")
print(f"AAPL: ${apple['price']} ({apple['change_percent']})")
Step 3: Get Historical Data & Create Charts
import matplotlib.pyplot as plt
def get_daily_history(symbol, days=90):
"""Fetch daily prices for the last N days."""
url = "https://www.alphavantage.co/query"
params = {
"function": "TIME_SERIES_DAILY",
"symbol": symbol,
"outputsize": "compact", # Last 100 days
"apikey": API_KEY
}
data = requests.get(url, params=params).json()
ts = data["Time Series (Daily)"]
df = pd.DataFrame.from_dict(ts, orient="index")
df.index = pd.to_datetime(df.index)
df = df.sort_index()
df.columns = ["open", "high", "low", "close", "volume"]
df = df.astype(float)
return df.tail(days)
# Plot AAPL vs MSFT
fig, ax = plt.subplots(figsize=(12, 6))
for symbol in ["AAPL", "MSFT", "GOOGL"]:
df = get_daily_history(symbol)
# Normalize to percentage change
normalized = (df["close"] / df["close"].iloc[0] - 1) * 100
ax.plot(normalized.index, normalized.values, label=symbol)
ax.set_title("Stock Performance Comparison (90 days)")
ax.set_ylabel("% Change")
ax.legend()
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig("stock_comparison.png", dpi=150)
print("Chart saved!")
Step 4: Add Technical Indicators
This is where Alpha Vantage shines. Bloomberg charges thousands for this data:
def get_rsi(symbol, period=14):
"""Relative Strength Index — is the stock overbought/oversold?"""
params = {
"function": "RSI",
"symbol": symbol,
"interval": "daily",
"time_period": period,
"series_type": "close",
"apikey": API_KEY
}
data = requests.get(
"https://www.alphavantage.co/query", params=params
).json()
latest = list(data["Technical Analysis: RSI"].items())[0]
return float(latest[1]["RSI"])
rsi = get_rsi("AAPL")
if rsi > 70:
print(f"⚠️ AAPL RSI={rsi:.1f} — Overbought! Consider selling.")
elif rsi < 30:
print(f"📈 AAPL RSI={rsi:.1f} — Oversold! Potential buying opportunity.")
else:
print(f"AAPL RSI={rsi:.1f} — Neutral zone.")
Step 5: Build a Simple Alert System
import time
WATCHLIST = {
"AAPL": {"buy_below": 170, "sell_above": 200},
"MSFT": {"buy_below": 380, "sell_above": 450},
"NVDA": {"buy_below": 800, "sell_above": 1000},
}
def check_alerts():
"""Check all stocks against your price targets."""
alerts = []
for symbol, targets in WATCHLIST.items():
stock = get_stock_price(symbol)
price = stock["price"]
if price < targets["buy_below"]:
alerts.append(
f"🟢 BUY {symbol}: ${price} (target: <${targets['buy_below']})"
)
elif price > targets["sell_above"]:
alerts.append(
f"🔴 SELL {symbol}: ${price} (target: >${targets['sell_above']})"
)
return alerts
# Run once (or schedule with cron)
for alert in check_alerts():
print(alert)
Step 6: Fundamental Analysis (Earnings, Revenue)
def get_earnings(symbol):
"""Get quarterly earnings data."""
params = {
"function": "EARNINGS",
"symbol": symbol,
"apikey": API_KEY
}
data = requests.get(
"https://www.alphavantage.co/query", params=params
).json()
for q in data["quarterlyEarnings"][:4]:
surprise = float(q["surprisePercentage"]) if q["surprisePercentage"] != "None" else 0
emoji = "✅" if surprise > 0 else "❌"
print(f"{emoji} {q['fiscalDateEnding']}: "
f"EPS ${q['reportedEPS']} "
f"(expected ${q['estimatedEPS']}) "
f"Surprise: {surprise:+.1f}%")
get_earnings("AAPL")
The Complete Dashboard (Put It All Together)
def stock_dashboard(symbol):
"""One function to rule them all."""
price = get_stock_price(symbol)
rsi = get_rsi(symbol)
history = get_daily_history(symbol, 30)
avg_30d = history["close"].mean()
trend = "📈 Uptrend" if price["price"] > avg_30d else "📉 Downtrend"
print(f"\n{=*50}")
print(f" {symbol} Dashboard")
print(f"{=*50}")
print(f" Price: ${price['price']:.2f} ({price['change_percent']})")
print(f" Volume: {price['volume']:,}")
print(f" RSI(14): {rsi:.1f}")
print(f" 30d Avg: ${avg_30d:.2f}")
print(f" Trend: {trend}")
print(f"{=*50}\n")
# Your free Bloomberg Terminal:
for ticker in ["AAPL", "MSFT", "GOOGL"]:
stock_dashboard(ticker)
Alpha Vantage vs Paid Alternatives
| Feature | Alpha Vantage (Free) | Yahoo Finance API ($100/mo) | Bloomberg ($24K/yr) |
|---|---|---|---|
| Real-time prices | ✅ | ✅ | ✅ |
| Technical indicators | ✅ 50+ | ❌ | ✅ |
| Fundamental data | ✅ | Limited | ✅ |
| Rate limit | 25/day free | 500/day | Unlimited |
| Price | $0 | $100/mo | $2,000/mo |
What I Built With This
I used these exact functions to build:
- A daily stock screener that runs via cron job
- A portfolio tracker that emails me weekly performance
- An earnings alert bot that notifies me before earnings dates
The entire codebase is on my GitHub.
Want me to build something like this for your data source? I build custom API integrations, scrapers, and data pipelines. Check my portfolio or find me on GitHub.
Previously in this series: SEC EDGAR API | FRED API | US Treasury API
Top comments (0)