Skip to main content

avantage

CI PyPI Python License: MIT

Modern, fully-typed Python wrapper for the Alpha Vantage API.

  • Async-first -- built on httpx for native async/await support
  • Fully typed -- every parameter and return value has type annotations; passes mypy --strict
  • 110+ endpoints -- stocks, forex, crypto, commodities, fundamentals, economic indicators, 50+ technical indicators, options, news sentiment, and more
  • Pydantic v2 models -- all responses parsed into typed dataclasses, not raw dicts
  • Built-in resilience -- token-bucket rate limiting, retry with exponential backoff + jitter
  • Minimal dependencies -- just httpx and pydantic

Installation

pip install avantage

With optional pandas support:

pip install avantage[pandas]

Quick Start

import asyncio
from avantage import AlphaVantageClient

async def main():
    async with AlphaVantageClient("YOUR_API_KEY") as client:
        # Get a stock quote
        quote = await client.equity.quote("AAPL")
        print(f"{quote.symbol}: ${quote.price} ({quote.change_percent})")

        # Get daily time series
        series = await client.equity.daily("MSFT")
        for entry in series.data[:3]:
            print(f"  {entry.timestamp}: O={entry.open} H={entry.high} L={entry.low} C={entry.close}")

        # Technical indicators
        rsi = await client.indicators.rsi("AAPL", "daily", time_period=14, series_type="close")
        print(f"RSI: {rsi.data[0].values}")

asyncio.run(main())

You can also set your API key via the environment variable ALPHAVANTAGE_API_KEY:

import os
os.environ["ALPHAVANTAGE_API_KEY"] = "YOUR_KEY"

client = AlphaVantageClient(os.environ["ALPHAVANTAGE_API_KEY"])

Plotting

Responses are Pydantic models, so you'll need to convert them to pandas DataFrames for plotting. Install the extras:

pip install avantage[pandas] matplotlib

Intraday Time Series

import asyncio
import pandas as pd
import matplotlib.pyplot as plt
from avantage import AlphaVantageClient

async def main():
    async with AlphaVantageClient("YOUR_API_KEY") as client:
        series = await client.equity.intraday("IBM", "5min")

    df = pd.DataFrame([
        {"time": e.timestamp, "close": e.close} for e in series.data
    ])
    df["time"] = pd.to_datetime(df["time"])
    df = df.sort_values("time")

    df.plot(x="time", y="close", title="IBM Intraday Close Price (5-min)", legend=False)
    plt.ylabel("Price (USD)")
    plt.tight_layout()
    plt.show()

asyncio.run(main())

IBM Intraday

Bollinger Bands

async def main():
    async with AlphaVantageClient("YOUR_API_KEY") as client:
        bbands = await client.indicators.bbands("IBM", "daily", time_period=20, series_type="close")

    df = pd.DataFrame([
        {
            "date": e.timestamp,
            "upper": e.values["Real Upper Band"],
            "middle": e.values["Real Middle Band"],
            "lower": e.values["Real Lower Band"],
        }
        for e in bbands.data
    ])
    df["date"] = pd.to_datetime(df["date"])
    df = df.sort_values("date").tail(90)

    fig, ax = plt.subplots()
    ax.plot(df["date"], df["upper"], label="Upper Band")
    ax.plot(df["date"], df["middle"], label="Middle Band (SMA 20)")
    ax.plot(df["date"], df["lower"], label="Lower Band")
    ax.fill_between(df["date"], df["upper"], df["lower"], alpha=0.1)
    ax.set_title("IBM Bollinger Bands (Daily)")
    ax.legend()
    plt.tight_layout()
    plt.show()

asyncio.run(main())

IBM Bollinger Bands

Crypto Daily

async def main():
    async with AlphaVantageClient("YOUR_API_KEY") as client:
        crypto = await client.crypto.daily("BTC", "USD")

    df = pd.DataFrame([
        {"date": e.timestamp, "close": e.close} for e in crypto.data
    ])
    df["date"] = pd.to_datetime(df["date"])
    df = df.sort_values("date").tail(90)

    df.plot(x="date", y="close", title="Bitcoin Daily Close Price (BTC/USD)", legend=False)
    plt.ylabel("Price (USD)")
    plt.tight_layout()
    plt.show()

asyncio.run(main())

BTC/USD Daily

API Reference

The client exposes domain-specific API groups as attributes:

async with AlphaVantageClient(api_key) as client:
    client.equity          # Stocks: quotes, time series, search, market status
    client.forex           # Foreign exchange rates and time series
    client.crypto          # Cryptocurrency rates and time series
    client.commodities     # Oil, gas, metals, agriculture prices
    client.fundamentals    # Company financials, earnings, dividends, splits
    client.economic        # GDP, CPI, unemployment, treasury yields
    client.indicators      # 50+ technical indicators (SMA, RSI, MACD, ...)
    client.intelligence    # News sentiment, top movers, insider transactions
    client.options         # Realtime and historical options chains
    client.analytics       # Fixed and sliding window analytics
    client.calendar        # Earnings and IPO calendars

Equity

# Realtime quote
quote = await client.equity.quote("AAPL")
# quote.symbol, quote.price, quote.change, quote.change_percent, quote.volume

# Time series (intraday, daily, weekly, monthly -- with adjusted variants)
series = await client.equity.daily("AAPL", outputsize="full")
series = await client.equity.intraday("AAPL", "5min")
series = await client.equity.weekly_adjusted("AAPL")

# Search
matches = await client.equity.search("Apple")
# [SymbolMatch(symbol="AAPL", name="Apple Inc", ...)]

# Bulk quotes (up to 100 symbols)
quotes = await client.equity.bulk_quotes("AAPL,MSFT,GOOGL")

# Market status
markets = await client.equity.market_status()

Forex

rate = await client.forex.exchange_rate("USD", "EUR")
# rate.exchange_rate, rate.bid_price, rate.ask_price

series = await client.forex.daily("USD", "EUR")
# [FXDataPoint(timestamp="2024-01-02", open=0.85, high=0.86, low=0.84, close=0.855)]

Crypto

rate = await client.crypto.exchange_rate("BTC", "USD")

daily = await client.crypto.daily("BTC", "USD")
# [CryptoDataPoint(timestamp=..., open=..., volume=..., market_cap=...)]

Commodities

oil = await client.commodities.wti(interval="daily")
# CommodityResponse(name="WTI", interval="daily", unit="dollars per barrel", data=[...])

gas = await client.commodities.natural_gas()
copper = await client.commodities.copper()

# Precious metals
gold_spot = await client.commodities.gold_silver_spot("GOLD")
gold_history = await client.commodities.gold_silver_history("GOLD", interval="daily")

Fundamentals

overview = await client.fundamentals.overview("AAPL")
# overview.market_capitalization, overview.pe_ratio, overview.eps, overview.beta, ...

income = await client.fundamentals.income_statement("AAPL")
# income.annual_reports, income.quarterly_reports

earnings = await client.fundamentals.earnings("AAPL")
estimates = await client.fundamentals.earnings_estimates("AAPL")
dividends = await client.fundamentals.dividends("AAPL")
splits = await client.fundamentals.splits("AAPL")

Economic Indicators

gdp = await client.economic.real_gdp(interval="quarterly")
cpi = await client.economic.cpi()
unemployment = await client.economic.unemployment()
yields = await client.economic.treasury_yield(maturity="10year")

Technical Indicators

All 50+ Alpha Vantage indicators are supported:

sma = await client.indicators.sma("AAPL", "daily", time_period=20, series_type="close")
rsi = await client.indicators.rsi("AAPL", "daily", time_period=14, series_type="close")
macd = await client.indicators.macd("AAPL", "daily", series_type="close")
bbands = await client.indicators.bbands("AAPL", "daily", time_period=20, series_type="close")
stoch = await client.indicators.stoch("AAPL", "daily")
adx = await client.indicators.adx("AAPL", "daily", time_period=14)
obv = await client.indicators.obv("AAPL", "daily")
# ... and 40+ more

All indicators return IndicatorResponse with metadata and data:

result = await client.indicators.macd("AAPL", "daily", series_type="close")
for point in result.data[:3]:
    print(point.timestamp, point.values)
    # 2024-01-02 {"MACD": 1.23, "MACD_Signal": 0.98, "MACD_Hist": 0.25}

Options

chain = await client.options.chain("AAPL", require_greeks=True)
for contract in chain.contracts[:3]:
    print(f"{contract.type} {contract.strike} exp:{contract.expiration} delta:{contract.delta}")

historical = await client.options.historical("AAPL", date="2024-01-19")

Intelligence

news = await client.intelligence.news_sentiment(tickers="AAPL", limit=10)
for article in news:
    print(f"{article.title} ({article.overall_sentiment_label})")

movers = await client.intelligence.top_movers()
# movers.top_gainers, movers.top_losers, movers.most_actively_traded

Configuration

client = AlphaVantageClient(
    api_key="YOUR_KEY",
    timeout=30.0,            # HTTP timeout in seconds (default: 30)
    max_retries=3,           # Retry attempts on transient failures (default: 3)
    retry_base_delay=1.0,    # Base delay for exponential backoff (default: 1.0)
    retry_max_delay=30.0,    # Maximum backoff delay (default: 30.0)
    rate_limit=75,           # Requests per minute (default: 75, safe for free tier)
)

Rate Limiting

The built-in token-bucket rate limiter prevents exceeding your API quota. The default of 75 requests/minute is safe for the free tier. Premium users can increase this:

client = AlphaVantageClient("YOUR_KEY", rate_limit=600)  # premium: 600/min

Retry Behavior

Transient failures (HTTP 5xx, 429, connection errors, timeouts) are automatically retried with exponential backoff and full jitter. Client errors (4xx) and business logic errors (invalid symbol, bad API key) are never retried.

Error Handling

from avantage import (
    AlphaVantageError,    # Base exception
    AuthenticationError,  # Invalid API key
    RateLimitError,       # API rate limit exceeded
    SymbolNotFoundError,  # Unknown symbol
    InvalidParameterError,# Bad request parameters
    APIResponseError,     # Malformed response
    UpstreamError,        # Server/network failures
)

try:
    quote = await client.equity.quote("INVALID")
except SymbolNotFoundError:
    print("Symbol not found")
except RateLimitError as e:
    print(f"Rate limited. Retry after: {e.retry_after}")
except AlphaVantageError as e:
    print(f"API error: {e.message}")

Contributing

Contributions are welcome! Please read CONTRIBUTING.md before opening a pull request.

Requirements

License

MIT

Metadata

Release files for avantage 0.1.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for avantage 0.1.4
File Size Uploaded Provenance
avantage-0.1.4.tar.gz 27.2 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for avantage 0.1.4
File Interpreter ABI Platform
avantage-0.1.4-py3-none-any.whl Python 3 none any Details

Total release size: 67.0 kB

Release files / avantage-0.1.4.tar.gz

Download URL avantage-0.1.4.tar.gz
Size 27.2 kB
Tags Source
SHA-256 checksum
How to use checksums
898683c0847e7fe27fec69c6a6d02585c88339ad8897348e75596c264edaf7fa
BLAKE2b-256 checksum
How to use checksums
bb320dc3ebbfb727c218b72656b6974b03bee832c83fa338ddc19d01506b8fe5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 28, 2026.

Transparency log

Release files / avantage-0.1.4-py3-none-any.whl

Download URL avantage-0.1.4-py3-none-any.whl
Size 39.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cfee26ddc91b89b3302a09921eb3a12162bca76f5f70e6641afd382e2644f2ef
BLAKE2b-256 checksum
How to use checksums
5aff33e9e63c4358c88fef8453673f78e16eaf9dc074e3dc111b32fb141b3a5c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 28, 2026.

Transparency log

Security for avantage 0.1.4

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for avantage-0.1.4.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 28, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page