Alpha Vantage market data for PiG agents: quotes, price series, fundamentals, earnings, technical indicators, news sentiment, and US macro series.
What makes it different from a thin API wrapper: every agent on your machine shares one cache and one rate budget. Run eight agents at once and they still spend one Alpha Vantage allowance between them, never pay twice for the same request, and never exceed the rate limit you set.
- Pure Python standard library at runtime: nothing to
pip install. PiG andpython3are enough. - Compact, typed tool output: every number carries a date and its source. Raw JSON never reaches the model.
- Fails loudly. A missing key, an exhausted budget, or an Alpha Vantage error is reported to the model as what it is. Nothing is estimated or made up, and errors are never cached.
PiG starts one extension process per agent. Your Alpha Vantage key, however, has one rate limit: the free tier allows 25 calls per day, and premium tiers cap calls per minute. If each process counted its own calls, eight agents would each believe they had the full allowance. They would burn the day's budget in minutes, and Alpha Vantage would start answering with HTTP 200 "Note" bodies that a naive cache would then store as if they were data.
This extension keeps both the cache and the budget in one SQLite file that every process opens:
flowchart LR
subgraph PiG["PiG: one extension process per agent"]
A1["agent 1<br/>alphavantage.py"]
A2["agent 2<br/>alphavantage.py"]
AN["agent N<br/>alphavantage.py"]
end
subgraph DB["~/.cache/pig-alphavantage/av.db (SQLite, WAL)"]
C[("cache<br/>responses + expiry")]
S[("spend log<br/>rolling minute / day")]
F[("in-flight claims")]
end
A1 & A2 & AN -- "BEGIN IMMEDIATE:<br/>cache hit? claim + spend?" --> DB
A1 & A2 & AN -. "claim owner only,<br/>no lock held" .-> AV["Alpha Vantage API"]
Each request runs the same protocol:
BEGIN IMMEDIATE, so only one process at a time makes the next decision.- If a fresh cached response exists, return it. No budget is spent.
- If another process is already fetching this exact request, wait for its result.
- Otherwise take one call from the budget, claim the request, and commit.
- Call Alpha Vantage with no lock held. Store the response only if it is real data.
The budget is a sliding log of calls, checked over a rolling minute and a rolling day. A refilling token bucket that allows N calls per minute can admit up to 2N calls inside one 60-second window, which is exactly what the provider rejects; the log cannot. The test suite proves these guarantees with real OS processes: eight processes making the same request cause one API call, and eight processes making different requests never exceed the per-minute or per-day limit.
You need PiG and python3 (3.11 or newer). Then:
# from a local checkout
pig install ./pig-alphavantage
# or from git
pig install git:http://github.com/Cpt-Falcon/pig-alphavantageTo try it for one run without installing, load the extension file directly:
pig -e ./pig-alphavantage/extensions/alphavantage/alphavantage.pyTo check that it loads and registers its tools without starting a session:
pig install ./pig-alphavantage/extensions/alphavantage/alphavantage.py --validate-only --json| Environment variable | Default | Meaning |
|---|---|---|
ALPHA_VANTAGE_API_KEY |
(required) | Your key. ALPHAVANTAGE_API_KEY also works. Get a free key. |
PIG_AV_PER_MINUTE |
5 |
Calls allowed in any rolling 60 seconds, across all agents. |
PIG_AV_PER_DAY |
25 |
Calls allowed in any rolling 24 hours. 0 means no daily cap (premium keys). |
PIG_AV_DB |
$XDG_CACHE_HOME/pig-alphavantage/av.db |
The shared cache and budget file (~/.cache/... when XDG_CACHE_HOME is unset). |
For a premium key with 75 calls per minute: export PIG_AV_PER_MINUTE=75 PIG_AV_PER_DAY=0.
The key is read from the environment only. It is never written to the cache, never part of a
cache key, and redacted from any error message that echoes it. Without a key the extension still
loads (so /av status works), and every tool call fails with a message saying which variable to
set.
| Data | Stays fresh |
|---|---|
| Quote, intraday bars | 60 s while prices move (09:30 to 17:00 New York, weekdays); otherwise until the next open |
| Daily bars, and the indicators computed from them | Until 17:00 New York on the next weekday |
| News sentiment | 30 minutes |
| Company overview, earnings, economic series | 24 hours |
| Income statement, balance sheet, cash flow | 7 days |
| Tool | What it returns | API calls |
|---|---|---|
av_quote |
Latest price, open/high/low, previous close, change, volume | 1 |
av_daily |
Up to 100 daily OHLCV bars, newest first, with a period summary | 1 |
av_intraday |
Up to 100 intraday bars (1, 5, 15, 30 or 60 min) | 1 |
av_overview |
Sector, industry, market cap, valuation ratios, margins, growth, 52-week range, analyst target | 1 |
av_financials |
Key lines of the income statement, balance sheet, or cash flow (annual or quarterly) | 1 |
av_earnings |
Quarterly reported vs estimated EPS and surprise % | 1 |
av_indicator |
SMA, EMA, RSI, MACD (12/26/9), or Bollinger Bands | 0 after av_daily |
av_news |
Relevance- and freshness-weighted sentiment, label counts, top topics, latest headlines | 1 |
av_economic |
Real GDP, CPI, inflation, fed funds rate, 10-year Treasury yield, or unemployment | 1 |
Indicators are computed locally from the cached daily series, so a symbol's price history and all five indicators cost one call in total instead of six.
Every result has an asOf date (each row of a series has its own date) and a provenance block
naming the Alpha Vantage function, when the data was fetched, and whether it came from the cache.
Real output from av_quote, captured during development:
{"symbol":"IBM","asOf":"2026-09-25","price":225.51,"open":226.15,"high":228.99,"low":225.19,
"previousClose":227.06,"change":-1.55,"changePercent":-0.6826,"volume":4147449.0,
"provenance":{"source":"Alpha Vantage GLOBAL_QUOTE","fetchedAt":"2026-09-28T04:54:42+00:00","cache":"miss"}}av_indicator with indicator: "RSI", points: 3, from the same development session. It was served
from the daily series that an av_daily call had just cached, so it spent nothing:
{"symbol":"IBM","indicator":"RSI","period":14,"asOf":"2026-09-25",
"method":"computed locally from 100 daily closes (2026-05-05..2026-09-25); null = warm-up",
"columns":["date","rsi"],"values":[["2026-09-25",41.1671],["2026-09-24",42.3582],["2026-09-23",47.002]],
"provenance":{"source":"Alpha Vantage TIME_SERIES_DAILY","fetchedAt":"2026-09-28T05:09:03+00:00","cache":"hit"}}When something goes wrong the tool returns an error the model can act on, for example:
av_quote failed: Alpha Vantage day budget exhausted (25/25 calls used); a call frees up in 3121s. No request was sent.
av_quote failed: Alpha Vantage rate_limited: Thank you for using Alpha Vantage! Our standard API rate limit is 25 requests per day...
av_daily failed: days must be an integer from 1 to 100, got 500
/avor/av statusshows the shared budget (calls this minute, calls today) and the cache (entries, size, hit rate). The numbers cover every agent that uses the same db file./av clear-cachedeletes cached responses. Calls already made still count against the budget.
After every call the extension updates a status line such as AV 23/25 left today.
The extension is a capability: install it and any PiG session gains the av_* tools
alongside whatever else it does. Use it when market data is one ingredient of your work.
A Piglet is a whole agent. piglets/av-analyst.yaml defines an
equity analyst that has only the Alpha Vantage tools (no file access, no shell, and av_intraday
scoped out), loads the av-research skill that teaches it to
spend the budget carefully, and sets its own system prompt. Use a Piglet when you want an agent
you can hand to someone and have it run the same way every time:
pig --piglet ./pig-alphavantage/piglets/av-analyst.yaml -p "How has IBM traded this month, and is it expensive?"The Piglet takes the extension and skill from this package's git repository, because PiG only lets a Piglet reach local files inside the Piglet's own directory.
uv sync # dev tools only; the extension itself has no dependencies
uv run pytest # offline: fake transport, no network, includes the multi-process tests
uv run mypy # strict
uv run ruff check . && uv run ruff format --check .
PIG_AV_LIVE=1 ALPHA_VANTAGE_API_KEY=... uv run pytest -m live # one real API callLayout:
package.json PiG/Pi package manifest (extension + skill)
extensions/alphavantage/
alphavantage.py PiG factory entrypoint: def new_extension()
pig_alphavantage/
constants.py Alpha Vantage, PiG, and environment names as enums and constants
config.py settings from the environment (the only place the key is read)
db.py the shared SQLite file: WAL, busy timeout, BEGIN IMMEDIATE
ratelimit.py rolling minute and day budget
cache.py read-through cache, in-flight dedupe, and budget in one protocol
policy.py cache freshness table
client.py HTTP transport and Alpha Vantage error-body detection
parse.py typed access to Alpha Vantage JSON
indicators.py SMA, EMA, RSI, MACD, Bollinger Bands
condense.py raw payloads to compact typed outputs
tools.py tool schemas and argument validation
extension.py registers the tools, /av, and the status line
skills/av-research/SKILL.md budget-aware research procedure
piglets/av-analyst.yaml example whole-agent Piglet
tests/ pytest suite (fake transport, multi-process, opt-in live)
- The budget covers one machine and one db file. Agents on other machines, or other programs using the same key, are invisible to it. Alpha Vantage may then refuse a call; the extension reports the refusal and does not cache it.
- The daily window is a rolling 24 hours, which is conservative: Alpha Vantage does not document exactly when its daily allowance resets.
- Market hours ignore exchange holidays. On a holiday a quote is refreshed more often than needed and the daily series is fetched once more.
- Indicators use the last 100 daily closes (the free
compactseries), so long lookbacks such as a 200-day SMA are not available; the period is capped at 60. - Premium-only endpoints return an Alpha Vantage "Information" error on a free key; the tool reports it rather than working around it.
- The db file needs a local filesystem. SQLite WAL mode does not work on network filesystems.
- Windows needs the
tzdatapackage for Python's time-zone database. - Piglet tool scoping in PiG 0.2.0. When the example Piglet ran under
pig -pduring development, PiG printed[piglet] No tools registered yet: skipping scoping, and the built-inreadtool stayed available despitetools: []. The Alpha Vantage tools themselves worked.
MIT. See LICENSE. Not affiliated with Alpha Vantage Inc. Market data is subject to Alpha Vantage's terms.