Skip to content

data_updater_v2.data_clients.eodhd

EODHDClient — EOD Historical Data: the raw calls (fetch_*) and, on the same class, the processed verbs the DataClient combines with FMP’s — FMPClient’s section names and shapes:

2 · UNIVERSE listings() — the exchange's ticker list, each line read for what it
IS · ids() — the id-mapping endpoint, every listing's ISIN, FIGI,
LEI, CUSIP, CIK
4 · PRICES daily() / intraday() per symbol · split_factors() · daily_bulk() —
one exchange's day, every ticker
5 · CORPORATE ACTIONS splits() / dividends() per symbol · splits_calendar() /
dividends_calendar() from the daily bulk files · symbol_changes()

Base https://eodhd.com/api/; the key is the api_token QUERY parameter (EODHD takes no header; common-http redacts it from logs); fmt=json on every route (CSV is the default and drops fields). Every fact below was probed live on our plan (2026-10-05, scratchpad fmpu/eod1-eod4) or is quoted from EODHD’s Bulk API page (saved as Data V2/Bulk API_ Whole-Exchange EOD, Splits and Dividends.pdf), as marked.

Routes and what they serve:

technical/{TICKER} function=splitadjusted: the daily series adjusted for splits only (5 calls): raw close / its close = the day’s split factor eod/{TICKER} one ticker’s daily history in one call, no row cap: open / high / low / close RAW (TQQQ 2025-11-18 close 98.36), adjusted_close split- and dividend-adjusted, and volume SPLIT-ADJUSTED as of today (TQQQ 2025-11-18: 267,348,000 = 2 x the raw 133.7M; AAPL 2019-01-02: 4 x). No row for the day still trading. intraday/{TICKER} 1m / 5m / 1h bars, from / to in UNIX seconds, at most 120 / 600 / 7,200 days a call (422 beyond, probed at each wall); stamps in UTC epoch at the bar’s start. Listings: RAW prices and volume (TQQQ before its split: 71.62 = raw), pre- and post-market included (04:00-20:00 ET; FMP serves 09:30-15:59 only). Depth: 1m from ~2016 (SPY) / 2008 (AAPL), 5m and 1h from ~2022, GSPC 1m from 2020, BTC 1m from 2016-18. Crypto minute volume does not reconcile with EODHD’s own daily (sum x price $63.5B vs $46.5B on 2026-10-02) nor with coins: its unit is unknown. div/{TICKER} dividend history: value split-ADJUSTED, unadjustedValue the cash as paid (AAPL 2019-02-08: 0.1825 vs 0.73), period (Quarterly, Semiannual, Monthly, Annual, Other, or null — FMP says Semi-Annual), declaration / record / payment dates. Amounts are rounded coarser than FMP’s (TQQQ 0.275 vs 0.27541). splits/{TICKER} split history: split = “NEW/OLD” (2-for-1 “2.000000/1.000000”, 1-for-8 “1.000000/8.000000”). Announced future splits appear (DXJ 3:1 on 2026-10-09), not always (SOXX 11-05 on FMP only). eod-bulk-last-day/{EX} one exchange, one day, every ticker: type eod / splits / dividends, a FLAT 100 calls each (doc). US = the composite (~50k rows: listings, OTC, mutual funds); NYSE / NASDAQ / AMEX / BATS = that venue only (5,886 / 5,258 / 282 / 1,555 on 10-02). INDX (1,547) and CC (1,847) are their own exchanges. The doc says a past non-trading day answers the previous session and a future day the latest one; probed, both answered [] — every row’s date is checked against the ask either way. Same-day volume is raw; an older day’s volume is split-adjusted once a split has happened since (TQQQ 2025-11-18 bulk: 267.3M). Dividends and splits for a FUTURE day list what is announced (10-06: 28 dividends, 3 splits) — never an undeclared ETF amount (BIL, SPY absent). exchange-symbol-list/{EX} the exchange’s ticker list (US 50,950 on 2026-10-18: Code, Name, Country, Exchange, Currency, Type, Isin; 13,298 of them on the listed venues — NASDAQ 5,479, NYSE 3,417, NYSE ARCA 2,501, BATS 1,574, AMEX 292 — the rest NMFQS fund classes and OTC); with delisted=1 the tickers that have left (US 60,433), same fields, no delisting date. fundamentals/{TICKER} one JSON document: General (profile fields), ETF_Data, SharesStats, outstandingShares, SplitsDividends … 10 calls. NOT on our plan (HTTP 403, probed 2026-10-18). id-mapping every listing’s ids, one exchange (filter[ex]) or one ticker (filter[symbol]): symbol, isin, figi (EODHD’s; on 159 of our listings an OLD one a reorganisation replaced: RKLB, SIRI, the DFA ETFs — OpenFIGI has the current), lei, cusip, cik. US 110,174 rows (73,116 with a FIGI), INDX 359 (103), CC none. 1,000 a page. symbol-change-history every US ticker rename from from on: exchange (US), old_symbol, new_symbol, company_name, effective (the first day under the new ticker). Without from it answers the last year only (323 on 2026-10-09); with from 2000-01-01, 1,224 from 2021-04-05 — its floor. Same day as FMP’s on 1,213 of the 1,215 renames both tell.

Spelling: listings as FMP (BRK-B) plus .US; indices GSPC.INDX (FMP ^GSPC) — NOT one to one: of FMP’s 302 US indices priced on 10-02, 72 have the same code and close on EODHD, 227 have no EODHD code, and ^TNX / ^TYX / ^FVX are TEN times larger on EODHD (CBOE’s index points: TNX 52.77 vs FMP’s yield 5.28); crypto BTC-USD.CC (FMP BTCUSD), daily volume in DOLLARS (identical to FMP’s composite: BTC 2026-09-28 42,589,028,679). Index sentinel: closed days carry 999999.9999 prices on some indices (MERV: 693 rows since 2015; none on GSPC, NDX, VIX, TNX).

Limits: 1,000 calls a minute and 100,000 a day on our plan; bulk 100 calls, intraday 5 (measured on the account counter), everything else 1.

Classes

EODHDClient

Bases: BaseClient

EOD Historical Data: the raw calls and the processed verbs. Carried state: the base’s only.

daily

daily(symbols: str | Symbols, start: dt.date | None = None, end: dt.date | None = None, asset: Asset) -> RawResponse | dict[str, RawResponse]

Daily bars, one symbol or many (our spelling or EODHD’s), oldest first, as traded (unadjusted), finished days only (bars.settled). start None = the vendor’s first day; end None = today. asset picks the spelling and the handling (the table above). Listings’ volume as served — divided by every split since the day (TQQQ 2025-11-18: 267.3M for the 133.7M traded); back to shares as traded with the splits table.

daily_bulk

daily_bulk(day: dt.date, exchange: str = 'US') -> RawResponse

One EODHD exchange’s daily bars for ONE day, every ticker, in the common shape: US (the composite: listings, OTC, mutual funds — filter to the universe in the flow), a venue (NYSE / NASDAQ / AMEX / BATS), INDX (symbols as EODHD codes: GSPC, TNX — not FMP’s) or CC (crypto, symbols in FMP’s spelling: BTC-USD -> BTCUSD). 100 calls whatever the size. Rows dated other than day are not that day’s and are left out (an empty list means not published, or no session). Volume is shares as traded for the latest day only: for an older day EODHD has divided it by any split since (un-adjust with the splits table).

dividends

dividends(symbols: str | Symbols, start: dt.date | None = None, end: dt.date | None = None) -> RawResponse | dict[str, RawResponse]

US listings’ dividend histories (EODHD), oldest first, in FMP’s shape: symbol, ex_date, period (as EODHD words it), amount (unadjustedValue: cash as paid), declaration / record / payment dates. start / end bound the ex-dates.

dividends_calendar

dividends_calendar(start: dt.date, end: dt.date) -> RawResponse

Every US dividend with its ex-date in [start, end] from EODHD’s daily bulk files, one call (100) per calendar day; a future day lists the announced ones — never an undeclared ETF amount (BIL’s appears on its ex-date).

fetch_bulk

fetch_bulk(exchange: str, kind: str, day: str) -> RawResponse

One exchange’s file for one day (kind eod / splits / dividends), as served.

fetch_dividends

fetch_dividends(ticker: str, start: str | None = None, end: str | None = None) -> RawResponse

One ticker’s dividends as served (value, unadjustedValue, period, dates).

fetch_eod

fetch_eod(ticker: str, start: str | None, end: str | None) -> RawResponse

One ticker’s daily rows as served (date, OHLC raw, adjusted_close, volume split-adjusted), oldest first; start / end ISO dates, None = all.

fetch_fundamentals

fetch_fundamentals(ticker: str, filter: str | None = None) -> RawResponse

One ticker’s fundamentals document as served (General: Code, Type, Name, Exchange, ISIN, CUSIP, CIK, IPODate, Sector, Industry, Description; ETF_Data; SharesStats; outstandingShares; SplitsDividends …), or one block of it (filter: “General”, “General::Sector”). 10 calls. NOT on our plan today: a 403 comes back as a failed answer (probed 2026-10-18, AAPL.US and SPY.US); declared so the day the plan carries it the profile for EODHD-only names is one call away.

fetch_id_mapping

fetch_id_mapping(exchange: str | None = None, symbol: str | None = None) -> RawResponse

EODHD’s ids for one exchange’s listings (every page, fetched at once) or one ticker (SPY.US), as served: symbol, isin, figi, lei, cusip, cik.

fetch_intraday

fetch_intraday(ticker: str, interval: str, start: int, end: int) -> RawResponse

One ticker’s bars of one EODHD width (1m / 5m / 1h) whose start lies in [start, end] (UNIX seconds), as served: timestamp, gmtoffset, datetime, OHLCV.

fetch_split_adjusted

fetch_split_adjusted(ticker: str, start: str | None, end: str | None) -> RawResponse

One ticker’s daily OHLCV adjusted for SPLITS ONLY (the Technical API’s function=splitadjusted), oldest first, whole history in one request (5 calls). Its close against eod’s raw close is the split factor of each day, the one thing that puts eod’s split-adjusted volume back to shares as traded (checked against FMP’s raw volume: AAPL 2020, TQQQ 2025, NVDA 2024, XLE 2018 exact).

fetch_splits

fetch_splits(ticker: str, start: str | None = None, end: str | None = None) -> RawResponse

One ticker’s splits as served (date, split “NEW/OLD”).

fetch_symbol_changes

fetch_symbol_changes(start: str, end: str | None = None) -> RawResponse

Every US rename effective in [start, end] as served (start an ISO day: without one EODHD answers the last year only).

fetch_symbols

fetch_symbols(exchange: str, delisted: bool = False) -> RawResponse

One exchange’s ticker list (Code, Name, Country, Exchange, Currency, Type, Isin): today’s listings, or with delisted the tickers that have left it (US: 60,433 on 2026-10-18 — 22,249 of them NMFQS mutual-fund share classes, 11,519 NASDAQ, 7,052 NYSE, 9,829 PINK; no delisting date on the row: the last bar, FMP’s list or the SEC’s Form 25 date it).

ids

ids(exchange: str | None = None, symbols: Iterable[str] | None = None) -> dict[str, dict[str, Any]]

EODHD’s ids for its listings: one exchange’s every listing (exchange: US, INDX; 111 pages for US, fetched at once, ~5 minutes), or only symbols (EODHD’s tickers, SPY.US; one call each). Its ticker -> {symbol, isin, figi, lei, cusip, cik}, each listing once (the same row served twice is one). EODHD’s FIGI can be one a reorganisation replaced (RKLB, SIRI): OpenFIGI’s is the current. A failed or cut answer raises FetchError (ids are a catalog: no holes).

intraday

intraday(symbols: str | Symbols, start: dt.date | None = None, end: dt.date | None = None, interval: str = '1min', asset: Asset) -> RawResponse | dict[str, RawResponse]

Intraday bars of the family’s days [start, end] (UTC days for crypto, ET session days for listings), one symbol or many, oldest first, in the common shape. start None = INTRADAY_FLOOR; end None = today. 1min / 5min / 1hour only (INTERVALS). Listings RAW with pre- and post-market bars (04:00-20:00 ET, as served — FMP serves the regular session only); crypto minute volume is coins (probed 2026-10-07): dollars = coins x the bar’s typical price.

listings

listings(exchange: str = 'US', delisted: bool = False) -> list[dict[str, Any]]

EODHD’s ticker list for one exchange in one call, as served: Code (our spelling for US listings: BRK-B), Name, Country, Exchange, Currency, Type, Isin (US: 50,984 on 2026-10-05); with delisted the tickers that have left it instead (US: 60,433 on 2026-10-18, no delisting date). Type is a second opinion only — wrong both ways in a 615-name sample (6 of 250 ETFs “Common Stock”; OZ, a common stock, “Unit”; DPU “ETF”; GJP, a STRATS trust, “Common Stock”) — and Isin can lag a reverse split (8 of 246 equities kept the old one). Each row also says what it IS as nc-feeds reads an EODHD line (papers.eodhd_kind: the spelling, the Type with the venue and the name): asset_class, security_type, and refused (None, or why the line is not a listing: a fund class code, a when-issued or test line). A failed or empty list raises FetchError (a catalog: no holes).

split_factors

split_factors(symbols: str | Symbols, start: dt.date | None = None, end: dt.date | None = None) -> dict[str, dict[dt.date, float]]

For US listings (EODHD’s spelling or ours), each day’s split factor since: EODHD’s raw close / its split-only adjusted close (eod and the Technical API, 1 + 5 calls a symbol). EODHD’s daily volume divided by it is the volume as traded. A symbol whose calls fail has no factors (its EODHD volume cannot be put back: the caller drops it).

splits

splits(symbols: str | Symbols, start: dt.date | None = None, end: dt.date | None = None) -> RawResponse | dict[str, RawResponse]

US listings’ split histories (EODHD), oldest first, in FMP’s shape: symbol, date, split_to, split_from, split_type (None: EODHD does not say). Announced future splits appear when EODHD has them. start / end bound the dates. Processed: a row with no factor or the same split twice taken out, named (actions.sound_splits).

splits_calendar

splits_calendar(start: dt.date, end: dt.date) -> RawResponse

Every US split dated in [start, end] from EODHD’s daily bulk files, one call (100) per calendar day; a future day lists the announced ones. Processed as splits.

symbol_changes

symbol_changes(since: dt.date | None = None) -> RawResponse

Every US rename EODHD tells effective from since on (None: as far back as it reaches, 2021-04-05), oldest first, in the common shape (changes.sound_changes: old_symbol / new_symbol in our spelling, date, name), the lines that are no rename taken out, named. A failed answer comes back as it is.

Functions

eodhd_ticker

eodhd_ticker(symbol: str, asset: Asset) -> str

Our symbol (FMP’s spelling) in EODHD’s: SPY -> SPY.US, ^GSPC -> GSPC.INDX, BTCUSD -> BTC-USD.CC. A symbol already carrying an EODHD suffix passes as given. Not every FMP index exists under the same code on EODHD (72 of 302 did on 2026-10-02), and yields differ in scale (EODHD TNX = 10 x FMP ^TNX).