pyvalue is a fundamental-data ingestion, normalization, metric-computation, and stock-screening toolkit built for value-oriented workflows. It supports SEC fundamentals for US issuers and EODHD for global fundamentals and market data, with everything persisted in SQLite for repeatable analysis.
This project is provided for educational and informational purposes only and does not constitute investment, financial, legal, or tax advice. Outputs may be inaccurate, incomplete, or delayed and are provided "as is" without warranties of any kind. You are solely responsible for any investment decisions and outcomes based on this software; use at your own risk. Nothing here is an offer or solicitation to buy or sell any security, and past performance is not indicative of future results. Consult a licensed professional before making investment decisions.
conda create -n pyvalue python=3.12 -y
conda activate pyvalue
python -m pip install -e .[dev]
pyvalue refresh-supported-exchanges --provider EODHD
pyvalue refresh-supported-tickers --provider EODHD --exchange-codes US
pyvalue ingest-fundamentals --provider EODHD --exchange-codes US --max-symbols 100
pyvalue normalize-fundamentals --provider EODHD --exchange-codes US
pyvalue refresh-security-metadata --exchange-codes US
pyvalue update-market-data --provider EODHD --exchange-codes US
pyvalue compute-metrics --exchange-codes US
pyvalue run-screen --config screeners/value.yml --exchange-codes US --output-csv data/screen_results_value.csv
pyvalue report-screen-failures --config screeners/value.yml --exchange-codes USDefault database: data/pyvalue.db
Default CLI behavior:
- commands that accept
--providerdefault toEODHD - fundamentals and market-data commands that accept
--max-age-daysdefault to30 - metric fact freshness checks and
report-fact-freshness --max-age-daysdefault to400 - multi-symbol EODHD fundamentals ingestion defaults to
950 req/minand runs through concurrent fetch workers with batched SQLite writes - once EODHD raw fundamentals identify a listing as secondary through
General.PrimaryTicker, downstream stage commands skip it; missing or unusablePrimaryTickeris treated as primary
Upgrade note:
pyvalue reconcile-listing-status --all-supportedbackfills canonicallisting.primary_listing_statusvalues from existingfundamentals_rawwithout downloading fundamentals or market data again- read-only canonical/report commands backfill only unknown
primary/secondary statuses in scope; run
reconcile-listing-statusafter an upgrade if you want an immediate full listing-status sweep
- Load canonical provider ticker catalogs into SQLite.
- Ingest raw fundamentals from SEC or EODHD.
- Classify EODHD listings as primary or secondary from raw fundamentals and keep only primary listings in downstream market-data, normalization, metric, FX-discovery, and screening scopes.
- Normalize raw payloads into provider-agnostic financial facts.
- Refresh canonical security metadata such as sector and industry from stored raw fundamentals.
- Update market data and market caps.
- Compute value and quality metrics.
- Run YAML-based stock screens against stored data, including ranked QARP output, row-oriented CSV exports, and compact multi-symbol console previews for passing symbols.
- Persist the latest metric-computation attempt status so reporting commands can reuse fresh failure reasons instead of recomputing the same missing metrics on every run.
pyvalue now applies one shared currency framework across normalization,
metrics, and screening.
Key rules:
- configured subunit currencies are normalized to their base currency before
monetary arithmetic:
GBX/GBP0.01->GBP,ZAC->ZAR,ILA->ILS - listing currency is stored once on
listing.currencyas the authoritative quote unit from catalog metadata. It can be a subunit such asGBX,ZAC, orILA; raw fundamentals payloads never backfill listing currency. - market-data prices are stored in the listing quote unit, while stored
market caps and monetary normalization targets use the base currency derived
from
listing.currency. - EODHD monetary currency resolution uses explicit precedence:
entry/field-level currency, then direct statement-level currency, then
payload-level
General.CurrencyCode, then a narrow documented repo fallback for legacy facts whoseunitalready stores the ISO currency code. - When EODHD source facts use a different currency than base(
listing.currency), normalization converts the fact into that base currency using stored FX. - Monetary facts retain a real
currencyvalue. Non-monetary facts keep a meaningfulunitsuch asshares. - Monetary metrics persist explicit unit metadata and currency; ratio, percent, multiple, count, and other non-monetary metrics do not carry fake currencies.
- FX lookup is DB-backed, uses latest available rate on or before the requested date, and supports direct, inverse, and triangulated lookup.
normalize-fundamentalsnever fetches FX from the web. Refresh FX explicitly first; if a required conversion still cannot be resolved from stored direct, inverse, or USD/EUR triangulated rates, that symbol fails normalization.
Refresh FX rates independently with:
pyvalue refresh-fx-ratesWith the default EODHD provider, the command syncs the provider FOREX
catalog, refreshes all canonical six-letter pairs, backfills full history on
the first run, and later tops up only the missing older/newer outer ranges.
SEC: US-only fundamentals. Coverage is useful, but normalization and metric coverage are less complete than EODHD.EODHD: Global fundamentals and all market data. This is the recommended provider for most workflows, including US fundamentals.
Start here for the full docs: Documentation Index
Core pages:
- Getting Started
- Configuration
- EODHD Provider Guide
- SEC Provider Guide
- CLI Reference
- Metrics Catalog
- Screening Guide
- Architecture Overview
- Database Review Guide
- Normalization and Facts
- Development Guide
- Testing and Quality Checks
- Troubleshooting
pyvalue refresh-supported-tickers --provider EODHD --exchange-codes LSE
pyvalue ingest-fundamentals --provider EODHD --symbols SHEL.LSE
pyvalue normalize-fundamentals --provider EODHD --symbols SHEL.LSE
pyvalue update-market-data --symbols SHEL.LSE
pyvalue compute-metrics --symbols SHEL.LSE
pyvalue run-screen --config screeners/value.yml --symbols SHEL.LSEFor local setup, tests, linting, and static checks, use: