Skip to main content

marketgoblin

Download, store, and load financial market data — fast and without fuss.

PyPI Python License CI codecov Docs

marketgoblin is a lightweight market data platform built on Polars and yfinance. It fetches multiple datasets (OHLCV, shares-outstanding, dividends), slices them into monthly Parquet files, writes JSON sidecars with metadata, and lets you load them back with a single call.


Features

  • Multi-dataset — OHLCV, shares-outstanding, and dividends selected via a Dataset enum; per-source dispatch makes it easy to add more
  • Tidy stacked OHLCV — adjusted and raw prices live in one frame, distinguished by an is_adjusted bool column; one network call per symbol covers both
  • Single-symbol and batch fetch — fetch() and fetch_many() with thread-pool concurrency
  • Disk persistence — monthly .pq slices with atomic writes; JSON sidecar per slice
  • Lazy evaluation — all data paths return pl.LazyFrame (Polars)
  • Date flexibility — dates stored as int32 YYYYMMDD on disk; use parse_dates=True to get pl.Date
  • Retry logic — YahooSource retries transient failures with exponential backoff (3 attempts)
  • Rate limiting — fetch_many() respects a configurable requests-per-second cap (default: 2 req/s)
  • Input validation — dates are validated before any I/O; unsupported (provider, dataset) pairs raise at the dispatch boundary
  • Pluggable providers — subclass BaseSource, implement _build_dispatch(), register in one line; YahooSource and TiingoSource included

Installation

pip install marketgoblin

Or with uv:

uv add marketgoblin

For development:

git clone https://github.com/aexsalomao/marketgoblin
cd marketgoblin
uv sync --extra dev

Quick Start

import polars as pl
from marketgoblin import Dataset, MarketGoblin

goblin = MarketGoblin(provider="yahoo", save_path="./data")

# Fetch and persist OHLCV — tidy stacked frame: each trading day appears
# twice (is_adjusted=True / False). Filter to pick a variant.
lf = goblin.fetch("AAPL", "2024-01-01", "2024-03-31", parse_dates=True)
adjusted = lf.filter(pl.col("is_adjusted")).collect()
print(adjusted)

# Load back from disk (no network call)
lf = goblin.load("AAPL", "2024-01-01", "2024-03-31", parse_dates=True)
print(lf.collect())

# Shares outstanding — sparse, corporate-action-driven series
shares = goblin.fetch("AAPL", "2024-01-01", "2024-03-31", dataset=Dataset.SHARES, parse_dates=True)
print(shares.collect())

# Dividends — event-driven (typically quarterly)
dividends = goblin.fetch("AAPL", "2024-01-01", "2024-03-31", dataset=Dataset.DIVIDENDS, parse_dates=True)
print(dividends.collect())

# Batch fetch — failed symbols are logged, never crash the batch
results = goblin.fetch_many(["AAPL", "MSFT", "GOOGL"], "2024-01-01", "2024-03-31")
for symbol, lf in results.items():
    print(f"{symbol}: {lf.collect().height} rows")

Run the full walkthrough:

python example.py

API

MarketGoblin

MarketGoblin(provider: str, api_key: str | None = None, save_path: str | Path | None = None, **source_kwargs)
Method Description
fetch(symbol, start, end, dataset=Dataset.OHLCV, parse_dates=False) Download, save to disk (if save_path set), return LazyFrame
load(symbol, start, end, dataset=Dataset.OHLCV, parse_dates=False) Load from disk; raises RuntimeError if no save_path
fetch_many(symbols, start, end, dataset=Dataset.OHLCV, parse_dates=False, max_workers=8, requests_per_second=2.0) Batch fetch via ThreadPoolExecutor, rate-limited
supported_datasets (property) frozenset[Dataset] of datasets the configured provider supports

Datasets

Dataset Provider support Columns
Dataset.OHLCV yahoo, tiingo date (int32), open / high / low / close (float32), volume (int64), is_adjusted (bool), symbol
Dataset.SHARES yahoo, tiingo date (int32), shares (int64), symbol
Dataset.DIVIDENDS yahoo, tiingo date (int32), dividend (float32), symbol
Dataset.SPLITS tiingo date (int32), split_factor (float32), symbol
Dataset.FUNDAMENTALS_DAILY tiingo date (int32), market_cap / enterprise_val (int64), pe_ratio / pb_ratio / trailing_peg_1y (float32), symbol
Dataset.FUNDAMENTALS_STATEMENTS tiingo date (int32), fiscal_year (int16), fiscal_quarter (int8), ~76 income/balance/cash-flow/overview line items each as <field>_{as_reported,adjusted} (float64 for $/share-counts, float32 for per-share & ratios), symbol

OHLCV is returned as a tidy stacked frame: each trading day appears twice (is_adjusted=True and is_adjusted=False). Filter downstream (.filter(pl.col("is_adjusted"))) to pick a variant. Adjusted Open/High/Low are derived locally from the Adj Close / Close ratio — verified to match yfinance's auto_adjust=True output exactly while halving network calls.

Data on disk

Property Detail
Date column int32 YYYYMMDD (e.g. 20240101); parse_dates=True → pl.Date
OHLC columns float32
Volume column int64
Shares column int64
Dividend column float32
Parquet path {save_path}/{provider}/{dataset}/{SYMBOL}/{SYMBOL}_{YYYY-MM}.pq
JSON sidecar Same path, .json extension — row count, date range, per-dataset stats (OHLCV also records has_adjusted/has_raw and missing trading days)

Adding a Provider

import polars as pl

from marketgoblin import Dataset
from marketgoblin.sources.base import BaseSource, Fetcher

class MySource(BaseSource):
    name = "mysource"

    def _build_dispatch(self) -> dict[Dataset, Fetcher]:
        return {Dataset.OHLCV: self._fetch_ohlcv}

    def _fetch_ohlcv(self, symbol: str, start: str, end: str) -> pl.LazyFrame:
        ...  # return a normalized LazyFrame with an is_adjusted column

Per-dataset fetchers all share the (symbol, start, end) signature — there is no adjusted toggle, since OHLCV variants are stacked into a single frame distinguished by the is_adjusted column.

Then register it in goblin.py:

_SOURCES = {"yahoo": YahooSource, "tiingo": TiingoSource, "mysource": MySource}

Running Tests

pytest
pytest --cov=marketgoblin   # with coverage

License

MIT © Antônio Salomão

Metadata

Release files for marketgoblin 0.7.0

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

Source distribution (sdist)

Source distribution for marketgoblin 0.7.0
File Size Uploaded
marketgoblin-0.7.0.tar.gz 47.9 kB Details

Built distribution (wheel)

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

Total release size: 109.1 kB

Release files / marketgoblin-0.7.0.tar.gz

Download URL marketgoblin-0.7.0.tar.gz
Size 47.9 kB
Tags Source
SHA-256 checksum
How to use checksums
f2a25503b78a240d8b18a57c036b2986a1997ff010828ad26ef5b5256e3248ab
BLAKE2b-256 checksum
How to use checksums
835c0ea3f6175a272426a68943602db3965afcc42ba5ef26ab1f73b0505dadc2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 Jun 10, 2026.

Transparency log

Release files / marketgoblin-0.7.0-py3-none-any.whl

Download URL marketgoblin-0.7.0-py3-none-any.whl
Size 61.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
532d932706a424efc88e5425ffc336c7b67ad89fe721b4609eb9ca3c72361c3e
BLAKE2b-256 checksum
How to use checksums
14312afc5fb510045caa315a4ea9e9963c0798e293eafd5c55a4d8a89810cd6e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 Jun 10, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.7.0 This release

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

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