reindex_dfs() rebuilt the combined index via sorted(set(...)) +
pd.to_datetime, dropping the index name set by history.py ('Date' for
daily, 'Datetime' for intraday). After concat, data.index.name was
None, so users doing data.stack().reset_index() got a 'level_0' column
instead of 'Date' / 'Datetime'.
Use Index.union, which preserves the name natively when sources agree.
Drive-by: narrow data.columns to MultiIndex before swaplevel to silence
a pyright attribute warning.
Some platforms (e.g. older macOS, exotic Linux distros) cannot build the
curl-impersonate binary that backs curl_cffi, leaving yfinance unusable.
This change keeps curl_cffi as the preferred and default backend but no
longer hard-requires it at runtime.
- New `yfinance/_http.py` abstracts the HTTP backend. If `curl_cffi` is
importable it is used as before; otherwise yfinance falls back to plain
`requests` with a realistic Chrome User-Agent and logs a warning so the
downgrade is explicit.
- `data.py`, `base.py`, `multi.py`, `scrapers/history.py` build sessions
via `_http.new_session()`.
- Scrapers and screener catch `_http.HTTPError` instead of importing
`curl_cffi.requests.exceptions.HTTPError` directly.
- `is_supported_session()` accepts either backend; `cookie_jar()` papers
over the small API difference between curl_cffi (`cookies.jar`) and
requests (`cookies` is itself the jar).
- New Advanced > Installation page documents the curl_cffi-free install
recipe; README links to it just under the install instruction.
Empirically verified that plain `requests` with a Chrome UA does not hit
the 401-after-~10-requests issue that the earlier `curl_adapter` approach
ran into; 15/15 quoteSummary calls succeed without rate limiting.
`setup.py` is unchanged -- `curl_cffi>=0.15` remains the default install
requirement (CVE-pinned). The fallback only activates when the import
fails at runtime; moving curl_cffi to extras_require can be a follow-up
decision for the maintainer.
Yahoo's v7 (`/v7/quote`) and v10 (`/quoteSummary`) endpoints accept
`lang` and `region` parameters and return localized fields (`longName`,
`shortName`, ...) when the ticker has been translated for that locale —
e.g. 1810.HK returns '小米集團-W' under `lang=zh-Hant-HK`, GAZP.ME
returns 'Публичное акционерное общество Газпром' under `lang=ru-RU`.
Previously these params were not exposed and `Ticker.info["longName"]`
always came back in U.S. English.
Surfaced as global config (`YfConfig.locale.lang` / `YfConfig.locale.region`)
rather than per-Ticker constructor params: a typical user wants the
same locale for every call in their session, and the config approach
also covers the v10 calendar/earnings endpoint in `_fetch_history_metadata`
without threading kwargs through three layers.
- Add `YfConfig.locale.lang` (default `"en-US"`) and `YfConfig.locale.region`
(default `"US"`).
- `Quote._fetch` (v10/quoteSummary) and `Quote._fetch_additional_info`
(v7/quote) read the locale from `YfConfig` on every call.
- `_fetch_history_metadata` (v1 calendar) reads the same locale, replacing
a hardcoded `lang=en-US, region=US`.
- The `v8/chart` endpoint ignores `lang` server-side, so we don't forward
there — would only generate noise.
- Verified live for Latin/diacritics (it-IT), CJK (zh-Hant-HK, ja-JP),
Cyrillic (ru-RU); Apple under ja-JP correctly stays "Apple Inc." since
it's a U.S. listing.
Closes#2582
`download()` used module-level dicts in `yfinance.shared` (`_DFS`,
`_ERRORS`, `_TRACEBACKS`, `_ISINS`) as scratch space. Concurrent calls
trampled each other; the previous fix wrapped the whole call in
`shared._LOCK`, which silently serialized parallel downloads — hiding
the race instead of removing it, and defeating the parallelism users
reach for `download()` to get.
- Introduce `_DownloadCtx` per call holding `dfs/errors/tracebacks/isins`
plus a fine-grained lock for thread workers.
- `_download_one`, `_download_one_threaded`, `_realign_dfs` take the ctx
explicitly and write into it.
- Drop the call-wide `shared._LOCK.acquire()`; concurrent `download()`
calls now actually run in parallel. The polling loop on the threaded
path reads `len(ctx.dfs)` under the ctx lock.
- `PriceHistory` records soft errors (delisted, missing tz, repair
failure) in `self._last_error` instead of `shared._ERRORS`; the
download loop reads it after `Ticker.history()` returns.
- `yfinance.shared` is left in place for import-compat with code that
may still import it, but yfinance no longer reads or writes it.
- Update existing test_multi to the new `_download_one(ctx, ...)`
signature and add regression tests covering result separation,
no-raise on concurrent calls, and a sentinel proving `shared._DFS`
is no longer used as scratch space.
Yahoo's `/v1/finance/sectors/{key}` and `/industries/{key}` endpoints accept
an ISO 3166-1 alpha-2 `region` query parameter and return regional top
companies/ETFs/funds accordingly. The Domain base class hard-coded `region=US`,
so `Sector("technology").top_companies` always returned U.S. names regardless
of the user's interest.
- Add `region: str = "US"` to `Domain.__init__` and propagate through
`Sector` and `Industry`.
- Normalize input via `.strip().upper()` so "us", " GB ", and "Fr" all work.
- Use `self._region` in the request params.
- Document and test the behavior.
Closes#2601
Yahoo's markettime endpoint silently ignores the `market` parameter and
always returns U.S. data, so `Market("EUROPE").status` previously returned
U.S. status while pretending to be European. The summary endpoint does
honor the parameter and is unaffected.
- Introduce `MarketRegion(str, Enum)` as the single source of truth for
the supported region values, exposed as `yfinance.MarketRegion`.
- Validate `Market(...)` input against the enum and raise `ValueError`
on unknown regions.
- Detect the markettime mismatch: when a non-`US` region is requested
but the response id is `us`, set `status` to `None` and log a warning
rather than returning misleading data.
- Document the markettime limitation and add tests covering validation
and the EUROPE/US fetch behavior.
Closes#2784
Guard both chart-error and chart-result checks against data['chart']
being None, which previously raised TypeError instead of the expected
YFPricesMissingError.
- history.py L270: add 'data["chart"]' truthiness check before accessing ['error']
- history.py L274: add 'not data["chart"]' short-circuit before accessing ['result']
- Add regression test covering chart=None, result=None, missing key, and error payload
The "1mo" branch compared only `dt1.month == dt2.month`, so e.g.
(2024-12-15, 2025-12-15) returned True. The "3mo" branch already
handles year differences via `year_diff`; mirror that by also
requiring `dt1.year == dt2.year`.
Added a test (`test_same_month_different_year`) that fails on the
old logic and passes on the fix. All existing tests still pass.
Concurrent calls to yf.download() from separate threads share the
module-level _DFS, _ERRORS, and _TRACEBACKS dicts, causing one call
to overwrite or read another's results. Serialize access with a
threading.Lock so each download() runs atomically.
Fixes#2557
Pandas 3.0 introduced many changes. One of them is a noisy deprecation warning `Pandas4Warning: Timestamp.utcnow is deprecated and will be removed in a future version. Use Timestamp.now('UTC') instead.`
This PR upgrades YFinance to use the latest Pandas 3.0.0 version, removing the warning
- In utils.py line 165 if the session is None then _requests is
mistakenly passed to as session to data.py which causes attribute
error: module 'requests.cookies' has no attribute 'update'
- The above condition happens only when searching tickers with ISIN
numbers
- Added tests with ISIN numbers
- Added tickerBase to raise an ValueError if an empty tickername is
passed or isin search results in to empty ticker. This is to have
consistent behaviour with utils.get_all_by_isin()
- Corrected ruff check failures
- Rebasing to latest upstream/dev
- Updated the value error to contain the ISIN number that wasn't found
- Check that if result from _fetch was None and either update the result
with additional info or set the result as the additional info.
- Added test_empty_info test case to protect if the behavior in Yahoo
changes.
- Fixed typo on line 1024