Drop-in yfinance wrapper with DuckDB OHLCV caching
Project description
dyfinance
Drop-in replacement for yfinance with DuckDB OHLCV caching. Generated by Claude.
# Change just this one line
import dyfinance as yf
ticker = yf.Ticker("AAPL")
df = ticker.history(period="1mo") # cached transparently
Why DuckDB?
dyfinance uses DuckDB as its cache backend:
- Single file, zero config -- like SQLite, DuckDB is an embedded database with no server process; your entire cache lives in one
~/.dyfinance/cache.duckdbfile - Columnar storage -- well-suited for analytical queries across many tickers and long date ranges
- Native pandas integration -- DuckDB reads and writes DataFrames without serialization overhead
- Your cache is a database -- you can query the cache directly with SQL for custom analysis beyond what yfinance offers:
import duckdb
conn = duckdb.connect("~/.dyfinance/cache.duckdb")
# Your own analysis — no yfinance API limits
conn.sql("""
SELECT ticker, interval,
MIN(ts) AS first_date, MAX(ts) AS last_date,
COUNT(*) AS rows
FROM ohlcv
GROUP BY ticker, interval
""").show()
Features
- yfinance-compatible -- same API signatures, defaults, and output structures
- Transparent DuckDB caching -- daily+ OHLCV data is cached locally; redundant fetches are eliminated
- Full fallback -- any attribute or method not overridden by dyfinance is delegated to yfinance
- Spot-check validation -- stale cache is automatically verified against fresh data and corrected if needed
Installation
pip install dyfinance
Requires Python >= 3.10.
Quick Start
import dyfinance as yf
# Single ticker
aapl = yf.Ticker("AAPL")
hist = aapl.history(period="6mo") # first call fetches, subsequent calls use cache
info = aapl.info # delegated to yfinance
# Multiple tickers
data = yf.download(["AAPL", "MSFT"], period="1mo")
# All yfinance features work as-is
aapl.dividends
aapl.financials
aapl.options
Cached Intervals
| Cached (DuckDB) | Passthrough (yfinance direct) |
|---|---|
1d, 5d, 1wk, 1mo, 3mo |
1m, 2m, 5m, 15m, 30m, 60m, 90m, 1h |
Known Limitations
- ISIN codes are not supported in the cached path. yfinance's
download()auto-converts ISIN codes (e.g.US0378331005) to ticker symbols, but dyfinance skips this conversion for cacheable intervals. Use ticker symbols directly (e.g.AAPLinstead ofUS0378331005).
Configuration
| Environment Variable | Default | Description |
|---|---|---|
DYFINANCE_DB_PATH |
~/.dyfinance/cache.duckdb |
Cache database file path |
DYFINANCE_STALE_HOURS |
6 |
Hours before spot-check fires |
Cache Management
import dyfinance as yf
# Clear cache for a specific ticker
yf.Ticker("AAPL").clear_cache() # all intervals
yf.Ticker("AAPL").clear_cache("1d") # daily only
Benchmark
Cache-read performance compared against yfinance's built-in SQLite cache. Both libraries serve data from their respective local caches — no network I/O is involved.
Ticker.history() — single ticker (20 iterations, median)
| Ticker | Period | yfinance (SQLite) | dyfinance (DuckDB) | Ratio |
|---|---|---|---|---|
| AAPL | 1mo | 12.0 ms | 20.8 ms | 1.7x |
| AAPL | 6mo | 13.6 ms | 24.1 ms | 1.8x |
| AAPL | 1y | 15.3 ms | 25.9 ms | 1.7x |
| MSFT | 1mo | 12.2 ms | 21.8 ms | 1.8x |
| MSFT | 1y | 15.4 ms | 25.8 ms | 1.7x |
| GOOGL | 1mo | 12.5 ms | 21.9 ms | 1.8x |
| GOOGL | 1y | 14.7 ms | 26.0 ms | 1.8x |
For single-ticker reads, yfinance is ~1.7-1.8x faster. SQLite (row-oriented) outperforms DuckDB (columnar) for small, per-ticker queries. This is expected — DuckDB's columnar engine is designed for analytical workloads, not single-row lookups.
download() — multi-ticker batch (10 iterations, median)
| Tickers | yfinance (SQLite) | dyfinance (DuckDB) | Winner |
|---|---|---|---|
| 5 | 161.2 ms | 10.8 ms | dyfinance 15x faster |
| 10 | 192.3 ms | 16.8 ms | dyfinance 11x faster |
| 20 | 252.3 ms | 32.0 ms | dyfinance 8x faster |
| 30 | 309.9 ms | 44.6 ms | dyfinance 7x faster |
| 50 | 485.1 ms | 74.7 ms | dyfinance 6x faster |
For multi-ticker downloads, dyfinance is 6-15x faster. DuckDB reads all tickers in a single batch query, avoiding the per-ticker overhead of creating yfinance Ticker objects.
Reproduce with:
python benchmarks/bench_cache.py # single-ticker
python benchmarks/bench_multi_symbol.py # multi-ticker
Development
pip install -e ".[dev]"
make test # offline tests
make test-live # live yfinance comparison tests (network required)
make lint # ruff check
make typecheck # mypy strict
make clean # remove caches and build artifacts
License
Apache-2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dyfinance-0.2.0.tar.gz.
File metadata
- Download URL: dyfinance-0.2.0.tar.gz
- Upload date:
- Size: 46.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b23feba30893f785ca51cfbb94adb5bc7717c3e83c09cc1fbe36f89a68cc01d4
|
|
| MD5 |
d173a4aa5170b6a19fd0d672fd1d1cd7
|
|
| BLAKE2b-256 |
f5243b2b00ff1facd5866ad645476ae86b64a4742e6f0f84cad60d585e4f1696
|
Provenance
The following attestation bundles were made for dyfinance-0.2.0.tar.gz:
Publisher:
publish.yml on Qooh0/dyfinance
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dyfinance-0.2.0.tar.gz -
Subject digest:
b23feba30893f785ca51cfbb94adb5bc7717c3e83c09cc1fbe36f89a68cc01d4 - Sigstore transparency entry: 1166295260
- Sigstore integration time:
-
Permalink:
Qooh0/dyfinance@51934b0bb3b9346309be247b9cea7cf741e9e01a -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Qooh0
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@51934b0bb3b9346309be247b9cea7cf741e9e01a -
Trigger Event:
push
-
Statement type:
File details
Details for the file dyfinance-0.2.0-py3-none-any.whl.
File metadata
- Download URL: dyfinance-0.2.0-py3-none-any.whl
- Upload date:
- Size: 24.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f138bfee3f78e94e1a6a4dad9f0b4ea1ea727dce5ab599d2f054ed203a2635f2
|
|
| MD5 |
a11d00c70db566b632c676062736b60b
|
|
| BLAKE2b-256 |
047f7230c2cea61e01c2e286f8299646269b51938600f442f14ef2528d913f4a
|
Provenance
The following attestation bundles were made for dyfinance-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on Qooh0/dyfinance
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dyfinance-0.2.0-py3-none-any.whl -
Subject digest:
f138bfee3f78e94e1a6a4dad9f0b4ea1ea727dce5ab599d2f054ed203a2635f2 - Sigstore transparency entry: 1166295357
- Sigstore integration time:
-
Permalink:
Qooh0/dyfinance@51934b0bb3b9346309be247b9cea7cf741e9e01a -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Qooh0
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@51934b0bb3b9346309be247b9cea7cf741e9e01a -
Trigger Event:
push
-
Statement type: