Skip to content

About

Alpha Vantage market data for PiG agents: nine typed tools, one SQLite cache and rate budget shared by every agent on the machine. Python extension + example Piglet.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

pig-alphavantage

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 and python3 are 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.

Why a shared budget matters

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"]
Loading

Each request runs the same protocol:

  1. BEGIN IMMEDIATE, so only one process at a time makes the next decision.
  2. If a fresh cached response exists, return it. No budget is spent.
  3. If another process is already fetching this exact request, wait for its result.
  4. Otherwise take one call from the budget, claim the request, and commit.
  5. 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.

Install

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-alphavantage

To try it for one run without installing, load the extension file directly:

pig -e ./pig-alphavantage/extensions/alphavantage/alphavantage.py

To check that it loads and registers its tools without starting a session:

pig install ./pig-alphavantage/extensions/alphavantage/alphavantage.py --validate-only --json

Configure

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.

Cache freshness

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

Tools

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

The /av command and status line

  • /av or /av status shows 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-cache deletes 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.

Extension or Piglet?

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.

Development

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 call

Layout:

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)

Limitations

  • 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 compact series), 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 tzdata package for Python's time-zone database.
  • Piglet tool scoping in PiG 0.2.0. When the example Piglet ran under pig -p during development, PiG printed [piglet] No tools registered yet: skipping scoping, and the built-in read tool stayed available despite tools: []. The Alpha Vantage tools themselves worked.

License

MIT. See LICENSE. Not affiliated with Alpha Vantage Inc. Market data is subject to Alpha Vantage's terms.

About

Alpha Vantage market data for PiG agents: nine typed tools, one SQLite cache and rate budget shared by every agent on the machine. Python extension + example Piglet.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages