Skip to content

๐Ÿ“ˆ Yahoo Finance Provider (yfinance)

The Yahoo Finance provider fetches stock, ETF, crypto, and index prices using the yfinance library. It is the primary market data provider for LibreFolio.

Implementation: backend/app/services/asset_source_providers/yahoo_finance/plugin.py

๐Ÿ“– User Guide: Yahoo Finance โ€” User Manual


โš™๏ธ How it Works

  1. Identifier: A Yahoo Finance ticker symbol (e.g., AAPL, BTC-USD, IE00B4L5Y983).
  2. Identifier Types: TICKER and ISIN are both accepted. ISIN is resolved by yfinance internally.
  3. No provider_params: Yahoo Finance does not require any additional configuration.

๐Ÿ’ฐ Current Value (get_current_value)

  1. The asset-source service checks its core current-value cache (120s TTL) before invoking the provider.
  2. Calls ticker.info โ€” the Yahoo quoteSummary endpoint. Returns regularMarketPrice, currency, and regularMarketTime in a single lightweight call.
  3. Fallback price: currentPrice โ†’ previousClose (if regularMarketPrice is null).
  4. No history() call at all โ€” current value polling never touches the chart API.

Avoid history() and fast_info for current price

  • ticker.history() calls the chart API and logs noisy Entering history() lines.
  • ticker.fast_info internally triggers 2 heavy HTTP calls (range=1y + range=5d).
  • ticker.info uses the quoteSummary endpoint โ€” lighter, returns price + currency together.

Cache TTL vs Polling Interval

Frontend polls every 30s for responsive UI, while the core cache has a 120s TTL. Repeated polls for the same provider key can therefore return without another Yahoo call.

๐Ÿ“ˆ Historical Data (get_history_value)

The public method now delegates its local work to focused helpers without changing its contract:

  1. Acquire โ€” _acquire_history_data()
  2. start_date == "min" calls ticker.history(period="max").
  3. A finite range calls ticker.history(start=start_date, end=end_date + 1 day), preserving LibreFolio's inclusive end date over yfinance's exclusive end.
  4. Currency metadata falls back to USD.
  5. Dividend and split series are acquired independently and best-effort; one failing does not suppress the other or the prices.
  6. Map โ€” _map_history_prices()
  7. Yahoo index values are converted to UTC before extracting the calendar date.
  8. Rows are filtered to the requested inclusive range.
  9. A row with Close = NaN is skipped. Optional Open, High, Low, or Volume NaNs become None.
  10. The provider returns only actual trading days; the query layer performs backward fill.
  11. Events โ€” _parse_dividend_events() and _parse_split_events()
  12. Positive in-range dividends and non-trivial in-range split ratios become typed asset events.
  13. The two parsers are also isolated best-effort, so either event family can survive a failure in the other.

Validation and data failures remain typed AssetSourceErrors: unsupported identifier types use INVALID_IDENTIFIER_TYPE, a missing optional dependency uses NOT_AVAILABLE, empty/unusable history uses NO_DATA, and malformed or unexpected Yahoo responses use FETCH_ERROR.

No provider-internal thread hop

Yahoo's yfinance calls remain synchronous and direct. The provider does not call asyncio.to_thread(); the asset-source service invokes the whole provider coroutine through asset_sources.core._run_provider_in_thread() in a dedicated thread with a new event loop.

  • Uses yfinance.Search(query) for real-time ticker search.
  • Minimum query length: 2 characters.
  • Results limited to top 20 quotes.
  • quoteType is normalized to LibreFolio asset types: equity โ†’ STOCK, etf โ†’ ETF, mutualfund โ†’ FUND, cryptocurrency โ†’ CRYPTO, etc.
  • Currency is fetched per-symbol via _fetch_currency() (cached separately, 24-hour TTL).

๐Ÿ“‹ Metadata (fetch_asset_metadata)

  • Fetches full ticker.info from Yahoo Finance.
  • Extracts: asset_type, currency, short_description (from longBusinessSummary), sector (single-sector distribution), identifier_ticker, identifier_isin.
  • ISIN is obtained via ticker.isin (not available for all markets).
  • Unknown sectors are logged as warnings and mapped to "Other".

๐Ÿ”— get_asset_url

Returns https://finance.yahoo.com/quote/{identifier}.

๐Ÿ“… Asset Events

During sync, the provider generates:

  • DIVIDEND events from ticker.dividends โ€” ex-dividend date + per-share amount.
  • SPLIT events from ticker.splits โ€” split date + ratio value (e.g., 4.0 for a 4:1 split).

Event acquisition and parsing are best-effort and independent. Events that are returned are persisted by asset_sources/price_store.py::_upsert_asset_events(), keyed by provider_assignment_id.


โšก Caching Strategy

Owner / Cache Key TTL Max Size Purpose
Core current value Provider code + identifier + identifier type (refresh also includes the provider-parameter hash) 120 sec 300 Avoid repeated ticker.info calls during current-price polling and refresh.
Core history Provider code + identifier + identifier type + provider-parameter hash 15 min 500 Reuse fetched date ranges during provider-driven refresh.
Core search query Provider code + normalized query 15 min 500 Avoid repeating the same provider search.
Yahoo currency lookup symbol 24 hours 2000 Cache the provider's fast_info currency sub-operation used by search().

All are in-memory, per-process TTL caches created with get_ttl_cache(). The shared result caches are owned by asset_sources/core.py; Yahoo owns only its currency sub-operation cache.

No provider-level history cache

Yahoo has no provider-level history cache. The outer refresh layer may reuse its core history cache and persists fetched prices to the database. get_prices_bulk() is DB-only; it never calls Yahoo while serving a historical query (see Architecture โ€” Price Query).


๐Ÿงช Test Configuration

Property Value
test_cases [{identifier: "AAPL", identifier_type: TICKER}]
test_search_query "Apple"

โš ๏ธ Limitations

  • Rate limits: Yahoo Finance may throttle requests. No built-in rate limiter โ€” rely on core sync Semaphore.
  • ISIN resolution: Not all ISINs are resolvable by yfinance (depends on market coverage).
  • Data gaps: Some tickers may have missing days or delayed data.

๐Ÿ“ฆ Dependency

  • Library: yfinance โ€” installed via pipenv install yfinance.
  • Optional import: If yfinance is not installed, current/history/search calls raise an AssetSourceError with error code NOT_AVAILABLE; metadata refresh degrades to None.
  • Transitive: pandas (required by yfinance).