7.3 KiB
7.3 KiB
name, description, version, author, metadata
| name | description | version | author | metadata | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| finance-search | Free finance APIs for stock, ETF, and mutual fund data — yfinance (no key), Alpha Vantage, Polygon.io, Twelve Data. Multi-backend with automatic fallback. | 1.1.0 | Hermes Agent |
|
finance-search — Free Finance APIs
Multi-backend finance data skill. Primary: yfinance (no API key). Fallbacks: Alpha Vantage, Polygon.io, Twelve Data (free keys required).
Backends
| Backend | Key Required | Rate Limit | Best For |
|---|---|---|---|
| yfinance | No | IP-based (Yahoo) | Stock/ETF/mutual fund prices, history, info |
| Alpha Vantage | Free key | 25/day | Historical data, fundamentals, FX |
| Polygon.io | Free key | 5/min | Real-time prices, ticker details |
| Twelve Data | Free key | 800/day | Historical data, technical indicators |
Setup
yfinance (no key — works immediately)
pip install yfinance
Alpha Vantage (free key)
- Go to https://www.alphavantage.co/support/#api-key
- Fill in name, email, organization (any values work)
- Click "GET FREE API KEY"
- Copy the key from the page
- Set env:
export ALPHA_VANTAGE_API_KEY=your_key
Polygon.io (free key)
- Go to https://polygon.io/dashboard/signup
- Sign up with email and password
- Verify email (check inbox for confirmation link)
- Log in, go to Dashboard → API Keys
- Copy the "Default" key
- Set env:
export POLYGON_API_KEY=your_key
Twelve Data (free key)
- Go to https://twelvedata.com/apikey
- Click "Get Free API Key"
- Sign up with email or Google/GitHub
- Key is shown immediately on the dashboard
- Set env:
export TWELVE_DATA_API_KEY=your_key
Getting API Keys — Agent Directive
When a backend fails because no API key is set, do NOT just report the failure. Proactively obtain a key:
- Check which backends are missing keys:
echo $ALPHA_VANTAGE_API_KEY,echo $POLYGON_API_KEY,echo $TWELVE_DATA_API_KEY - For each missing key, open the signup URL in the browser tool and walk through the signup flow
- Save each key to
~/.hermes/.envand the active profile's.env:echo 'ALPHA_VANTAGE_API_KEY=abc123' >> ~/.hermes/.env echo 'ALPHA_VANTAGE_API_KEY=abc123' >> ~/.hermes/profiles/general/.env - Verify:
curl -s "https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=IBM&apikey=$ALPHA_VANTAGE_API_KEY" | python3 -c "import sys,json; d=json.load(sys.stdin); print('OK' if 'Global Quote' in d else 'FAIL: '+str(d))"
Priority order for obtaining keys: Twelve Data first (800/day, best free tier), then Polygon (5/min, good for spot checks), then Alpha Vantage (25/day, last resort). Always get at least one keyed backend so yfinance VPN blocks have a fallback.
Usage
Stock/ETF/Mutual Fund Performance
import yfinance as yf
# Single ticker
ticker = yf.Ticker("FZROX")
hist = ticker.history(period="1y")
info = ticker.info
# Key fields
print(f"Name: {info.get('longName')}")
print(f"Category: {info.get('category')}")
print(f"Expense Ratio: {info.get('annualReportExpenseRatio')}")
print(f"1Y Return: {((hist['Close'].iloc[-1] - hist['Close'].iloc[0]) / hist['Close'].iloc[0]) * 100:.2f}%")
Multi-Ticker Comparison
import yfinance as yf
import json
tickers = {
"FZROX": "Fidelity ZERO Total Market",
"FNILX": "Fidelity ZERO Large Cap",
"FZIPX": "Fidelity ZERO Extended Market",
"FZILX": "Fidelity ZERO International",
}
results = {}
for t, name in tickers.items():
f = yf.Ticker(t)
h = f.history(period="1y")
if not h.empty:
ret = ((h['Close'].iloc[-1] - h['Close'].iloc[0]) / h['Close'].iloc[0]) * 100
results[t] = {
"name": name,
"return_1y_pct": round(ret, 2),
"start": round(h['Close'].iloc[0], 2),
"end": round(h['Close'].iloc[-1], 2),
"expense_ratio": f.info.get('annualReportExpenseRatio', 'N/A'),
}
print(json.dumps(results, indent=2))
Alpha Vantage Fallback
import os, requests
key = os.environ.get("ALPHA_VANTAGE_API_KEY")
if key:
url = f"https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=FZROX&apikey={key}"
data = requests.get(url).json()
Polygon.io Fallback
import os, requests
key = os.environ.get("POLYGON_API_KEY")
if key:
url = f"https://api.polygon.io/v2/aggs/ticker/FZROX/prev?apiKey={key}"
data = requests.get(url).json()
Twelve Data Fallback
import os, requests
key = os.environ.get("TWELVE_DATA_API_KEY")
if key:
url = f"https://api.twelvedata.com/time_series?symbol=FZROX&interval=1day&outputsize=365&apikey={key}"
data = requests.get(url).json()
Auto-Fallback Pattern
Try backends in order. First success wins:
import yfinance as yf, os, requests, json
def get_fund_performance(ticker, period="1y"):
# 1. Try yfinance (no key)
try:
f = yf.Ticker(ticker)
h = f.history(period=period)
if not h.empty:
ret = ((h['Close'].iloc[-1] - h['Close'].iloc[0]) / h['Close'].iloc[0]) * 100
return {"source": "yfinance", "ticker": ticker, "return_pct": round(ret, 2)}
except:
pass
# 2. Try Alpha Vantage
key = os.environ.get("ALPHA_VANTAGE_API_KEY")
if key:
try:
url = f"https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol={ticker}&outputsize=full&apikey={key}"
r = requests.get(url, timeout=10)
if r.status_code == 200:
return {"source": "alphavantage", "ticker": ticker, "raw": r.json()}
except:
pass
# 3. Try Polygon
key = os.environ.get("POLYGON_API_KEY")
if key:
try:
url = f"https://api.polygon.io/v2/aggs/ticker/{ticker}/prev?apiKey={key}"
r = requests.get(url, timeout=10)
if r.status_code == 200:
return {"source": "polygon", "ticker": ticker, "raw": r.json()}
except:
pass
# 4. Try Twelve Data
key = os.environ.get("TWELVE_DATA_API_KEY")
if key:
try:
url = f"https://api.twelvedata.com/time_series?symbol={ticker}&interval=1day&outputsize=365&apikey={key}"
r = requests.get(url, timeout=10)
if r.status_code == 200:
return {"source": "twelvedata", "ticker": ticker, "raw": r.json()}
except:
pass
return {"error": f"All backends failed for {ticker}"}
Common Fidelity Zero Tickers
| Ticker | Name |
|---|---|
| FZROX | Fidelity ZERO Total Market Index |
| FNILX | Fidelity ZERO Large Cap Index |
| FZIPX | Fidelity ZERO Extended Market Index |
| FZILX | Fidelity ZERO International Index |
Pitfalls
- yfinance blocked on VPN IPs. Yahoo rate-limits shared/VPN IPs. If
fc.yahoo.comconnection refused, rotate VPN (nordvpnskill) or use a keyed backend. - Mutual fund data is delayed. Yahoo Finance mutual fund prices are typically T+1. Don't expect real-time.
- Alpha Vantage free tier is 25 requests/day. Don't use for bulk queries.
- Polygon free tier is 5 requests/minute. Good for spot checks, not streaming.
- Twelve Data free tier is 800 requests/day. Best free tier for volume.
- Some tickers may be delisted or unavailable. yfinance will warn. Check the ticker on Yahoo Finance first.