--- # yfinance-tools.yaml # Tool catalog for the `yfinance` Python library (v1.4.1). # yfinance scrapes public Yahoo! Finance endpoints (v7/v10/v8 chart, quote, # options, fundamentals, websocket) to expose market data in a Pythonic way. # Every tool that touches Yahoo is `openWorldHint: true`; pure local helpers # (config, cache directory, in-process collection builders) stay false. # Parameter names, defaults and enums below mirror the real Python signatures # in `yfinance/` — keep them in sync if the upstream API changes. # Style mirrors ./tools.yaml (Portainer MCP catalog). version: v1.0 tools: ## Ticker — single-symbol data ## Wraps `yfinance.Ticker(symbol, session=None)` and its ~50 @property ## accessors. The Python-side optional `session=` argument is intentionally ## omitted from each tool below; it is a per-process HTTP/session override ## that does not translate well to a serialized tool call. ## ------------------------------------------------------------ - name: tickerInfo description: >- Return the full company / instrument profile dict for one symbol — company description, sector, industry, officers, exchange metadata plus a snapshot of current price, market cap and key ratios. Wraps `Ticker(symbol).get_info()` which hits Yahoo `quoteSummary` (heavy). Use `tickerFastInfo` when you only need price / volume. parameters: - name: symbol description: Yahoo ticker symbol (e.g. "AAPL", "MSFT", "0700.HK", "BTC-USD", "EURUSD=X", "^GSPC"). type: string required: true annotations: title: Get Ticker Info readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickerFastInfo description: >- Lightweight quote snapshot via `Ticker(symbol).get_fast_info()`. Exposes a dict-like `FastInfo` with: currency, quoteType, exchange, timezone, shares, lastPrice, previousClose, regularMarketPreviousClose, open, dayHigh, dayLow, lastVolume, fiftyDayAverage, twoHundredDayAverage, tenDayAverageVolume, threeMonthAverageVolume, yearHigh, yearLow, yearChange, marketCap. Skips quoteSummary, so much faster than `tickerInfo` and safer for high-frequency polling. parameters: - name: symbol type: string required: true annotations: title: Get Ticker Fast Info readOnlyHint: true destructiveHint: false idempotentHint: false openWorldHint: true - name: tickerHistory description: >- Download OHLCV history for one symbol via `Ticker(symbol).history(...)`. Returns a pandas DataFrame indexed by Date/Datetime with columns Open, High, Low, Close, Volume, Dividends, Stock Splits (plus Capital Gains for funds). The DataFrame's `.attrs["history_metadata"]` carries Yahoo's chart metadata. parameters: - name: symbol type: string required: true - name: period description: >- Lookback window. Default is '1mo' when start/end are not given, otherwise null (use start/end). Mutually exclusive with start/end — but can be combined for `end = start + period`. Use "max" for full history. type: string required: false enum: - "1d" - "5d" - "1mo" - "3mo" - "6mo" - "1y" - "2y" - "5y" - "10y" - "ytd" - "max" - name: interval description: >- Bar size. Default "1d". Intraday intervals (1m, 2m, 5m, 15m, 30m, 60m, 90m, 1h) cannot extend more than ~60 days back. type: string required: false enum: - "1m" - "2m" - "5m" - "15m" - "30m" - "60m" - "90m" - "1h" - "1d" - "5d" - "1wk" - "1mo" - "3mo" - name: start description: >- Inclusive start. ISO date "YYYY-MM-DD" or datetime. Default 99 years ago. type: string required: false - name: end description: >- Exclusive end. ISO date "YYYY-MM-DD" or datetime. Default now. For end="2023-01-01", last bar = 2022-12-31. type: string required: false - name: prepost description: Include pre/post-market bars for intraday intervals. Default false. type: boolean required: false - name: actions description: Include Dividends and Stock Splits columns. Default true. type: boolean required: false - name: auto_adjust description: >- If true (default), all OHLC are back-adjusted for splits and dividends. Set false to keep raw OHLC plus a separate Adj Close. type: boolean required: false - name: back_adjust description: Back-adjusted data to mimic true historical prices. Default false. type: boolean required: false - name: repair description: >- Run scipy-backed heuristics that detect Yahoo's known bad-tick patterns (100x / 0.01x splits, missing dividends, currency-unit flips) and rewrite affected bars. Requires the `repair` extra. Not supported with interval "5d"; for "1wk"/"1mo"/"3mo" the scraper silently fetches 1d and resamples. Default false. type: boolean required: false - name: keepna description: Keep rows where every OHLC value is NaN (Yahoo holiday rows). Default false. type: boolean required: false - name: rounding description: Round prices to 2 decimals. Default false → use Yahoo precision. type: boolean required: false - name: timeout description: Per-request timeout in seconds. Default 10. Can be a float (0.01 ok). type: number required: false - name: raise_errors description: >- Deprecated alias — use `yf.config.debug.hide_exceptions = false`. If true, raise on errors instead of logging. Default false. type: boolean required: false annotations: title: Get Ticker History readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickerHistoryMetadata description: >- Return the metadata Yahoo attaches to the chart response: exchange, timezone, currency, regular-market hours, instrument type, firstTradeDate, validRanges, etc. Calls `Ticker(symbol).get_history_metadata()`. parameters: - name: symbol type: string required: true annotations: title: Get History Metadata readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickerActions description: >- Return one action stream as a pandas Series (or combined DataFrame for "actions"). Wraps `get_dividends / get_splits / get_capital_gains / get_actions`. All accept a `period` argument that defaults to "max". parameters: - name: symbol type: string required: true - name: kind description: Which action stream to return. "actions" merges dividends + splits. type: string required: false enum: - "actions" - "dividends" - "splits" - "capital_gains" - name: period description: Lookback window. Default "max". type: string required: false enum: - "1d" - "5d" - "1mo" - "3mo" - "6mo" - "1y" - "2y" - "5y" - "10y" - "ytd" - "max" annotations: title: Get Ticker Actions readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickerFinancials description: >- Return one of the three financial statements as a DataFrame. Rows are line items, columns are period end dates. Wraps `get_income_stmt / get_balance_sheet / get_cash_flow`. With `pretty=true` Yahoo's camelCase keys are translated to human row labels via the maps in `yfinance/const.py`. parameters: - name: symbol type: string required: true - name: statement description: Which statement to retrieve. type: string required: true enum: - "income_stmt" - "balance_sheet" - "cash_flow" - name: freq description: Reporting frequency. "trailing" = TTM (income_stmt / cash_flow only; balance_sheet has no TTM). type: string required: false enum: - "yearly" - "quarterly" - "trailing" - name: pretty description: Translate raw Yahoo keys to human-readable labels. Default false. type: boolean required: false - name: as_dict description: Return the result as a plain dict instead of a DataFrame. Default false. type: boolean required: false annotations: title: Get Ticker Financials readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickerValuationMeasures description: >- Historical valuation ratios (P/E, P/B, P/S, EV/EBITDA, EV/Revenue, market cap) as a DataFrame via `get_valuation_measures()`. parameters: - name: symbol type: string required: true annotations: title: Get Valuation Measures readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickerEarnings description: >- Historical revenue + earnings table per year or quarter via `get_earnings(freq=)`. For forward-looking estimates use `tickerAnalystEstimates`. parameters: - name: symbol type: string required: true - name: freq description: Default "yearly". type: string required: false enum: - "yearly" - "quarterly" - name: as_dict description: Return dict instead of DataFrame. Default false. type: boolean required: false annotations: title: Get Ticker Earnings readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickerEarningsDates description: >- Upcoming + recent earnings dates with EPS estimate, reported EPS and surprise %. Wraps `get_earnings_dates(limit=, offset=)`. Yahoo caps `limit` at 100; offset=0 starts from future estimates, offset=N skips that many quarters back. parameters: - name: symbol type: string required: true - name: limit description: Max rows to return. Default 12, max 100. type: number required: false - name: offset description: Skip this many quarters before reading. Default 0. type: number required: false annotations: title: Get Earnings Dates readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickerAnalystEstimates description: >- Forward-looking analyst data. Wraps the seven `Ticker.get_*` methods under `yfinance/scrapers/analysis.py` plus the `recommendations*`/`upgrades_downgrades` methods on `TickerBase`. Most return a DataFrame; `analyst_price_targets` returns a dict. parameters: - name: symbol type: string required: true - name: kind description: Which analyst dataset to return. type: string required: true enum: - "analyst_price_targets" - "earnings_estimate" - "revenue_estimate" - "earnings_history" - "eps_trend" - "eps_revisions" - "growth_estimates" - "recommendations" - "recommendations_summary" - "upgrades_downgrades" - name: as_dict description: Return dict instead of DataFrame (where applicable). Default false. type: boolean required: false annotations: title: Get Analyst Estimates readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickerHolders description: >- Ownership data via the `holders` scraper. `major_holders` returns the breakdown table; the other kinds return per-holder DataFrames. parameters: - name: symbol type: string required: true - name: kind type: string required: true enum: - "major_holders" - "institutional_holders" - "mutualfund_holders" - "insider_purchases" - "insider_transactions" - "insider_roster_holders" - name: as_dict description: Return dict instead of DataFrame. Default false. type: boolean required: false annotations: title: Get Ticker Holders readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickerCalendar description: >- Next earnings + dividend + split events for one symbol as a dict. Wraps `Ticker(symbol).get_calendar()`. (This is the per-symbol calendar; for market-wide event calendars see `getCalendars`.) parameters: - name: symbol type: string required: true annotations: title: Get Ticker Calendar readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickerNews description: >- Recent Yahoo Finance news items for one symbol. Wraps `Ticker(symbol).get_news(count=, tab=)`. Returns a list of dicts with title, link, publisher, providerPublishTime, type, thumbnails, etc. parameters: - name: symbol type: string required: true - name: count description: Number of articles to return. Default 10. type: number required: false - name: tab description: Yahoo news tab. Default "news". type: string required: false enum: - "news" - "all" - "press releases" annotations: title: Get Ticker News readOnlyHint: true destructiveHint: false idempotentHint: false openWorldHint: true - name: tickerSecFilings description: SEC filings (10-K, 10-Q, 8-K, etc.) Yahoo has surfaced for the symbol. Wraps `get_sec_filings()`. parameters: - name: symbol type: string required: true annotations: title: Get SEC Filings readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickerSustainability description: ESG / sustainability scores DataFrame, when Yahoo publishes one for the symbol. Wraps `get_sustainability(as_dict=)`. parameters: - name: symbol type: string required: true - name: as_dict description: Return dict instead of DataFrame. Default false. type: boolean required: false annotations: title: Get Sustainability Scores readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickerIsin description: >- Return the ISIN for the symbol. Best-effort and **experimental** — depends on a businessinsider.com lookup keyed off `Ticker.info`'s shortName; will return "-" if not resolvable. parameters: - name: symbol type: string required: true annotations: title: Get ISIN readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickerShares description: >- Share-count history DataFrame (basic & diluted shares outstanding over time) from the fundamentals time-series endpoint. Wraps `get_shares(as_dict=)`. parameters: - name: symbol type: string required: true - name: as_dict type: boolean required: false annotations: title: Get Shares Outstanding readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickerSharesFull description: >- Full daily shares-outstanding Series between two dates. Wraps `get_shares_full(start=, end=)`. Default window is the last 18 months. parameters: - name: symbol type: string required: true - name: start description: ISO date / datetime. Default = end - 548 days. type: string required: false - name: end description: ISO date / datetime. Default now. type: string required: false annotations: title: Get Shares Outstanding (Full) readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickerOptionExpirations description: >- List the available option expiration dates for a symbol (sorted ascending, "YYYY-MM-DD" strings). Wraps `Ticker(symbol).options`. parameters: - name: symbol type: string required: true annotations: title: List Option Expirations readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickerOptionChain description: >- Full option chain for one expiration via `Ticker(symbol).option_chain(date=, tz=)`. Returns a NamedTuple `(calls, puts, underlying)` where calls/puts are DataFrames with contractSymbol, lastTradeDate, strike, lastPrice, bid, ask, change, percentChange, volume, openInterest, impliedVolatility, inTheMoney, contractSize, currency. parameters: - name: symbol type: string required: true - name: date description: 'Expiration date "YYYY-MM-DD". Omit to use the nearest expiration.' type: string required: false - name: tz description: 'Convert lastTradeDate to this timezone (e.g. "America/New_York").' type: string required: false annotations: title: Get Option Chain readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickerFundsData description: >- ETF / mutual-fund specific fields via `Ticker.get_funds_data()`. The resulting `FundsData` exposes properties: `quote_type`, `description`, `fund_overview`, `fund_operations` (DataFrame), `asset_classes` (dict), `top_holdings` (DataFrame), `equity_holdings`, `bond_holdings`, `bond_ratings`, `sector_weightings`. parameters: - name: symbol type: string required: true annotations: title: Get Funds Data readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickerLive description: >- Subscribe to live ticks for ONE symbol using `Ticker(symbol).live()`. Blocking; calls `message_handler(dict)` for each decoded protobuf message. For multi-symbol streams use `streamLiveQuotes`. parameters: - name: symbol type: string required: true - name: verbose description: Print connection / subscription notices to stdout. Default true. type: boolean required: false annotations: title: Stream One Ticker Live readOnlyHint: true destructiveHint: false idempotentHint: false openWorldHint: true ## Multi-ticker — batch downloads + collection ## ------------------------------------------------------------ - name: downloadHistory description: >- Bulk download OHLCV for many symbols in parallel via `yfinance.download`. Returns a single (multi-indexed) DataFrame. Preferred over a loop of `tickerHistory` calls for portfolio sweeps. parameters: - name: tickers description: 'Space- or comma-separated string ("AAPL MSFT NVDA") OR an array of symbols. ISINs are auto-resolved to tickers.' type: array required: true items: type: string - name: start description: ISO date / datetime, inclusive. Default 99 years ago. type: string required: false - name: end description: ISO date / datetime, exclusive. Default now. type: string required: false - name: period description: Lookback window. Default "1mo" when start & end are not given. type: string required: false enum: - "1d" - "5d" - "1mo" - "3mo" - "6mo" - "1y" - "2y" - "5y" - "10y" - "ytd" - "max" - name: interval description: Bar size. Default "1d". Intraday capped at ~60 days. type: string required: false enum: - "1m" - "2m" - "5m" - "15m" - "30m" - "60m" - "90m" - "1h" - "1d" - "5d" - "1wk" - "1mo" - "3mo" - name: group_by description: 'Top-level column grouping. Default "column" → columns are field names; "ticker" → columns are symbols.' type: string required: false enum: - "ticker" - "column" - name: actions description: Include dividend + stock-split columns. Default false. type: boolean required: false - name: auto_adjust description: Adjust all OHLC automatically. Default true. type: boolean required: false - name: back_adjust description: Back-adjusted to mimic true historical prices. Default false. type: boolean required: false - name: repair description: Detect currency-unit 100x mixups and attempt repair. Default false. type: boolean required: false - name: keepna description: Keep NaN rows returned by Yahoo. Default false. type: boolean required: false - name: prepost description: Include pre/post-market data. Default false. type: boolean required: false - name: threads description: 'Use multitasking to parallelize per-symbol requests. true → auto pool size (min(N, cpu*2)); int → exact pool size; false → serial. Default true.' type: boolean required: false - name: ignore_tz description: Strip tz info from the index so multi-market frames align. Default true for ≥1d intervals, false for intraday. type: boolean required: false - name: progress description: Show progress bar. Default true. Forced off when DEBUG logging is on. type: boolean required: false - name: rounding description: Round prices to 2 decimals. Default false. type: boolean required: false - name: timeout description: Per-request timeout in seconds (float ok). Default 10. type: number required: false - name: multi_level_index description: Always return a MultiIndex DataFrame even for a single symbol. Default true. type: boolean required: false annotations: title: Download Multi-Ticker History readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickersContainer description: >- Construct a `Tickers` collection holding individual Ticker instances keyed by symbol — convenient when you want per-symbol property access without calling `Ticker(...)` in a loop. Exposes `.history(...)`, `.download(...)`, `.news()`, `.live()` methods. parameters: - name: tickers description: Space-separated string or array of symbols. type: array required: true items: type: string annotations: title: Build Tickers Collection readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: false - name: tickersHistory description: >- Multi-symbol `Tickers.history(...)`. Thin wrapper around `downloadHistory` that also populates each child `Ticker._history` attribute. Use `downloadHistory` instead unless you need the Tickers object to retain history caches. parameters: - name: tickers type: array required: true items: type: string - name: period type: string required: false - name: interval type: string required: false - name: start type: string required: false - name: end type: string required: false - name: prepost type: boolean required: false - name: actions type: boolean required: false - name: auto_adjust type: boolean required: false - name: repair type: boolean required: false - name: threads type: boolean required: false - name: group_by type: string required: false enum: - "ticker" - "column" - name: progress type: boolean required: false - name: timeout type: number required: false annotations: title: Tickers Collection History readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: tickersNews description: 'Per-symbol news for every ticker in the collection. Returns `{symbol: [news, ...]}` via `Tickers(tickers).news()`.' parameters: - name: tickers type: array required: true items: type: string annotations: title: Tickers Collection News readOnlyHint: true destructiveHint: false idempotentHint: false openWorldHint: true ## Search & Lookup — symbol discovery ## ------------------------------------------------------------ - name: searchTickers description: >- Yahoo Finance search by keyword / company name via `yf.Search(query, ...)`. Wraps `/v1/finance/search`. Returns quotes, news, lists, research reports and nav links. Constructor runs the search immediately; the returned object exposes `.quotes`, `.news`, `.lists`, `.research`, `.nav`, `.all`, `.response`. parameters: - name: query description: Search query (ticker, partial ticker, or company name). type: string required: true - name: max_results description: Max stock quotes to return. Default 8. type: number required: false - name: news_count description: Number of news articles. Default 8. type: number required: false - name: lists_count description: Number of curated lists. Default 8. type: number required: false - name: include_cb description: Include the company breakdown. Default true. type: boolean required: false - name: include_nav_links description: Include navigation links. Default false. type: boolean required: false - name: include_research description: Include research reports. Default false. type: boolean required: false - name: include_cultural_assets description: Include cultural assets. Default false. type: boolean required: false - name: enable_fuzzy_query description: Enable fuzzy search for typos. Default false. type: boolean required: false - name: recommended description: Recommended number of results. Default 8. type: number required: false - name: timeout description: Request timeout in seconds. Default 30. type: number required: false - name: raise_errors description: Raise exceptions on error. Default true. type: boolean required: false annotations: title: Search Tickers readOnlyHint: true destructiveHint: false idempotentHint: false openWorldHint: true - name: lookupTickers description: >- Fuzzy symbol lookup across asset classes via `yf.Lookup(query, ...)`. Per asset class call `.get_all / .get_stock / .get_mutualfund / .get_etf / .get_index / .get_future / .get_currency / .get_cryptocurrency`, each accepting `count=` (default 25). Returns structured DataFrames of candidate symbols. parameters: - name: query type: string required: true - name: type description: 'Restrict to one asset class. Maps to `Lookup.get_()`. Default "all".' type: string required: false enum: - "all" - "stock" - "mutualfund" - "etf" - "index" - "future" - "currency" - "cryptocurrency" - name: count description: Max rows. Default 25. type: number required: false - name: timeout description: Request timeout in seconds. Default 30. type: number required: false - name: raise_errors description: Raise on error instead of logging. Default true. type: boolean required: false annotations: title: Lookup Tickers readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true ## Domain — Market / Sector / Industry ## ------------------------------------------------------------ - name: marketSummary description: >- Market overview for a region via `yf.Market(market).summary`. Hits `/v6/finance/quote/marketSummary` for shortName / regularMarketPrice / regularMarketChange / regularMarketChangePercent of every exchange/index Yahoo tracks for that region. Returns a dict keyed by exchange. parameters: - name: market description: Yahoo `MarketRegion` enum value. (Yahoo only honors a fixed set — passing other ISO country codes raises ValueError.) type: string required: true enum: - "US" - "GB" - "ASIA" - "EUROPE" - "RATES" - "COMMODITIES" - "CURRENCIES" - "CRYPTOCURRENCIES" - name: timeout description: Request timeout in seconds. Default 30. type: number required: false annotations: title: Get Market Summary readOnlyHint: true destructiveHint: false idempotentHint: false openWorldHint: true - name: marketStatus description: >- Open/closed status, open/close timestamps, and timezone for a region's primary exchange via `yf.Market(market).status`. Yahoo's `/v6/finance/markettime` silently returns US data for non-US requests; the scraper logs a warning and yields None in that case. parameters: - name: market type: string required: true enum: - "US" - "GB" - "ASIA" - "EUROPE" - "RATES" - "COMMODITIES" - "CURRENCIES" - "CRYPTOCURRENCIES" - name: timeout type: number required: false annotations: title: Get Market Status readOnlyHint: true destructiveHint: false idempotentHint: false openWorldHint: true - name: sectorInfo description: >- Aggregate info for a Yahoo sector via `yf.Sector(key, region=)`. Exposes properties `name`, `symbol`, `ticker`, `overview`, `top_companies`, `top_etfs`, `top_mutual_funds`, `industries`, `research_reports`. parameters: - name: key description: Sector slug (lowercase-hyphenated). type: string required: true enum: - "basic-materials" - "communication-services" - "consumer-cyclical" - "consumer-defensive" - "energy" - "financial-services" - "healthcare" - "industrials" - "real-estate" - "technology" - "utilities" - name: region description: 'ISO 3166-1 alpha-2 country code (scopes top_companies/etfs/funds). Default "US".' type: string required: false - name: attribute description: Which property to return. Default returns the whole `Sector` object's state as a dict. type: string required: false enum: - "overview" - "top_companies" - "top_etfs" - "top_mutual_funds" - "industries" - "research_reports" - "name" - "symbol" annotations: title: Get Sector Info readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: industryInfo description: >- Aggregate info for a Yahoo industry via `yf.Industry(key, region=)`. Exposes `sector_key`, `sector_name`, `overview`, `top_companies`, `top_performing_companies`, `top_growth_companies`, `research_reports`. parameters: - name: key description: Industry slug (e.g. "software-infrastructure", "semiconductors"). type: string required: true - name: region description: 'ISO 3166-1 alpha-2 country code. Default "US".' type: string required: false - name: attribute description: Which property to return. type: string required: false enum: - "overview" - "top_companies" - "top_performing_companies" - "top_growth_companies" - "research_reports" - "sector_key" - "sector_name" annotations: title: Get Industry Info readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true ## Calendars — earnings / IPO / economic events / splits (market-wide) ## yf.Calendars(start=, end=) → call any of the four getters below. ## ------------------------------------------------------------ - name: getEarningsCalendar description: >- Market-wide earnings calendar via `Calendars(start, end).get_earnings_calendar(...)`. Returns a DataFrame sorted by Event Start Date desc. Default window is today → today + 7 days when start/end are omitted. parameters: - name: start description: Window start date (ISO / datetime). Default today. Set with `end` together. type: string required: false - name: end description: Window end date. Default start + 7 days. type: string required: false - name: market_cap description: Minimum market cap cutoff in USD. Default null (no filter). type: number required: false - name: filter_most_active description: Filter for actively traded stocks. Default true. Disabled internally when `offset > 0`. type: boolean required: false - name: limit description: Max rows. Default 12. Yahoo caps at 100. type: number required: false - name: offset description: Pagination offset. Default 0. type: number required: false - name: force description: Re-query even if a previous call cached the same body. Default false. type: boolean required: false annotations: title: Get Earnings Calendar readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: getIpoInfoCalendar description: 'IPO calendar via `Calendars(start, end).get_ipo_info_calendar(...)`.' parameters: - name: start type: string required: false - name: end type: string required: false - name: limit description: Max rows. Default 12, capped at 100. type: number required: false - name: offset type: number required: false - name: force type: boolean required: false annotations: title: Get IPO Calendar readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: getEconomicEventsCalendar description: >- Economic events calendar (CPI, FOMC, etc.) via `Calendars(start, end).get_economic_events_calendar(...)`. parameters: - name: start type: string required: false - name: end type: string required: false - name: limit type: number required: false - name: offset type: number required: false - name: force type: boolean required: false annotations: title: Get Economic Events Calendar readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: getSplitsCalendar description: 'Upcoming stock-splits calendar via `Calendars(start, end).get_splits_calendar(...)`.' parameters: - name: start type: string required: false - name: end type: string required: false - name: limit type: number required: false - name: offset type: number required: false - name: force type: boolean required: false annotations: title: Get Splits Calendar readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true ## Screener — yf.EquityQuery / FundQuery / ETFQuery + yf.screen ## ------------------------------------------------------------ - name: screenMarket description: >- Run `yf.screen(query, ...)`. `query` may be the name of a predefined Yahoo screener (string — e.g. "day_gainers") OR a serialized query tree from `EquityQuery / FundQuery / ETFQuery` (object). Returns Yahoo's `finance.result[0]` payload with the matched quotes. Note: `size` is for custom queries (default 100, max 250); `count` is for predefined queries (default 25, max 250). Yahoo's predefined endpoint ignores `offset` — when an offset is supplied with a predefined name, the call transparently switches to the custom-query endpoint. parameters: - name: query description: >- Either a string (predefined screener name from `PREDEFINED_SCREENER_QUERIES`) or a QueryBase serialization, e.g. `{"operator": "and", "operands": [{"operator":"gt", "operands":["intradaymarketcap", 1e10]}, {"operator":"lt", "operands":["peratio.lasttwelvemonths", 20]}]}`, plus a `_quoteType` hint of "EQUITY" / "MUTUALFUND" / "ETF". type: object required: true - name: size description: Result count for custom queries. Default 100, max 250. type: number required: false - name: count description: Result count for predefined queries. Default 25, max 250. type: number required: false - name: offset description: Pagination offset. Default 0. type: number required: false - name: sortField description: 'Yahoo field id to sort by (e.g. "intradaymarketcap", "percentchange", "dayvolume"). Default "ticker" for custom; predefined defaults baked into each template.' type: string required: false - name: sortAsc description: Sort ascending. Default false (descending). type: boolean required: false - name: userId description: Yahoo user ID. Default empty. type: string required: false - name: userIdType description: 'Type of user ID. Default "guid".' type: string required: false annotations: title: Screen Market readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: true - name: listPredefinedScreeners description: >- Return the keys (and optionally the full bodies) of `PREDEFINED_SCREENER_QUERIES`. Examples: `aggressive_small_caps`, `day_gainers`, `day_losers`, `growth_technology_stocks`, `most_actives`, `most_shorted_stocks`, `small_cap_gainers`, `undervalued_growth_stocks`, `undervalued_large_caps`, `conservative_foreign_funds`, `high_yield_bond`, `portfolio_anchors`, `solid_large_growth_funds`, `solid_midcap_growth_funds`, `top_mutual_funds`, `top_etfs_us`, `top_performing_etfs`, `technology_etfs`, `bond_etfs`. parameters: - name: include_bodies description: When true, return each entry's full QueryBase tree, not just the name. Default false. type: boolean required: false annotations: title: List Predefined Screeners readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: false - name: buildScreenerQuery description: >- Construct an `EquityQuery / FundQuery / ETFQuery` programmatically. Use this when assembling a custom screener before calling `screenMarket`. Operators are validated against the per-universe `valid_fields` and `valid_values` maps in `yfinance/const.py`. parameters: - name: queryType description: Which screener universe to build for. type: string required: true enum: - "equity" - "mutualfund" - "etf" - name: operator description: >- Top-level operator. Value operators take a [field, value] (or [field, lo, hi] for btwn, [field, v1, v2, ...] for is-in); logical operators take a list of nested queries. type: string required: true enum: - "eq" - "is-in" - "btwn" - "gt" - "lt" - "gte" - "lte" - "and" - "or" - name: operands description: 'Operand list. Each entry is either a leaf (string field name + scalar) or a nested query object (operator + operands).' type: array required: true items: type: object annotations: title: Build Screener Query readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: false ## Live streaming — Yahoo WebSocket (protobuf-encoded) ## ------------------------------------------------------------ - name: streamLiveQuotes description: >- Open a Yahoo WebSocket and stream real-time pricing for a set of symbols. Wraps `yf.WebSocket(url=, verbose=)` (sync) or `yf.AsyncWebSocket(url=, verbose=)` (asyncio). After construction, call `subscribe(symbols)` then `listen(message_handler)`. Messages are protobuf-encoded per `yfinance/pricing.proto`. The async variant additionally maintains a heartbeat-subscribe task. parameters: - name: symbols description: Symbols to subscribe to. Single string or array. type: array required: true items: type: string - name: mode description: '"sync" → `WebSocket`; "async" → `AsyncWebSocket` (must be awaited).' type: string required: false enum: - "sync" - "async" - name: url description: 'WebSocket server URL. Default "wss://streamer.finance.yahoo.com/?version=2".' type: string required: false - name: verbose description: Print connection / subscription / message text to stdout. Default true. type: boolean required: false - name: durationSeconds description: How long to listen before closing. Omit to listen indefinitely (Ctrl-C / `close()` to stop). type: number required: false annotations: title: Stream Live Quotes readOnlyHint: true destructiveHint: false idempotentHint: false openWorldHint: true - name: liveSubscribe description: 'Add symbols to an existing live stream (`WebSocket.subscribe`). Sends `{"subscribe": [...]}`. Async variant must be awaited.' parameters: - name: symbols type: array required: true items: type: string annotations: title: Subscribe Live Symbols readOnlyHint: false destructiveHint: false idempotentHint: true openWorldHint: true - name: liveUnsubscribe description: 'Remove symbols from an existing live stream (`WebSocket.unsubscribe`). Sends `{"unsubscribe": [...]}`.' parameters: - name: symbols type: array required: true items: type: string annotations: title: Unsubscribe Live Symbols readOnlyHint: false destructiveHint: true idempotentHint: true openWorldHint: true ## Auth — Yahoo crumb / cookie challenge ## ------------------------------------------------------------ - name: authSetCookies description: >- Inject existing Yahoo login cookies (T / Y) into the shared `YfData` session via `Auth.set_login_cookies(cookie_t, cookie_y)`. Required when scraping account-gated data. Cookies stay in the Singleton session for the lifetime of the process. parameters: - name: cookie_t description: Value of the Yahoo "T" cookie. type: string required: true - name: cookie_y description: Value of the Yahoo "Y" cookie. type: string required: true annotations: title: Set Yahoo Login Cookies readOnlyHint: false destructiveHint: false idempotentHint: true openWorldHint: false - name: authStrategy description: >- Force the cookie-acquisition strategy used by `YfData`. "basic" hits the plain cookie endpoint; "csrf" follows the consent + CSRF flow (needed in EU regions). The default ("basic") falls back to "csrf" automatically on failure. parameters: - name: strategy type: string required: true enum: - "basic" - "csrf" annotations: title: Set Yahoo Auth Strategy readOnlyHint: false destructiveHint: false idempotentHint: true openWorldHint: true ## Config & Cache — local-state helpers ## ------------------------------------------------------------ - name: setConfig description: >- Update the global `yf.config` (proxy, retry count, locale, debug flags). Mutates a process-wide singleton; affects every subsequent request. parameters: - name: proxy description: 'HTTP/HTTPS proxy URL. Updates `yf.config.network.proxy`. Default null.' type: string required: false - name: retries description: Retry attempts on transient HTTP failures. Updates `yf.config.network.retries`. Default 0. type: number required: false - name: lang description: 'BCP-47 language tag for Yahoo v7/v10 endpoints. Updates `yf.config.locale.lang`. Default "en-US".' type: string required: false - name: region description: 'ISO 3166-1 alpha-2 country code. Updates `yf.config.locale.region`. Default "US".' type: string required: false - name: hideExceptions description: 'Swallow non-fatal scraper exceptions and return empty data. Updates `yf.config.debug.hide_exceptions`. Default true.' type: boolean required: false - name: logging description: 'Enable verbose yfinance logging. Updates `yf.config.debug.logging` (same as `enable_debug_mode()`). Default false.' type: boolean required: false annotations: title: Set yfinance Config readOnlyHint: false destructiveHint: false idempotentHint: true openWorldHint: false - name: getConfig description: Dump the current `yf.config` tree as JSON. annotations: title: Get yfinance Config readOnlyHint: true destructiveHint: false idempotentHint: true openWorldHint: false - name: enableDebugMode description: Shortcut for `yf.enable_debug_mode()` — turns on internal logging at DEBUG level. annotations: title: Enable Debug Mode readOnlyHint: false destructiveHint: false idempotentHint: true openWorldHint: false - name: setTzCacheLocation description: >- Point yfinance's SQLite tz / cookie cache at a custom directory via `yf.set_tz_cache_location(path)`. Useful for tests or when the default platformdirs path is read-only. parameters: - name: path description: Absolute filesystem path to the cache directory. type: string required: true annotations: title: Set TZ Cache Location readOnlyHint: false destructiveHint: false idempotentHint: true openWorldHint: false - name: clearTzCache description: >- Delete the on-disk tz / cookie cache directory (the next request will re-create it). Destructive against local state only; does not touch Yahoo. parameters: - name: path description: Cache directory to remove. Defaults to the active location. type: string required: false annotations: title: Clear TZ Cache readOnlyHint: false destructiveHint: true idempotentHint: true openWorldHint: false # ============================================================================ # CLI design — `yfin` # ---------------------------------------------------------------------------- # Wraps every tool above as a subcommand of a single binary, `yfin`. # Every `command:` field below shows the exact CLI invocation; every # `tool:` field is a back-reference to the matching `tools[].name` so the # generator script (`scripts/gen-cli.py`, planned) can scaffold Typer # commands directly from this section without drift. # ============================================================================ cli: binary: yfin entry_point: yfin.__main__:app description: >- Single-binary CLI for the yfinance Python library. All 49 tools above are reachable as `yfin [args] [flags]`. Output defaults to a Rich-formatted table on a TTY, JSON when stdout is a pipe; override with `--format` or write to disk with `--out`. framework: Typer + Rich python: ">=3.9" dependencies: - "typer>=0.12" - "rich>=13" - "yfinance>=1.4.1" # the wrapped library - "pyarrow>=14" # for --format parquet - "PyYAML>=6" # so the CLI can load this file as its own SSOT packaging: pyproject_entry: 'yfin = "yfin.__main__:app"' install: pip install yfin completion: yfin --install-completion {bash|zsh|fish|pwsh} config_file: path: ~/.yfin/config.toml purpose: >- Stores user-level defaults that are also exposed as flags: proxy, retries, locale (lang/region), cache_dir, default_format, stored Yahoo cookies (T/Y). Flags always override config. ## Global flags every subcommand accepts. ## ------------------------------------------------------------ globalOptions: - name: --format shortFlag: -f description: Output format. Default `table` when stdout is a TTY, `json` when piped. type: string enum: - table # Rich-rendered (DataFrame, dict, list) - json # pandas to_json(orient='split') / json.dumps for dict/list - ndjson # one JSON object per line; ideal for streaming output - csv # pandas to_csv (DataFrame only) - tsv # pandas to_csv(sep='\t') - parquet # pandas to_parquet (DataFrame only); needs --out - yaml # PyYAML safe_dump (dict/list only) - name: --out shortFlag: -o description: Write to PATH instead of stdout. Format is inferred from the file extension if --format is omitted. type: string - name: --pretty description: Pretty-print JSON / YAML output (indent=2). Default true for table/json on TTY, false for ndjson. type: boolean - name: --compact description: Opposite of --pretty; force single-line JSON. Useful for piping into `jq -c`. type: boolean - name: --columns description: Comma-separated list of columns to keep before rendering (DataFrame outputs only). type: string - name: --limit description: Truncate the rendered output to the first N rows / items. Renders client-side after the API call returns. type: number - name: --proxy description: HTTP/HTTPS proxy URL. Forwarded to `yf.config.network.proxy` for this invocation. type: string - name: --timeout description: Request timeout in seconds (float ok). Default 10. type: number - name: --retries description: Retry attempts on transient HTTP failures. Default 0. type: number - name: --lang description: 'BCP-47 language tag. Default "en-US".' type: string - name: --region description: 'ISO 3166-1 alpha-2 country code. Default "US".' type: string - name: --cache-dir description: Override the tz / cookie SQLite cache directory. type: string - name: --config description: Use a non-default ~/.yfin/config.toml path. type: string - name: --no-color description: Disable Rich color output. Auto-disabled when stdout is not a TTY. type: boolean - name: --quiet shortFlag: -q description: Suppress progress bars and warnings. type: boolean - name: --verbose shortFlag: -v description: Enable yfinance debug logging (one -v = INFO, two -vv = DEBUG). type: boolean - name: --version description: Print yfin and yfinance versions and exit. type: boolean - name: --install-completion description: Install shell completion (Typer built-in). type: string enum: - bash - zsh - fish - pwsh ## Format inference rules used by --out when --format is not given. ## ------------------------------------------------------------ outputFormats: extension_map: ".json": json ".ndjson": ndjson ".jsonl": ndjson ".csv": csv ".tsv": tsv ".parquet": parquet ".pq": parquet ".yaml": yaml ".yml": yaml table_renderers: DataFrame: rich.table.Table from pandas with column dtype hints dict: rich.table.Table (2-col key/value) or rich.tree.Tree for nested list: rich.table.Table if list of dicts; otherwise bullet list Series: rich.table.Table (index / value) NamedTuple: walks fields; calls/puts (option_chain) get a panel each ## Subcommand groups — one entry per CLI namespace. ## ------------------------------------------------------------ commandGroups: ## ticker — per-symbol queries (one symbol per call). - name: ticker description: Single-symbol queries. Symbol is the first positional argument. commands: - command: yfin ticker info SYMBOL tool: tickerInfo notes: Heavy (`quoteSummary`); use `fast-info` when you only need price. - command: yfin ticker fast-info SYMBOL tool: tickerFastInfo - command: >- yfin ticker history SYMBOL [--period 1mo|...|max] [--interval 1d|...|3mo] [--start YYYY-MM-DD] [--end YYYY-MM-DD] [--prepost] [--no-actions] [--no-auto-adjust] [--back-adjust] [--repair] [--keepna] [--rounding] tool: tickerHistory notes: Boolean flags follow Typer convention — `--prepost`/`--no-prepost`, `--auto-adjust`/`--no-auto-adjust`. Use --out aapl.parquet for round-tripping into pandas. - command: yfin ticker history-metadata SYMBOL tool: tickerHistoryMetadata - command: yfin ticker actions SYMBOL [--kind actions|dividends|splits|capital_gains] [--period max|...] tool: tickerActions - command: yfin ticker financials SYMBOL --statement income_stmt|balance_sheet|cash_flow [--freq yearly|quarterly|trailing] [--pretty-rows] [--as-dict] tool: tickerFinancials notes: '`--pretty-rows` maps to `pretty=true` (avoids clashing with the global `--pretty` JSON flag).' - command: yfin ticker valuation SYMBOL tool: tickerValuationMeasures - command: yfin ticker earnings SYMBOL [--freq yearly|quarterly] [--as-dict] tool: tickerEarnings - command: yfin ticker earnings-dates SYMBOL [--limit 12] [--offset 0] tool: tickerEarningsDates - command: yfin ticker analyst SYMBOL --kind {analyst_price_targets|earnings_estimate|revenue_estimate|earnings_history|eps_trend|eps_revisions|growth_estimates|recommendations|recommendations_summary|upgrades_downgrades} [--as-dict] tool: tickerAnalystEstimates - command: yfin ticker holders SYMBOL --kind {major_holders|institutional_holders|mutualfund_holders|insider_purchases|insider_transactions|insider_roster_holders} [--as-dict] tool: tickerHolders - command: yfin ticker calendar SYMBOL tool: tickerCalendar - command: yfin ticker news SYMBOL [--count 10] [--tab news|all|"press releases"] tool: tickerNews - command: yfin ticker sec-filings SYMBOL tool: tickerSecFilings - command: yfin ticker sustainability SYMBOL [--as-dict] tool: tickerSustainability - command: yfin ticker isin SYMBOL tool: tickerIsin - command: yfin ticker shares SYMBOL [--as-dict] tool: tickerShares - command: yfin ticker shares-full SYMBOL [--start YYYY-MM-DD] [--end YYYY-MM-DD] tool: tickerSharesFull - command: yfin ticker options SYMBOL tool: tickerOptionExpirations notes: Lists expirations only. Use `yfin ticker option-chain` for the actual chain. - command: yfin ticker option-chain SYMBOL [--date YYYY-MM-DD] [--tz America/New_York] tool: tickerOptionChain notes: Default format renders three panels — calls table, puts table, underlying dict. - command: yfin ticker funds-data SYMBOL tool: tickerFundsData - command: yfin ticker live SYMBOL [--no-verbose] [--duration N] [--format ndjson] tool: tickerLive notes: Long-running. Streams decoded protobuf as NDJSON by default; Ctrl-C to stop. ## download — quick multi-ticker history shortcut (top-level on purpose). - name: download description: Top-level shortcut for batch OHLCV downloads. Positional args = symbols. commands: - command: >- yfin download SYMBOL [SYMBOL...] [--start YYYY-MM-DD] [--end YYYY-MM-DD] [--period 1mo|...] [--interval 1d|...] [--group-by ticker|column] [--actions] [--auto-adjust/--no-auto-adjust] [--back-adjust] [--repair] [--keepna] [--prepost] [--threads/--no-threads] [--ignore-tz/--no-ignore-tz] [--rounding] [--no-progress] [--no-multi-level-index] tool: downloadHistory notes: Default output for many symbols is a directory of CSVs when --out is a path ending in '/'; otherwise a single multi-indexed CSV/Parquet. ## tickers — `Tickers` collection methods (rarely needed in CLI form). - name: tickers description: Operations on a `Tickers` collection. Mostly equivalent to `yfin download`. commands: - command: yfin tickers history SYMBOL [SYMBOL...] [shared download flags] tool: tickersHistory - command: yfin tickers news SYMBOL [SYMBOL...] tool: tickersNews ## search — symbol discovery - name: search description: Yahoo Finance keyword / company-name search. commands: - command: >- yfin search QUERY [--max-results 8] [--news-count 8] [--lists-count 8] [--include-cb/--no-include-cb] [--include-nav-links] [--include-research] [--include-cultural-assets] [--fuzzy] [--recommended 8] [--no-raise-errors] tool: searchTickers notes: '--fuzzy is the CLI alias for `enable_fuzzy_query`.' ## lookup — typed symbol lookup - name: lookup description: Fuzzy symbol lookup across asset classes. commands: - command: yfin lookup QUERY [--type all|stock|mutualfund|etf|index|future|currency|cryptocurrency] [--count 25] [--no-raise-errors] tool: lookupTickers ## market — region-level overview - name: market description: Region-level market overview / status. commands: - command: yfin market summary REGION tool: marketSummary notes: REGION is one of US, GB, ASIA, EUROPE, RATES, COMMODITIES, CURRENCIES, CRYPTOCURRENCIES. - command: yfin market status REGION tool: marketStatus notes: Yahoo silently returns US data for non-US — CLI prints a warning to stderr in that case. ## sector / industry — domain aggregates - name: sector description: Sector aggregates (top companies / ETFs / mutual funds / industries). commands: - command: yfin sector KEY [--attribute overview|top_companies|top_etfs|top_mutual_funds|industries|research_reports|name|symbol] [--region US] tool: sectorInfo - command: yfin sector list tool: sectorInfo notes: Convenience subcommand — prints the 11 valid sector keys; no Yahoo call. - name: industry description: Industry aggregates (top performing / top growth companies). commands: - command: yfin industry KEY [--attribute overview|top_companies|top_performing_companies|top_growth_companies|research_reports|sector_key|sector_name] [--region US] tool: industryInfo ## calendars — market-wide event calendars - name: calendars description: Market-wide earnings / IPO / economic events / splits calendars. commands: - command: yfin calendars earnings [--start YYYY-MM-DD] [--end YYYY-MM-DD] [--market-cap 1e10] [--no-filter-most-active] [--limit 12] [--offset 0] [--force] tool: getEarningsCalendar - command: yfin calendars ipo [--start YYYY-MM-DD] [--end YYYY-MM-DD] [--limit 12] [--offset 0] [--force] tool: getIpoInfoCalendar - command: yfin calendars economic [--start YYYY-MM-DD] [--end YYYY-MM-DD] [--limit 12] [--offset 0] [--force] tool: getEconomicEventsCalendar - command: yfin calendars splits [--start YYYY-MM-DD] [--end YYYY-MM-DD] [--limit 12] [--offset 0] [--force] tool: getSplitsCalendar ## screen — predefined + custom market screens - name: screen description: Run Yahoo Finance screens (predefined or custom QueryBase trees). commands: - command: yfin screen list-predefined [--include-bodies] tool: listPredefinedScreeners - command: yfin screen predefined NAME [--count 25] [--offset 0] [--sort-field FIELD] [--sort-asc] tool: screenMarket notes: NAME is one of the 19 keys (e.g. day_gainers, undervalued_growth_stocks). Maps to `query=NAME`. - command: yfin screen run --query QUERY [--type equity|mutualfund|etf] [--size 100] [--offset 0] [--sort-field FIELD] [--sort-asc] tool: screenMarket notes: '`--query` accepts a JSON string, `@file.json`, or `-` to read stdin. Wraps `screenMarket` with a QueryBase tree.' - command: yfin screen build --type equity|mutualfund|etf --operator OP --operands JSON tool: buildScreenerQuery notes: Emit a serialized QueryBase tree to stdout (no Yahoo call). Useful for piping into `yfin screen run --query -`. ## live — Yahoo WebSocket streaming - name: live description: Stream live ticks via Yahoo WebSocket. commands: - command: yfin live SYMBOL [SYMBOL...] [--mode sync|async] [--url URL] [--no-verbose] [--duration N] [--format ndjson] tool: streamLiveQuotes notes: Long-running. `--duration N` closes the socket after N seconds. Without `--duration`, listen until Ctrl-C. - command: yfin live subscribe SYMBOL [SYMBOL...] tool: liveSubscribe notes: Sends a `subscribe` frame to an existing socket — only meaningful inside a Python session, not as a one-shot CLI call. Provided for completeness; the daemon mode is a planned future addition. - command: yfin live unsubscribe SYMBOL [SYMBOL...] tool: liveUnsubscribe ## auth — Yahoo cookie / strategy management - name: auth description: Manage Yahoo crumb / cookie state. commands: - command: yfin auth cookies --t TOKEN --y TOKEN [--save] tool: authSetCookies notes: '`--save` persists the cookies to ~/.yfin/config.toml so future invocations reuse them automatically.' - command: yfin auth strategy STRATEGY tool: authStrategy notes: STRATEGY is `basic` or `csrf`. Persisted to config when run with `--save`. ## config — local-state helpers - name: config description: Read / write the yfin config file and the in-process yf.config. commands: - command: yfin config get [KEY] tool: getConfig notes: With no KEY, dumps the full config tree as JSON (or YAML via --format yaml). - command: yfin config set [--proxy URL] [--retries N] [--lang TAG] [--region CODE] [--hide-exceptions/--no-hide-exceptions] [--logging/--no-logging] tool: setConfig - command: yfin config debug-on tool: enableDebugMode - command: yfin config cache-dir PATH tool: setTzCacheLocation - command: yfin config clear-cache [--path PATH] tool: clearTzCache ## Notes on tools that don't get a CLI command. ## ------------------------------------------------------------ unsupported: - tool: tickersContainer reason: Returns a live Python object. Not meaningful as a one-shot CLI call. Users should use `yfin download` / `yfin tickers history` instead, which deliver the same data without holding object state. ## Quickstart examples — copy-pasteable. ## ------------------------------------------------------------ examples: - description: Apple last month, daily, written to Parquet. shell: yfin ticker history AAPL --period 1mo --interval 1d --out aapl.parquet - description: Quarterly income statement (human-labelled rows) as JSON. shell: yfin ticker financials AAPL --statement income_stmt --freq quarterly --pretty-rows --format json - description: Portfolio sweep — three stocks since 2024, grouped by ticker, to CSV. shell: yfin download AAPL MSFT NVDA --start 2024-01-01 --interval 1d --group-by ticker --out portfolio.csv - description: Top 25 day gainers right now. shell: yfin screen predefined day_gainers --count 25 - description: Custom screen — large caps with P/E < 20, sorted by market cap. shell: | yfin screen run --type equity --size 50 --sort-field intradaymarketcap --query '{ "operator":"and", "operands":[ {"operator":"gt","operands":["intradaymarketcap",1e10]}, {"operator":"lt","operands":["peratio.lasttwelvemonths",20]}, {"operator":"eq","operands":["region","us"]} ] }' - description: Stream Tesla + Apple live for 60 s as NDJSON. shell: yfin live AAPL TSLA --duration 60 --format ndjson > ticks.ndjson - description: Upcoming earnings this week, large caps only. shell: yfin calendars earnings --start 2026-06-09 --end 2026-06-16 --market-cap 1e10 - description: Set proxy + Chinese locale, then refresh Apple's info. shell: | yfin config set --proxy http://127.0.0.1:7890 --lang zh-CN yfin ticker info AAPL ## Generator hint — how to scaffold the actual Typer app from this file. ## ------------------------------------------------------------ generator: script: scripts/gen-cli.py # planned inputs: - yfinance-tools.yaml # this file (tools + cli sections) outputs: - yfin/__main__.py # Typer root app - yfin/commands/*.py # one module per commandGroup - yfin/renderers.py # --format / --out plumbing - yfin/config.py # ~/.yfin/config.toml loader - yfin/_completion.sh # Typer-generated completions rules: - "Every entry in `commandGroups[].commands` becomes a Typer @app.command." - "The `tool:` field selects the matching `tools[]` entry; its `parameters` drive Typer Option/Argument generation (enum → click.Choice, boolean → --flag/--no-flag, array → multiple)." - "`globalOptions` are attached to the root callback so every subcommand inherits them." - "Anything in `unsupported` is skipped silently." - "`--format`/`--out` dispatch is centralized in `renderers.py`; commands return the raw Python value (DataFrame/dict/list) and never print directly." ## Estimated effort for each stage. ## ------------------------------------------------------------ roadmap: - stage: MVP scope: 10 high-traffic commands (ticker info|fast-info|history|financials, download, search, screen predefined, market summary, calendars earnings, config set) effort: ~half a day - stage: Full scope: All 49 tools wired, table + json + csv + parquet renderers, Rich panels for option_chain. effort: 2-3 days - stage: Polish scope: yaml-driven code generation, shell completion, ~/.yfin/config.toml, persistent auth cookies, pyproject packaging + PyPI publish. effort: ~1 additional day # ============================================================================ # Output schemas — what each tool actually returns (sampled live, 2026-06-08) # ---------------------------------------------------------------------------- # Captured by running the `yfin` CLI against live Yahoo from a residential exit # node. Each entry records: returnType (Python), structure (fields/columns), # notes (gotchas), and a live `sample` (truncated). These supplement the # `tools[].description` field with concrete shape information that callers # can rely on when post-processing JSON output. # ============================================================================ outputSchemas: tickerFastInfo: returnType: FastInfo (dict-like) structure: keys: - {key: currency, type: string, example: "USD"} - {key: dayHigh, type: float, example: 315.17} - {key: dayLow, type: float, example: 307.15} - {key: exchange, type: string, example: "NMS"} - {key: fiftyDayAverage, type: float, example: 281.24} - {key: lastPrice, type: float, example: 307.34} - {key: lastVolume, type: int, example: 65246700} - {key: marketCap, type: float, example: 4.514e12} - {key: open, type: float} - {key: previousClose, type: float} - {key: quoteType, type: string, example: "EQUITY"} - {key: regularMarketPreviousClose, type: float} - {key: shares, type: int, example: 14687356000} - {key: tenDayAverageVolume, type: int} - {key: threeMonthAverageVolume, type: int} - {key: timezone, type: string, example: "America/New_York"} - {key: twoHundredDayAverage, type: float} - {key: yearChange, type: float, example: 0.5256} - {key: yearHigh, type: float} - {key: yearLow, type: float} notes: 20 keys total; all flat scalars. JSON output is a plain dict (not pandas split-orient). tickerHistory: returnType: pd.DataFrame structure: index: {name: Date, type: tz-aware DatetimeIndex} columns: - {name: Open, type: float} - {name: High, type: float} - {name: Low, type: float} - {name: Close, type: float} - {name: Volume, type: int} - {name: Dividends, type: float, note: zero on non-event rows} - {name: Stock Splits, type: float, note: zero on non-event rows} - {name: Capital Gains, type: float, note: only present for fund-like symbols} - {name: "Repaired?", type: bool, note: only present when --repair is set} json_shape: "orient=split → {columns, index (ISO timestamps), data}" sample_csv: | Date,Open,High,Low,Close,Volume,Dividends,Stock Splits 2026-06-01 00:00:00-04:00,309.63,310.94,305.02,306.31,48849900,0.0,0.0 2026-06-02 00:00:00-04:00,307.46,315.45,306.69,315.20,44534700,0.0,0.0 notes: | Index timestamps are tz-aware exchange local time. With --repair an extra bool column 'Repaired?' is appended. tickerActions: returnType: pd.Series (or DataFrame when kind=actions) structure: Series: index: tz-aware DatetimeIndex (event timestamps) values: float (e.g. 0.26 dollars/share for AAPL dividends) DataFrame (kind=actions): columns: [Dividends, Stock Splits] json_shape: | Series → orient=split → {name, index, data}. The `data` array is a flat list of floats (NOT list-of-lists). sample: | 8 dividends in 2y for AAPL: 2024-08-12: $0.25 2024-11-08: $0.25 2025-02-10: $0.25 2025-05-12: $0.26 2025-08-11: $0.26 2025-11-10: $0.26 tickerFinancials: returnType: pd.DataFrame structure: columns: ISO period-end timestamps (most recent first) rows: 33+ line items (camelCase by default; human labels when pretty=true) sample_columns: ["2026-03-31", "2025-12-31", "2025-09-30", "2025-06-30"] sample_pretty_rows: - "Tax Effect Of Unusual Items" - "Tax Rate For Calcs" - "Normalized EBITDA" - "Net Income From Continuing Operation Net Minority Interest" - "Reconciled Depreciation" notes: | Quarterly returns latest 4-5 periods; yearly returns latest 4-5 fiscal years. Trailing (TTM) only valid for income_stmt and cash_flow. tickerEarningsDates: returnType: pd.DataFrame structure: index: {name: "Earnings Date", type: ISO datetime (UTC)} columns: - {name: "EPS Estimate", type: float, nullable: true} - {name: "Reported EPS", type: float, nullable: true, note: null for upcoming dates} - {name: "Surprise(%)", type: float, nullable: true, note: null for upcoming dates} sample: - {date: "2026-07-29T20:00:00Z", estimate: 4.24, reported: null, surprise: null} - {date: "2026-04-29T20:00:00Z", estimate: 4.06, reported: 4.27, surprise: 5.22} - {date: "2026-01-28T21:00:00Z", estimate: 3.92, reported: 4.14, surprise: 5.69} notes: First row(s) are future estimates; surprise is null until reported. tickerAnalystEstimates: returnType: varies by --kind variants: analyst_price_targets: type: dict sample: {current: 307.34, high: 400.0, low: 215.0, mean: 310.507, median: 310.0} recommendations: type: pd.DataFrame columns: [period, strongBuy, buy, hold, sell, strongSell] sample_row: ["0m", 7, 23, 15, 1, 2] earnings_estimate: type: pd.DataFrame columns: [numberOfAnalysts, avg, low, high, yearAgoEps, growth] index: ["0q", "+1q", "0y", "+1y"] eps_trend: type: pd.DataFrame columns: [current, "7daysAgo", "30daysAgo", "60daysAgo", "90daysAgo"] growth_estimates: type: pd.DataFrame columns: [stockTrend, indexTrend] tickerHolders: returnType: pd.DataFrame variants: institutional_holders: columns: ["Date Reported", Holder, pctHeld, Shares, Value, pctChange] sample_row: - "2026-03-31" - "Blackrock Inc." - 0.0779 - 1144695425 - 351810687727 - -0.0086 major_holders: columns: [Value] index: [insidersPercentHeld, institutionsPercentHeld, institutionsFloatPercentHeld, institutionsCount] insider_transactions: columns: [Insider, Position, "Transaction Type", Shares, Value, "URL", "Start Date", "Ownership"] tickerCalendar: returnType: dict structure: Dividend Date: ISO date (string) Ex-Dividend Date: ISO date (string) Earnings Date: list[ISO date] Earnings High: float Earnings Low: float Earnings Average: float Revenue High: int Revenue Low: int Revenue Average: int sample: Dividend Date: "2026-05-14" Ex-Dividend Date: "2026-05-11" Earnings Date: ["2026-07-31"] Earnings High: 1.99 Earnings Low: 1.83 Earnings Average: 1.89541 tickerNews: returnType: list[dict] structure: item: id: string (uuid) content: id: string contentType: 'STORY | PRESS_RELEASE | ...' title: string summary: string pubDate: ISO datetime provider: {displayName: string, url: string} thumbnail: {originalUrl, resolutions: list} canonicalUrl: {url, lang, region} clickThroughUrl: {url} sample: - title: "Apple WWDC preview: Apple gets a second shot at its AI rollout" provider: "Yahoo Finance" - title: "Broadcom, AMD, Super Micro, and More Stocks That Explain Today's Market" provider: "Barrons.com" tickerSecFilings: returnType: list[dict] structure: item: date: ISO date type: '10-K | 10-Q | 8-K | SD | DEF 14A | ...' title: string (human description) edgarUrl: string exhibits: list[dict] sample: - {date: "2026-05-28", type: "SD", title: "Specialized Disclosure Report..."} - {date: "2026-05-01", type: "10-Q", title: "Periodic Financial Reports"} - {date: "2026-04-30", type: "8-K", title: "Corporate Changes & Voting Matters"} notes: ~77 filings returned for AAPL (full Yahoo-tracked history). tickerIsin: returnType: dict structure: symbol: string isin: string # "-" if unresolvable (e.g. crypto, indices) sample: {symbol: "AAPL", isin: "US0378331005"} tickerShares: returnType: pd.DataFrame status: UPSTREAM_UNIMPLEMENTED notes: | Raises `YFNotImplementedError('shares')` as of yfinance 1.4.1. Use `tickerSharesFull` for the daily shares-outstanding series. tickerSharesFull: returnType: pd.Series structure: index: tz-aware DatetimeIndex (daily) values: int (shares outstanding) sample: - ["2024-12-27T05:00:00Z", 15115799552] - ["2024-12-28T05:00:00Z", 15115799552] - ["2025-01-04T05:00:00Z", 15115799552] notes: Default window = last 548 days (~18 months). ~80 datapoints in default window. tickerOptionExpirations: returnType: list[string] structure: ISO dates ("YYYY-MM-DD"), ascending. sample: ["2026-06-08", "2026-06-10", "2026-06-12", "2026-06-15", "2026-06-17"] tickerOptionChain: returnType: NamedTuple(calls, puts, underlying) structure: calls: pd.DataFrame puts: pd.DataFrame underlying: dict (quote snapshot) DataFrame_columns: - contractSymbol - lastTradeDate (datetime) - strike (float) - lastPrice (float) - bid (float) - ask (float) - change (float) - percentChange (float) - volume (int) - openInterest (int) - impliedVolatility (float) - inTheMoney (bool) - contractSize (string, "REGULAR") - currency (string) notes: | JSON serialization wraps the NamedTuple as a dict {calls, puts, underlying}. Table render emits three Rich panels (calls / puts / underlying). downloadHistory: returnType: pd.DataFrame (MultiIndex columns) structure: group_by=column (default): columns: MultiIndex(level0=field, level1=symbol) levels: - level0: [Open, High, Low, Close, Volume, Dividends, Stock Splits] - level1: list of symbols group_by=ticker: columns: MultiIndex(level0=symbol, level1=field) sample_json_columns: | [["Close", "AAPL"], ["Close", "MSFT"], ["Close", "NVDA"], ["Dividends", "AAPL"], ["Dividends", "MSFT"], ["Dividends", "NVDA"], ...] sample_csv_header: | Price,Close,Close,High,High,Low,Low,Open,Open,Volume,Volume Ticker,AAPL,MSFT,AAPL,MSFT,AAPL,MSFT,AAPL,MSFT,AAPL,MSFT Date,,,,,,,,,, notes: | For 5-day × 3-symbol AAPL/MSFT/NVDA: 5 rows × 15 cols (5 fields × 3 symbols). Parquet write is round-trippable via pandas.read_parquet. searchTickers: returnType: dict (Search.all) structure: quotes: list[dict] news: list[dict] lists: list[dict] research: list[dict] nav: list[dict] quote_item: symbol: string shortname: string longname: string exchange: string (e.g. "NMS", "NYQ", "GER") exchDisp: string (e.g. "NASDAQ", "NYSE") quoteType: 'EQUITY | ETF | INDEX | ...' typeDisp: string sector: string sectorDisp: string industry: string industryDisp: string score: float isYahooFinance: bool sample_top_hit: symbol: AAPL shortname: "Apple Inc." exchange: NMS sector: Technology industry: Consumer Electronics score: 23212.0 lookupTickers: returnType: pd.DataFrame structure: index: symbol (string) columns: [exchange, sectorLink, sector, quoteType, score, regularMarketChange, regularMarketChangePercent, regularMarketPrice, shortName] sample_top_hit: symbol: AAPL data: [NMS, "https://finance.yahoo.com/sector/technology", Technology, equity, 23212, -3.89, -1.2499, 307.34, "Apple Inc."] marketSummary: returnType: dict (keyed by exchange code) structure: key: exchange code (e.g. CME, CBT, CXI, CMX) value: shortName: string (e.g. "Russell 2000 Futures", "VIX", "Gold") regularMarketPrice: float regularMarketChange: float regularMarketChangePercent: float exchange: string exchangeTimezoneName: string marketState: string sample: CME: {shortName: "Russell 2000 Futures", regularMarketPrice: 2874.7, regularMarketChangePercent: 1.4075} CBT: {shortName: "Dow Futures", regularMarketPrice: 51099.0, regularMarketChangePercent: 0.32} CXI: {shortName: VIX, regularMarketPrice: 18.99, regularMarketChangePercent: -11.72} CMX: {shortName: Gold, regularMarketPrice: 4355.7, regularMarketChangePercent: -0.22} notes: | US region returned 4 entries (futures + VIX + gold) at sampling time. regularMarketPrice is a flat float (NOT a {raw, fmt, longFmt} dict — old assumption). marketStatus: returnType: dict structure: id: string ("us") name: string ("U.S. markets") status: 'open | closed | premarket | postmarket' yfit_market_id: string close: ISO datetime (UTC) open: ISO datetime (UTC) duration: list[{hrs, mins}] message: human string tz: timezone object (when present) sample: id: us name: U.S. markets status: closed open: "2026-06-08T13:30:00+00:00" close: "2026-06-08T20:00:00+00:00" message: "U.S. markets open in 1 hour 42 minutes" notes: | Yahoo silently returns US data for non-US regions; the scraper logs a warning and yields null in that case. sectorInfo: returnType: dict (when --attribute omitted) or scalar (when set) full_dict_keys: [key, name, symbol, overview, top_companies, top_etfs, top_mutual_funds, industries, research_reports] sub_shapes: overview: dict (market_weight, market_cap, message_board_id, employee_count, sector_key, parent_name, parent_key, description) top_companies: type: pd.DataFrame index: symbol columns: [name, rating, "market weight"] sample_top: NVDA: ["NVIDIA Corporation", "Strong Buy", 0.491] AAPL: ["Apple Inc.", "Strong Buy", ...] MSFT: ["Microsoft Corporation", "Strong Buy", ...] top_etfs: type: dict sample: {SMH: "VanEck Semiconductor ETF", XLK: "Technology Select Sector SPDR Fund"} top_mutual_funds: type: dict industries: type: pd.DataFrame index: industry slug columns: [name, symbol, "market weight"] sample_top: semiconductors: ["Semiconductors", "^YH31130020", 0.388] software-infrastructure: ["Software - Infrastructure", "^YH31110030", 0.197] industryInfo: returnType: dict (when --attribute omitted) full_dict_keys: [key, name, symbol, sector_key, sector_name, overview, top_companies, top_performing_companies, top_growth_companies, research_reports] sub_shapes: top_companies: type: pd.DataFrame index: symbol columns: [name, rating, "market weight"] sample_top_for_semiconductors: NVDA: ["NVIDIA Corporation", "Strong Buy", 0.49185] AVGO: ["Broadcom Inc.", "Strong Buy", 0.17970] MU: ["Micron Technology, Inc.", "Strong Buy", 0.07497] top_performing_companies: type: pd.DataFrame columns: [name, "ytd return", "last price", "target price"] top_growth_companies: type: pd.DataFrame columns: [name, "ytd return", "growth estimate"] getEarningsCalendar: returnType: pd.DataFrame structure: index: row number (0-based) columns: [Symbol, Company, "Event Name", Timing, EPS Estimate, Reported EPS, "Surprise(%)", Marketcap, "Event Start Date"] sample: - {Symbol: ORCL, Company: "Oracle Corporation", "Event Name": "Q4 2026 Earnings Announcement", Timing: AMC, "EPS Estimate": 1.96, Marketcap: 5.41e11} - {Symbol: UEC, Company: "Uranium Energy Corp.", "Event Name": "Q3 2026 Earnings Announcement", Timing: BMO, "EPS Estimate": -0.01, Marketcap: 6.25e9} notes: Sorted by Event Start Date descending. screenMarket: returnType: dict (Yahoo "finance.result[0]") structure: id: string title: string description: string canonicalName: string criteriaMeta: dict rawCriteria: string start: int count: int total: int (total matches, can exceed `count`) useRecords: bool quotes: list[dict] quote_item: symbol: string shortName: string regularMarketPrice: float regularMarketChangePercent: float regularMarketChange: float marketCap: float ellipsis: '... (~60 fields total)' sample_predefined_day_gainers: total: 74 top_5: - {symbol: COO, shortName: "The Cooper Companies, Inc.", regularMarketPrice: 67.34, regularMarketChangePercent: 8.578} - {symbol: ABM, shortName: "ABM Industries Incorporated", regularMarketPrice: 42.54, regularMarketChangePercent: 6.670} - {symbol: ARCB, shortName: "ArcBest Corporation", regularMarketPrice: 155.09, regularMarketChangePercent: 6.168} listPredefinedScreeners: returnType: list[string] count: 19 members: - aggressive_small_caps - bond_etfs - conservative_foreign_funds - day_gainers - day_losers - growth_technology_stocks - high_yield_bond - most_actives - most_shorted_stocks - portfolio_anchors - small_cap_gainers - solid_large_growth_funds - solid_midcap_growth_funds - technology_etfs - top_etfs_us - top_mutual_funds - top_performing_etfs - undervalued_growth_stocks - undervalued_large_caps buildScreenerQuery: returnType: dict structure: type: 'equity | mutualfund | etf' query: operator: 'AND | OR | EQ | GT | LT | GTE | LTE | BTWN | IS-IN' operands: list (nested queries or [field, value]) sample: type: equity query: operator: AND operands: - {operator: GT, operands: ["intradaymarketcap", 10000000000.0]} - {operator: EQ, operands: ["region", "us"]} streamLiveQuotes: returnType: stream of dict (one per protobuf message) structure: id: symbol price: float time: int (ms epoch) exchange: string quoteType: int (Yahoo enum) marketHours: int changePercent: float dayVolume: int change: float lastSize: int priceHint: int notes: Decoded from yfinance/pricing.proto. CLI writes one JSON object per line to stdout (or --out). # ============================================================================ # Learnings — captured during yfin CLI implementation (2026-06-08) # ---------------------------------------------------------------------------- # Things that bit us, things that turned out NOT to be true, things to # remember when extending or regenerating the CLI. Each entry has: # topic — short slug # summary — one-line takeaway # detail — the full story # appliesTo — what this affects # ============================================================================ learnings: - topic: rate-limit-is-ip-not-cli summary: Yahoo's 403/429 on query1/query2 is an IP-level block, not a CLI/yfinance bug. detail: | During testing both AWS Singapore (52.221.x) and macOS Tailscale exit nodes returned HTTP 429 to every query1/query2 API path even from raw curl with a browser User-Agent. The same IP got HTTP 200 on the finance.yahoo.com html site. Conclusion: Yahoo Finance API gates by IP reputation, separately from the consumer site. Residential / mobile IPs almost always work; datacenter IPs almost always don't. yfinance's cookie+crumb dance does NOT bypass this — it's an L7 IP block. appliesTo: All openWorldHint=true tools. remediation: | Surface YFRateLimitError as a friendly stderr message + exit code 2 (not a Rich traceback). Recommend --proxy URL or switching exit nodes. - topic: crumb-handshake-works-when-ip-isnt-blocked summary: yfinance's basic-strategy crumb handshake transparently fixes 429 when the IP is OK. detail: | Once we switched to a residential exit node, the very first `yfin ticker fast-info MSFT` call triggered _get_crumb_basic() → got cookie + crumb → response code=200 → returned full FastInfo dict. We did NOT need authSetCookies / authStrategy / any retry logic. The basic strategy is sufficient unless you hit a EU consent wall. appliesTo: authStrategy, authSetCookies remediation: | Don't ship retry logic; let yfinance handle the handshake. Surface auth errors only when basic→csrf fallback also fails. - topic: lxml-and-scipy-are-not-truly-optional summary: yfinance documents `lxml/html5lib/scipy/requests_cache/requests_ratelimiter` as optional but several core tools NEED them. detail: | - tickerEarningsDates raises ImportError("Import lxml failed") because the scraper uses pandas.read_html under the hood. - tickerHistory with --repair raises ImportError unless scipy is present. - The `nospam` extras (requests_cache/requests_ratelimiter) are needed if users want their own caching session (we document that in CLI). appliesTo: tickerEarningsDates, tickerHistory (--repair), nospam users remediation: | The yfin pyproject.toml lists lxml, html5lib, scipy, requests_cache, requests_ratelimiter as direct deps so `uv tool install` always works. - topic: typer-callback-vs-subcommand-conflict summary: invoke_without_command=True swallows the positional that would otherwise route to a subcommand. detail: | Initial design had `yfin sector KEY [--attribute X]` as a callback AND `yfin sector list` as a subcommand. Running `yfin sector list` ran the callback with key="list" (NOT the list subcommand) and queried Yahoo for sector "list". Same trap hit search/lookup/live. appliesTo: sector, search, lookup, live remediation: | Drop invoke_without_command=True. Make the default action an explicit subcommand: `yfin sector info KEY`, `yfin search run QUERY`, `yfin lookup run QUERY`, `yfin live stream SYMBOL ...`. - topic: screen-build-needs-recursive-wrapping summary: EquityQuery/FundQuery/ETFQuery 'and'/'or' operators require nested QueryBase instances, not raw dicts. detail: | _validate_or_and_operand() in yfinance/screener/query.py enforces `all(isinstance(e, QueryBase) for e in operand)`. Passing raw dicts raises TypeError. The CLI's `screen build` must recurse to wrap each operand in the same query class before constructing the parent. appliesTo: buildScreenerQuery remediation: | In yfin/commands/screen.py::build, recurse via _build_query() and only fall through to raw operands for leaf value operators (eq/gt/lt/gte/lte/btwn/is-in). - topic: market-summary-field-shape-changed summary: regularMarketPrice in marketSummary is a flat float, NOT a {raw, fmt, longFmt} dict. detail: | Old yfinance behavior wrapped numeric fields in {raw, fmt, longFmt}. Current Yahoo response returns flat floats. Anything that tries `v.get('regularMarketPrice', {}).get('raw')` will crash with AttributeError: 'float' object has no attribute 'get'. appliesTo: marketSummary, screenMarket (some fields) remediation: | Treat numeric quote fields as raw floats. Defensive: check isinstance(v, dict). - topic: actions-series-not-list-of-lists summary: ticker actions --kind dividends returns a Series, whose JSON `data` is a flat list of floats. detail: | Initial test assumed `data[i][0]` (list-of-lists). pandas Series orient=split produces `{name, index, data}` where data is 1-D. DataFrame orient=split produces 2-D `data`. Type matters. appliesTo: tickerActions (dividends/splits/capital_gains), tickerSharesFull remediation: | Renderer dispatch in yfin/renderers.py already distinguishes DataFrame vs Series. Downstream consumers must match. - topic: ticker-shares-is-not-implemented summary: yfinance 1.4.1 stubs `Ticker.get_shares()` — raises YFNotImplementedError. detail: | `yfin ticker shares AAPL` raises YFNotImplementedError('shares') from yfinance/scrapers/fundamentals.py. Documented in yfinance/scrapers/ fundamentals.py:39 — the property is a placeholder for a yet-to-be written scraper. appliesTo: tickerShares remediation: | Use `tickerSharesFull` instead. CLI surfaces the upstream error as-is; don't mask it. - topic: ticker-options-empty-on-non-options-symbols summary: tickerOptionExpirations returns [] for crypto, FX, indices. detail: | Yahoo's options endpoint returns {} for symbols without listed options. The CLI's Tuple/list serializer handles empty correctly; downstream code should expect a possibly-empty list. appliesTo: tickerOptionExpirations, tickerOptionChain - topic: typer-period-enum-strictness summary: --period only accepts the 11 Yahoo periods. "3d" / "7d" / numeric strings get rejected at CLI level. detail: | First test sweep tried `--period 3d` and got `Invalid value for '--period': '3d' is not one of '1d', '5d', '1mo', '3mo', '6mo', '1y', '2y', '5y', '10y', 'ytd', 'max'.` from Typer. This is correct behavior — `5d` is the smallest > 1d period. appliesTo: tickerHistory, downloadHistory, tickersHistory, tickerActions remediation: | For arbitrary day counts, pass --start/--end instead of --period. Documented in `globalOptions` notes and per-command help text. - topic: requires-python-must-be-3.10-not-3.9 summary: yfinance 1.4.1 transitively requires curl_cffi>=0.15, which dropped Python 3.9. detail: | uv sync failed with: "Because curl-cffi==0.15.0 depends on Python>=3.10 and yfinance==1.4.1 depends on curl-cffi>=0.15, … your project's requirements are unsatisfiable." Even though setup.py for yfinance lists 3.6+, the actual runtime floor is 3.10. appliesTo: yfin/pyproject.toml requires-python remediation: | Pin `requires-python = ">=3.10"` in yfin/pyproject.toml. - topic: console-script-needs-wrapper-for-error-shaping summary: Typer's `app` callable can't catch its own SystemExit cleanly. Use a wrapper main(). detail: | Putting `try: app() except YFRateLimitError` directly under `if __name__ == "__main__":` only fires when run via `python -m yfin`. When uv installs the console script (`yfin = yfin.__main__:app`), the script imports `app` and calls it directly — bypassing the guard. appliesTo: yfin/__main__.py remediation: | Export `main()` that wraps `app()` in try/except, and change the entry point to `yfin = "yfin.__main__:main"`. - topic: pretty-rows-vs-global-pretty summary: Two `--pretty` flags would collide; use `--pretty-rows` for the per-financials flag. detail: | The global `--pretty` flag controls JSON/YAML formatting. The yfinance `pretty=` kwarg on get_income_stmt translates row labels. Both are useful and orthogonal. Naming them differently avoids ambiguity. appliesTo: tickerFinancials (CLI) remediation: | CLI exposes `--pretty-rows` (maps to yfinance pretty=true), keeps global `--pretty` for JSON formatting. - topic: global-flags-must-come-before-subcommand summary: Typer parses global options on the root callback ONLY before the subcommand name. detail: | `yfin ticker fast-info AAPL --format json` → fails with "No such option: --format" because Typer attaches --format to the root app, not the leaf command. Correct: `yfin --format json ticker fast-info AAPL`. appliesTo: All globalOptions remediation: | Document the ordering in README + --help. Could be relaxed by duplicating global flags onto every subcommand, but that bloats help. - topic: search-needs-class-instantiation-side-effect summary: yf.Search runs the HTTP call inside __init__, so the CLI cannot lazy-build a "Search builder". detail: | The Search class fetches data eagerly when constructed. There is no `.execute()` step. Implication: every flag that affects the query (max_results, news_count, fuzzy, etc.) must be passed as constructor args. Mirrored 1:1 in `yfin search run`. appliesTo: searchTickers - topic: tickers-history-multi-index-csv-is-pivoted-twice summary: download() returns a DataFrame with MultiIndex columns; to_csv writes a 3-row header. detail: | The CSV header is: Price,Close,Close,High,High,… then Ticker,AAPL,MSFT,AAPL,MSFT,… then Date,,,, Tools that consume the CSV must skip those 3 header rows or use `pd.read_csv(..., header=[0,1])` and index_col=0. appliesTo: downloadHistory, tickersHistory remediation: | For naive downstream consumers, set `--group-by ticker` and write to Parquet for round-trippable round-trips (pyarrow preserves the MultiIndex). - topic: residential-ip-rate-limit-tldr summary: 17/17 live tests passed once on a residential IP exit; flaky on first attempt because of Yahoo cold-start. detail: | Pattern observed: first request after switching exit nodes may still return 429 (Yahoo's edge cache hasn't propagated the new IP's rep score). Wait ~10s and retry; subsequent requests reliably succeed. appliesTo: any first-request-after-IP-change scenario remediation: | `yfin --retries N` is already plumbed through to yf.config.network.retries. Could add an automatic --retry-on-429 flag with exponential backoff. - topic: tickers-history-progress-corrupts-stdout summary: download()'s progress bar writes to stdout; mixed with JSON output it breaks json.load(). detail: | Initial tests failed JSON parse because the progress bar bytes preceded the JSON body. Adding --no-progress fixes it. Quiet mode (`-q`) auto-disables progress. appliesTo: downloadHistory, tickersHistory remediation: | In yfin/_shared.py, force progress=False when stdout is a pipe (auto). User can re-enable with `--progress`. - topic: cli-binary-stats summary: Final yfin implementation = 1857 LOC across 18 Python files; 51 subcommands wrapping 49 tools. detail: | Tally as of 2026-06-08: ticker.py 371 LOC, 22 commands renderers.py 321 LOC __main__.py 166 LOC screen.py 132 LOC live.py 105 LOC config.py(cmd) 105 LOC config.py(mod) 98 LOC calendars.py 85 LOC sector.py 71 LOC download.py 70 LOC _shared.py 66 LOC tickers.py 53 LOC industry.py 50 LOC auth.py 48 LOC search.py 44 LOC market.py 36 LOC lookup.py 32 LOC Global install: ~/.local/share/uv/tools/yfin/, symlinked to ~/.local/bin/yfin.