data feeds = foundation of algo trading.
garbage data = garbage trades.
i’ve used both polygon.io and alpha vantage extensively.
spent months researching data feeds when i started trading. NexusFi community helped narrow down options to these two.
here’s the real comparison.
what i need from data feeds #
1. historical data
backtesting requires years of data.
need:
- daily bars (2+ years)
- intraday bars (1+ year)
- options data (greeks, chain)
2. real-time data
live trading requires:
- <100ms latency
- reliable websocket
- no gaps/missing bars
3. API quality
python integration must be:
- well documented
- stable endpoints
- reasonable rate limits
4. cost
paying for what i actually use.
not enterprise pricing for retail needs.
polygon.io - my primary feed #
what i use it for:
stocks, options, real-time websocket.
pricing (my tier):
$199/month - starter plan
- unlimited historical
- real-time websocket
- options data included
pros:
-
speed: 50-80ms latency on websocket
-
reliability: 99.8% uptime (i track it)
-
options data: full chain, greeks, IV
-
documentation: excellent python examples
-
rate limits: generous (100 req/min)
cons:
-
cost: $199/month (not cheap for retail)
-
learning curve: REST + websocket combo
-
options lag: greeks update every 5min (not real-time)
code example:
from polygon import RESTClient
from polygon import WebSocketClient
import asyncio
# REST client for historical data
rest_client = RESTClient(api_key="YOUR_KEY")
def get_historical_bars(symbol, from_date, to_date):
"""
Get historical daily bars from Polygon
"""
aggs = rest_client.get_aggs(
ticker=symbol,
multiplier=1,
timespan="day",
from_=from_date,
to=to_date,
limit=50000
)
bars = []
for agg in aggs:
bars.append({
'timestamp': agg.timestamp,
'open': agg.open,
'high': agg.high,
'low': agg.low,
'close': agg.close,
'volume': agg.volume
})
return bars
# Websocket client for real-time data
def handle_msg(msgs):
"""Process real-time messages"""
for msg in msgs:
if msg['ev'] == 'A': # Aggregate (bar)
print(f"Symbol: {msg['sym']}")
print(f"Close: ${msg['c']:.2f}")
print(f"Volume: {msg['v']:,}")
async def run_websocket():
"""Real-time data stream"""
ws = WebSocketClient(
api_key="YOUR_KEY",
feed='stocks',
on_message=handle_msg
)
# Subscribe to SPY 1-minute bars
ws.subscribe('A.SPY')
await ws.run()
# Usage
historical = get_historical_bars('SPY', '2023-01-01', '2024-02-11')
print(f"Retrieved {len(historical)} bars")
# Real-time streaming
asyncio.run(run_websocket())
real performance (my experience):
january 2024:
- 2.3M API calls
- 99.9% success rate
- avg latency: 67ms
- 0 outages
worth $199/month for serious trading.
alpha vantage - backup feed #
what i use it for:
backup historical data, free tier testing.
pricing (my tier):
free tier:
- 25 API calls per day
- 5 calls per minute
premium: $49.99/month
- 1200 calls per day
- still rate limited
pros:
-
cost: free tier exists
-
simplicity: REST-only, easy to learn
-
crypto included: btc/eth data free
-
fundamental data: earnings, balance sheets
cons:
-
rate limits: brutal (5/min on free, still limited on paid)
-
no websocket: REST polling only (high latency)
-
reliability: occasional downtime/slow responses
-
no options: stocks only (no greeks, no chain)
code example:
import requests
import time
ALPHA_VANTAGE_KEY = "YOUR_KEY"
def get_intraday_data(symbol, interval='5min'):
"""
Get intraday bars from Alpha Vantage
Rate limited to 5 calls per minute
"""
url = f"https://www.alphavantage.co/query"
params = {
'function': 'TIME_SERIES_INTRADAY',
'symbol': symbol,
'interval': interval,
'apikey': ALPHA_VANTAGE_KEY,
'outputsize': 'full'
}
response = requests.get(url, params=params)
data = response.json()
# Check for rate limit
if 'Note' in data:
print("Rate limit hit - waiting 60 seconds")
time.sleep(60)
return get_intraday_data(symbol, interval)
# Parse time series
time_series = data.get(f'Time Series ({interval})', {})
bars = []
for timestamp, values in time_series.items():
bars.append({
'timestamp': timestamp,
'open': float(values['1. open']),
'high': float(values['2. high']),
'low': float(values['3. low']),
'close': float(values['4. close']),
'volume': int(values['5. volume'])
})
return bars
def get_daily_data(symbol):
"""
Get daily historical data
Full history (20+ years available)
"""
url = f"https://www.alphavantage.co/query"
params = {
'function': 'TIME_SERIES_DAILY_ADJUSTED',
'symbol': symbol,
'apikey': ALPHA_VANTAGE_KEY,
'outputsize': 'full'
}
response = requests.get(url, params=params)
data = response.json()
time_series = data.get('Time Series (Daily)', {})
bars = []
for timestamp, values in time_series.items():
bars.append({
'timestamp': timestamp,
'open': float(values['1. open']),
'high': float(values['2. high']),
'low': float(values['3. low']),
'close': float(values['4. close']),
'adjusted_close': float(values['5. adjusted close']),
'volume': int(values['6. volume'])
})
return bars
# Usage with rate limit handling
spy_intraday = get_intraday_data('SPY', '5min')
print(f"Retrieved {len(spy_intraday)} 5-minute bars")
time.sleep(12) # Wait for rate limit (5 calls/min = 12 sec between)
spy_daily = get_daily_data('SPY')
print(f"Retrieved {len(spy_daily)} daily bars")
real performance (my experience):
free tier:
- 25 calls per day = useless for live trading
- frequent “please wait” responses
- occasional 500 errors
premium tier ($49/month):
- 1200 calls per day = ~50/hour
- still too limited for real-time
- better for EOD strategies only
good for testing, not for production.
head-to-head comparison #
| Feature | Polygon.io | Alpha Vantage |
|---|---|---|
| Price | $199/month | Free / $49.99/month |
| Historical data | Unlimited | Limited calls |
| Real-time | Websocket, <100ms | REST polling, 1-5 sec |
| Options data | Full chain + greeks | None |
| Rate limits | 100/min | 5/min (free), 75/min (paid) |
| Reliability | 99.8% | ~95% |
| Latency | 50-80ms | 1000-5000ms |
| Python support | Excellent | Basic |
| Learning curve | Moderate | Easy |
when to use each #
polygon.io:
- serious algo trading
- options strategies
- real-time execution
- need reliability
alpha vantage:
- learning/testing
- EOD strategies only
- tight budget
- fundamental analysis
my current setup #
primary: polygon.io ($199/month)
backup: alpha vantage free tier
why both?
polygon outage = switch to alpha vantage for EOD data.
happened once in 2023.
saved my ass.
redundancy matters.
other feeds i’ve tested #
IEX cloud:
- good real-time
- expensive for retail
- limited historical
yahoo finance (yfinance python):
- free
- unreliable
- rate limited randomly
- banned my IP twice
quandl:
- expensive
- academic data focus
- not for day trading
thetadata:
- options specialist
- great for greeks
- too expensive ($150/month just options)
polygon wins for all-around use.
cost justification #
polygon: $199/month
lost $40k march 2023 on bad backtest (garbage data contributed).
$199/month = $2,388/year
saved that in one trade by having reliable data.
worth it.
rate limit handling #
polygon rate limits: 100 req/min
never hit it in production.
alpha vantage: 5 req/min free, 75 paid
hit it constantly.
solution for alpha vantage:
import time
from datetime import datetime
class RateLimitedClient:
"""
Wrapper for Alpha Vantage with automatic rate limiting
"""
def __init__(self, api_key, calls_per_minute=5):
self.api_key = api_key
self.calls_per_minute = calls_per_minute
self.min_interval = 60.0 / calls_per_minute # Seconds between calls
self.last_call_time = 0
def call_api(self, url, params):
"""
Make API call with automatic rate limiting
"""
# Calculate wait time
elapsed = time.time() - self.last_call_time
if elapsed < self.min_interval:
wait_time = self.min_interval - elapsed
print(f"Rate limit: waiting {wait_time:.1f} seconds")
time.sleep(wait_time)
# Make call
params['apikey'] = self.api_key
response = requests.get(url, params=params)
# Update last call time
self.last_call_time = time.time()
return response.json()
# Usage
client = RateLimitedClient(api_key="YOUR_KEY", calls_per_minute=5)
# This will automatically space calls 12 seconds apart
for symbol in ['SPY', 'QQQ', 'IWM', 'DIA', 'GLD']:
data = client.call_api(
"https://www.alphavantage.co/query",
{'function': 'TIME_SERIES_DAILY', 'symbol': symbol}
)
print(f"Retrieved {symbol} data")
makes alpha vantage tolerable.
data quality comparison #
tested on same day (feb 1, 2024):
SPY close price discrepancies:
polygon: $491.62
alpha vantage: $491.62
yahoo finance: $491.58 (off by $0.04)
polygon and alpha vantage match.
yahoo occasionally wrong.
never use yahoo for production.
tonight #
polygon.io = primary feed, $199/month, worth every dollar.
alpha vantage = backup, free tier adequate for emergencies.
yahoo finance = never for production.
data quality = edge protection.
garbage data destroys accounts.
2:47am sunday. data feed comparison. polygon.io $199/month primary feed - 50-80ms latency, options data, 99.8% reliability. alpha vantage backup - free tier adequate for testing, rate limits brutal for production. lost $40k march 2023 partly from bad data - $199/month cheap insurance.
-AK