Expand description
Bring-your-own-key FMP (Financial Modeling Prep) data sync + snapshot-factor formulas (issue #52 / #132).
Direct HTTP, no third-party FMP SDK. Given the user’s own API key, fetch
adjusted daily bars (and optionally annual fundamentals, a symbol → sector
industry map, and snapshot-factor panels) and write a docs/data-layout.md
tree:
<out>/prices/{SYM}.csv.gz adjusted OHLCV (always)
<out>/fundamentals/{SYM}.csv.gz dense forward-filled factors (--include-fundamentals)
<out>/tracked/universe.csv.gz symbol,sector,market_cap (--include-industry)
<out>/panels/{name}.csv.gz snapshot-factor panels (--include-snapshot-factors)§Reuse across CLI and service
sync writes to a local path; sync_into is the storage-agnostic core
over any ObjectSink + ObjectSource, so the CLI and a backend service
produce byte-identical trees whether the destination is local disk or an
S3/R2 bucket (pomelo-s3’s S3Source). The pure [factors] formulas
are the single source of truth a Rust service links directly (and wasm/PyO3
bindings can expose later).
The key never leaves the machine; we neither host nor redistribute FMP data.
FMP stays out of yuzu-core / pomelo-data / WASM — the HttpClient
indirection keeps networking optional (build with --no-default-features)
and testable.
§MVP scope
Enough to backtest price-based strategies over a short US window: close /
OHLC TA and cross-section ops on a modest symbol list. Fundamentals are
best-effort from the annual ratios/key-metrics/growth endpoints (plus
income-statement for filing-date visibility, #131); richer
fundamentals, full-universe, and point-in-time index membership are out of
scope (see #53 / #125). Delisted names can be unioned into the universe with
--include-delisted for survivorship-honest backtests (#124 / #26) — see
[delisted]. Which library features an FMP Starter key can honestly
support — and which panels are missing — is documented in
docs/fmp-data-source.md (#51).
Structs§
- Delisted
Symbol - A delisted security from FMP’s
delisted-companiesendpoint. - Index
Membership - The reconstructor: the current constituent set plus the change log (ascending).
- Symbol
Filter - Filters for
build_symbol_list— a screened market universe. - Sync
Config - Knobs for one [
sync] run. - Sync
Summary - What a [
sync] run produced. - Ureq
Client - The real ureq-backed client — only with the
fmp-syncfeature. A dependent that supplies its ownHttpClientcan build with the feature off. The real ureq-backed client — only with thefmp-syncfeature. The real ureq-backed client — only with theureqfeature.
Enums§
- Http
Error - A classified HTTP failure so the retry loop knows whether to back off.
- Index
- An index we can reconstruct PIT membership for. Each maps to FMP’s
current-snapshot + historical-change-log endpoints and a membership series
name (
in_<index>). - Write
Mode - How an already-present symbol tree is treated by a sync run.
Constants§
- MEMBERSHIP_
SERIES - Membership series names auto-loaded by the CLI (
load_ctx) frompanels/, sosignal * in_sp500works on therun/sweeppath. Kept in sync withIndex::series_name(asserted in tests). - US_
EXCHANGES - The default exchange filter — the three US major exchanges. (AMEX is now
NYSE American, but FMP still labels it
AMEX.)
Traits§
- Http
Client - Minimal blocking HTTP GET, abstracted so sync logic is tested with a mock.
Functions§
- build_
symbol_ list - Build a screened symbol universe from FMP’s screener
(
/stable/company-screener) — the “establish the sync list first” step so a whole-market backtest has a persisted, reviewable symbol list to sync. The filters are pushed to the API and re-applied client-side as a safety net. Returns tickers, sorted and de-duplicated. - fetch_
delisted - Fetch the delisted universe, paging
delisted-companiesuntil an empty page or [MAX_DELISTED_PAGES].exchangesfilters client-side (comma-separated FMP codes;None/ empty /"all"keeps every exchange — note thatdelisted-companiescarries no market cap, so a--min-market-capfloor cannot apply to these names). Returns rows sorted and de-duplicated by symbol. - parse_
market_ cap - Parse a market-cap threshold with an optional magnitude suffix —
k,m,b,t(thousand / million / billion / trillion), case-insensitive. Plain numbers and scientific notation pass through. Examples:1b→ 1e9,500m→ 5e8,2.5t→ 2.5e12,1e9→ 1e9,0→ 0. - parse_
symbols_ list - Parse a symbols-list file into tickers. One ticker per line; the first
comma-separated field is taken (so a
symbol,...CSV works), and blank lines,#comments, and a literalsymbolheader are skipped. - sync
- Sync
symbolsfrom FMP into the localouttree perSyncConfig— a thin convenience wrapper oversync_intofor the common on-disk case. - sync_
into - Storage-agnostic core: sync
symbolsfrom FMP into anystore— local disk (LocalSource) or an S3/R2 bucket (pomelo-s3’sS3Source) — so the CLI and a backend service produce byte-identical trees for the same inputs. Prices are always fetched; fundamentals and industry are opt-in. Progress and per-symbol failures are logged to stderr (API key redacted); a per-symbol failure is recorded and the batch continues. - write_
index_ membership - Reconstruct and write an index membership panel (
panels/in_sp500.csv.gz, etc.) over the synced tree’s trading calendar. Columns are the index’sever_members(from, to)— the same universe you should have synced. Returns(days, symbols)in the written panel.