Skip to content

Feature: Add Multi-Ticker Info Retrieval API#2886

Open
CalJaDav wants to merge 1 commit into
ranaroussi:devfrom
CalJaDav:feature/multi-ticker-info
Open

Feature: Add Multi-Ticker Info Retrieval API#2886
CalJaDav wants to merge 1 commit into
ranaroussi:devfrom
CalJaDav:feature/multi-ticker-info

Conversation

@CalJaDav

@CalJaDav CalJaDav commented Jul 2, 2026

Copy link
Copy Markdown

Add Multi-Ticker Info Retrieval API

Summary

This PR adds the ability to download company info for multiple tickers in parallel, mirroring the ergonomics of yf.download() for historical data. Users can now call yf.Tickers(["AAPL", "MSFT, "NVDA"]).info to fetch info for all symbols concurrently. This enables the rapid collection of important metadata about the instruments (for example, quote currencies, exhanges).

Motivation

Previously, retrieving info for multiple tickers required either:

  1. Looping and calling .info on individual Ticker objects (slow, serialized)
  2. Using yf.download() for historical data (different API, different return type)

With this PR, metadata retrieval now works like historical downloads: specify multiple tickers, then efficiently retrieve metadata batch. With this implementation, metadata retrieval becomes faster by many orders of magnitude.

Changes

Core Implementation

  • yfinance/multi.py

    • New _InfoCtx context class for per-call thread-safe state (mirrors _DownloadCtx)
    • New public info(tickers, threads=True, progress=False, session=None) function
    • New _info_impl() internal orchestrator with threaded worker support
    • New _info_one_threaded() and _info_one() worker functions
  • yfinance/tickers.py

    • New Tickers.info property
    • New Tickers.get_info(threads=True, progress=False) method
    • Returns: dict[symbol] -> dict keyed by ticker

Testing

  • tests/test_multi.py

    • TestInfoThreadSafety.test_multi_info_best_effort_partial_failure(): Validates one failing ticker doesn't block others
    • TestInfoThreadSafety.test_concurrent_multi_info_calls_keep_results_separate(): Ensures concurrent multi-info calls don't leak state
    • TestInfoThreadSafety.test_multi_info_threads_do_not_serialize_fetches(): Asserts threaded execution is truly parallel
  • tests/test_ticker.py

    • TestTickersInfo.test_get_info_delegates_to_multi(): Validates Tickers.get_info() wiring
    • TestTickersInfo.test_info_property_uses_get_info(): Validates info property delegation

Documentation

  • doc/source/reference/examples/tickers.py: Added short usage example showing tickers.info multi-fetch
  • doc/source/reference/yfinance.ticker_tickers.rst: Added concise reference note on Tickers.info / Tickers.get_info() return type

Usage

import yfinance as yf

tickers = yf.Tickers(["AAPL", "MSFT, "NVDA"])

# Fetch info for all symbols in parallel
infos = tickers.info  # or tickers.get_info()

# Access individual ticker info
print(infos["AAPL"]["symbol"])  # "AAPL"
print(infos["AAPL"]["industry"])  # "Consumer Electronics"
print(infos["MSFT"]["currency"])  # "USD"

- Add yfinance.multi.info() for parallel info fetching across multiple tickers
- Add Tickers.info property and Tickers.get_info() method
- Implement best-effort semantics with per-ticker error handling
- Lock network fetch outside critical section for true parallel execution
- Add comprehensive test coverage for threading and partial failures
- Update reference docs with multi-ticker info usage examples
@ValueRaider

ValueRaider commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Many fetches of info will get your IP rate-limited or blocked.

Some of the metadatas you listed are in history_metadata. For the fields that don't change, use yfinance_cache

@ValueRaider ValueRaider closed this Jul 2, 2026
@ValueRaider ValueRaider reopened this Jul 2, 2026
@CalJaDav

CalJaDav commented Jul 2, 2026

Copy link
Copy Markdown
Author

Many fetches of info will get your IP rate-limited or blocked.

Some of the metadatas you listed are in history_metadata. For the fields that don't change, use yfinance_cache

Good to know. Would you like me to close this out then?

@ValueRaider

Copy link
Copy Markdown
Collaborator

I'm not decided because the code is fine. Are you willing to generalise it to more attributes e.g. calendar? So basically:

  • Rename core fetcher to _attr_impl(ctx, tickers, attr_name, ...
  • Have some callers do a smarter merge e.g. merge dict-of-calendars into a single dataframe.

@CalJaDav

CalJaDav commented Jul 5, 2026

Copy link
Copy Markdown
Author

I'm not decided because the code is fine.

Don't accept it just because I've writing a few lines of halfway decent code! It only took a few hours to put together.

Aside from the persistent caching offered through the cached version of the library, in-memory LRU caches on the Tickers class or even a global singleton cache on the underlying Ticker class get_info methods could help mitigate excessive info spam.

Setting Tickers.get_info(threads=False) as a default with a warning about getting rate limited if threads are used could help as well.

  • Rename core fetcher to _attr_impl(ctx, tickers, attr_name, ...
  • Have some callers do a smarter merge e.g. merge dict-of-calendars into a single dataframe.

Can do. Each attr would probably need its own _xxx_impl method, given the differences in handling and output, with _attr_impl acting as a factory/delegator method.

Let me know if you'd like me to action anything in particular. Happy to burn a few more hours on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants