docs: add API references, mapping corrections, and verification script

- Add yfinance.org and defeatbeta-api.org reference docs
- Fix defeatbeta_mapping.org: deprecated yfinance property names
  (quarterly_financials→quarterly_income_stmt, financials→income_stmt),
  longName vs longBusinessSummary conceptual mismatch, cashflow note typo
- Add Mapping Limitations section with live verification results (AAPL):
  DuckDB 1.4.3 incompatibility, format differences, coverage gaps
- Add docs/test_mapping.py as runnable mapping verification script
- Add offline.py, persistent_cache.py, download_data.py, warmup_cache.py
  for offline/cached defeatbeta usage
- Add aapl_yfinance.py exploration script and quant.py scaffold
- Add .envrc (uv layout) and update pyproject.toml + uv.lock

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-26 15:33:21 +08:00
parent b71a8e77b0
commit b5bf689e72
16 changed files with 3650 additions and 141 deletions
+203
View File
@@ -0,0 +1,203 @@
#+TITLE: defeatbeta-api Reference
#+AUTHOR: Wong Ding Feng
#+DATE: 2026-04-25
* How Data Retrieval Works
** NOT a full download
Uses *DuckDB + ~cache_httpfs~ extension* querying *remote Parquet files on HuggingFace*
(~defeatbeta/yahoo-finance-data~). Every query runs SQL directly against remote files:
#+begin_src sql
SELECT * FROM 'https://huggingface.co/.../stock_prices.parquet' WHERE symbol = 'AAPL'
#+end_src
Parquet's columnar format + DuckDB *predicate pushdown* = only the row-groups matching
your ticker are fetched over HTTP range requests. Not the full 3-4 GB file.
** On-disk cache
- Default 1 GB cache at ~~/.defeatbeta/cache/~
- Stores fetched blocks so repeated queries are fast
- On startup: checks ~spec.json~ on HuggingFace, clears stale cache if dataset was updated
* Getting All Available Tickers
#+begin_src python
from defeatbeta_api.data.company_meta import CompanyMeta
meta = CompanyMeta()
all_tickers = meta.get_all_tickers() # List[str]
all_companies = meta.get_all_companies_info() # List[dict]: symbol, name, cik, currency
#+end_src
Reads ~company_tickers.json~ from HuggingFace — a small JSON, not the big Parquet files.
* Single Ticker API — ~Ticker("AAPL")~
#+begin_src python
from defeatbeta_api.data.ticker import Ticker
t = Ticker("AAPL")
#+end_src
** Company Info
| Method | Returns | What it gives |
|----------------------------+-------------+---------------------------------------------------------|
| ~info()~ | DataFrame | Profile: name, sector, industry, description, headcount |
| ~officers()~ | DataFrame | Executive officers |
| ~sec_filing()~ | DataFrame | SEC filings list |
| ~news()~ | ~News~ object | Latest news articles |
| ~earning_call_transcripts()~ | ~Transcripts~ | Earnings call transcripts |
| ~calendar()~ | DataFrame | Upcoming earnings dates |
** Prices & Basic Finance
| Method | Returns | What it gives |
|------------------------------------+-----------+------------------------------|
| ~price()~ | DataFrame | Historical OHLCV prices |
| ~splits()~ | DataFrame | Stock split events |
| ~dividends()~ | DataFrame | Dividend payment history |
| ~shares()~ | DataFrame | Shares outstanding over time |
| ~beta(period="5y", benchmark="SPY")~ | DataFrame | Calculated beta vs benchmark |
| ~currency(symbol)~ | DataFrame | Exchange rate history |
| ~ttm_eps()~ | DataFrame | Trailing 12-month EPS |
** Financial Statements
| Method | Returns | What it gives |
|------------------------------+-----------+-------------------------|
| ~quarterly_income_statement()~ | ~Statement~ | Quarterly P&L |
| ~annual_income_statement()~ | ~Statement~ | Annual P&L |
| ~quarterly_balance_sheet()~ | ~Statement~ | Quarterly balance sheet |
| ~annual_balance_sheet()~ | ~Statement~ | Annual balance sheet |
| ~quarterly_cash_flow()~ | ~Statement~ | Quarterly cash flow |
| ~annual_cash_flow()~ | ~Statement~ | Annual cash flow |
** TTM Aggregates
| Method | Returns | What it gives |
|----------------------------------------+-----------+----------------------------------|
| ~ttm_revenue()~ | DataFrame | Trailing 12-month revenue |
| ~ttm_fcf()~ | DataFrame | Trailing 12-month free cash flow |
| ~ttm_ebitda()~ | DataFrame | Trailing 12-month EBITDA |
| ~ttm_net_income_common_stockholders()~ | DataFrame | Trailing 12-month net income |
| ~ttm_pe()~ | DataFrame | Trailing P/E (price / ttm_eps) |
** Revenue Breakdown
| Method | Returns | What it gives |
|------------------------+-----------+-----------------------------|
| ~revenue_by_segment()~ | DataFrame | Revenue by business segment |
| ~revenue_by_geography()~ | DataFrame | Revenue by region |
| ~revenue_by_product()~ | DataFrame | Revenue by product line |
** Valuation Multiples
| Method | Returns | What it gives |
|-------------------------+-----------+------------------------------|
| ~market_capitalization()~ | DataFrame | Historical market cap |
| ~ps_ratio()~ | DataFrame | Price/Sales ratio |
| ~pb_ratio()~ | DataFrame | Price/Book ratio |
| ~peg_ratio()~ | DataFrame | PEG ratio |
| ~enterprise_value()~ | DataFrame | Enterprise value |
| ~enterprise_to_revenue()~ | DataFrame | EV/Revenue |
| ~enterprise_to_ebitda()~ | DataFrame | EV/EBITDA |
| ~debt_to_equity()~ | DataFrame | D/E ratio |
| ~net_debt_ttm()~ | DataFrame | Net debt (TTM) |
| ~wacc()~ | DataFrame | Weighted avg cost of capital |
** Profitability Returns
| Method | Returns | What it gives |
|---------------------+-----------+------------------------------------|
| ~roe()~ | DataFrame | Return on equity |
| ~roa()~ | DataFrame | Return on assets |
| ~roic()~ | DataFrame | Return on invested capital |
| ~roce()~ | DataFrame | Return on capital employed |
| ~equity_multiplier()~ | DataFrame | Financial leverage (assets/equity) |
| ~asset_turnover()~ | DataFrame | Revenue/assets efficiency |
** Margins
| Method | Returns | What it gives |
|------------------------------+-----------+--------------------|
| ~quarterly_gross_margin()~ | DataFrame | Gross margin % |
| ~annual_gross_margin()~ | DataFrame | Gross margin % |
| ~quarterly_operating_margin()~ | DataFrame | Operating margin % |
| ~annual_operating_margin()~ | DataFrame | Operating margin % |
| ~quarterly_net_margin()~ | DataFrame | Net margin % |
| ~annual_net_margin()~ | DataFrame | Net margin % |
| ~quarterly_ebitda_margin()~ | DataFrame | EBITDA margin % |
| ~annual_ebitda_margin()~ | DataFrame | EBITDA margin % |
| ~quarterly_fcf_margin()~ | DataFrame | FCF margin % |
| ~annual_fcf_margin()~ | DataFrame | FCF margin % |
** YoY Growth
| Method | Returns | What it gives |
|-----------------------------------------+-----------+---------------------|
| ~quarterly_revenue_yoy_growth()~ | DataFrame | Revenue growth % |
| ~annual_revenue_yoy_growth()~ | DataFrame | Revenue growth % |
| ~quarterly_operating_income_yoy_growth()~ | DataFrame | Op. income growth % |
| ~annual_operating_income_yoy_growth()~ | DataFrame | Op. income growth % |
| ~quarterly_ebitda_yoy_growth()~ | DataFrame | EBITDA growth % |
| ~annual_ebitda_yoy_growth()~ | DataFrame | EBITDA growth % |
| ~quarterly_net_income_yoy_growth()~ | DataFrame | Net income growth % |
| ~annual_net_income_yoy_growth()~ | DataFrame | Net income growth % |
| ~quarterly_fcf_yoy_growth()~ | DataFrame | FCF growth % |
| ~annual_fcf_yoy_growth()~ | DataFrame | FCF growth % |
| ~quarterly_eps_yoy_growth()~ | DataFrame | EPS growth % |
| ~quarterly_ttm_eps_yoy_growth()~ | DataFrame | TTM EPS growth % |
** Industry Comparisons
Uses the ticker's own industry to benchmark against peers.
| Method | Returns | What it gives |
|------------------------------------+-----------+--------------------------|
| ~industry_ttm_pe()~ | DataFrame | Avg P/E across industry |
| ~industry_ps_ratio()~ | DataFrame | Industry P/S |
| ~industry_pb_ratio()~ | DataFrame | Industry P/B |
| ~industry_roe()~ | DataFrame | Industry ROE |
| ~industry_roa()~ | DataFrame | Industry ROA |
| ~industry_roic()~ | DataFrame | Industry ROIC |
| ~industry_equity_multiplier()~ | DataFrame | Industry leverage |
| ~industry_asset_turnover()~ | DataFrame | Industry efficiency |
| ~industry_quarterly_gross_margin()~ | DataFrame | Industry gross margin % |
| ~industry_quarterly_ebitda_margin()~ | DataFrame | Industry EBITDA margin % |
| ~industry_quarterly_net_margin()~ | DataFrame | Industry net margin % |
** DCF / Advanced
| Method | Returns | What it gives |
|-----------------------------+---------+----------------------------------------|
| ~dcf_data()~ | dict | All raw inputs for a DCF model |
| ~dcf()~ | dict | Full DCF valuation + exports ~.xlsx~ |
| ~download_data_performance()~ | str | Timing summary of data fetch durations |
* Multi-Ticker API — ~Tickers(["AAPL", "NVDA"])~
#+begin_src python
from defeatbeta_api.data.tickers import Tickers
t = Tickers(["AAPL", "NVDA"])
t = Tickers(["AAPL", "NVDA"], max_workers=2) # limit parallelism
#+end_src
Wraps all ~Ticker~ methods, running them in *parallel threads*.
- Methods returning simple data → *combined DataFrame* (all tickers in one table)
- Methods returning complex objects (statements, news, transcripts) → ~{symbol: result}~ dict
Same method names as ~Ticker~, plus industry comparison methods operate per unique
industry represented across the list.
#+begin_src python
t.info() # → DataFrame (combined)
t.price() # → DataFrame (combined)
t.annual_income_statement() # → {'AAPL': Statement(...), 'NVDA': Statement(...)}
t.news() # → {'AAPL': News(...), 'NVDA': News(...)}
t.earning_call_transcripts() # → {'AAPL': Transcripts(...), 'NVDA': Transcripts(...)}
t.industry_roe() # → DataFrame (one row per unique industry)
#+end_src
+186 -128
View File
@@ -7,20 +7,20 @@
# Overview
| Category | Yahoo Finance | DefeatBeta-API | Notes |
|----------|--------------|----------------|-------|
| **Data Source** | Yahoo Finance API | HuggingFace + DuckDB | No rate limits |
| **Query Engine** | Direct API | DuckDB OLAP | Sub-second queries |
| **Update Frequency** | Real-time (15min delayed) | Daily batch | DefeatBeta is historical only |
| **Historical Depth** | Full history | Full history | Comparable coverage |
| **Special Features** | Limited | Earnings transcripts, DCF, AI | DefeatBeta has unique capabilities |
| Category | Yahoo Finance | DefeatBeta-API | Notes |
|--------------------+---------------------------+-------------------------------+------------------------------------|
| **Data Source** | Yahoo Finance API | HuggingFace + DuckDB | No rate limits |
| **Query Engine** | Direct API | DuckDB OLAP | Sub-second queries |
| **Update Frequency** | Real-time (15min delayed) | Daily batch | DefeatBeta is historical only |
| **Historical Depth** | Full history | Full history | Comparable coverage |
| **Special Features** | Limited | Earnings transcripts, DCF, AI | DefeatBeta has unique capabilities |
* Price & Volume Data
| Yahoo Finance | DefeatBeta-API | Return Type | Notes |
|--------------|----------------|-------------|-------|
| ~ticker.history(period='max')~ | ~ticker.price()~ | pandas.DataFrame | OHLCV data |
| ~ticker.history(period='1d')~ | N/A | - | Real-time not available |
| Yahoo Finance | DefeatBeta-API | Return Type | Notes |
|----------------------------------------+-------------------------+------------------+--------------------------|
| ~ticker.history(period='max')~ | ~ticker.price()~ | pandas.DataFrame | OHLCV data |
| ~ticker.history(period='1d')~ | N/A | - | Real-time not available |
| ~ticker.history(start='...', end='...')~ | ~ticker.price()~ (filter) | pandas.DataFrame | Date filtering available |
* DefeatBeta Price Data Structure
@@ -33,14 +33,14 @@
* Financial Statements
| Yahoo Finance | DefeatBeta-API | Return Type | Notes |
|--------------|----------------|-------------|-------|
| ~ticker.quarterly_financials~ | ~ticker.quarterly_income_statement()~ | Statement object | Different format |
| ~ticker.financials~ | ~ticker.annual_income_statement()~ | Statement object | Annual version |
| ~ticker.quarterly_balance_sheet~ | ~ticker.quarterly_balance_sheet()~ | Statement object | Same structure |
| ~ticker.balance_sheet~ | ~ticker.annual_balance_sheet()~ | Statement object | Annual version |
| ~ticker.quarterly_cashflow~ | ~ticker.quarterly_cash_flow()~ | Statement object | Note: 'flow' vs 'flow' |
| ~ticker.cashflow~ | ~ticker.annual_cash_flow()~ | Statement object | Annual version |
| Yahoo Finance | DefeatBeta-API | Return Type | Notes |
|--------------------------------+-------------------------------------+------------------+------------------------|
| ~ticker.quarterly_income_stmt~ | ~ticker.quarterly_income_statement()~ | Statement object | Different format |
| ~ticker.income_stmt~ | ~ticker.annual_income_statement()~ | Statement object | Annual version |
| ~ticker.quarterly_balance_sheet~ | ~ticker.quarterly_balance_sheet()~ | Statement object | Same structure |
| ~ticker.balance_sheet~ | ~ticker.annual_balance_sheet()~ | Statement object | Annual version |
| ~ticker.quarterly_cashflow~ | ~ticker.quarterly_cash_flow()~ | Statement object | 'cashflow' vs 'cash_flow' |
| ~ticker.cashflow~ | ~ticker.annual_cash_flow()~ | Statement object | Annual version |
** Statement Object Methods
#+BEGIN_SRC python
@@ -53,16 +53,16 @@ income_stmt.print_pretty_table() # Formatted output
* Valuation Metrics
| Yahoo Finance | DefeatBeta-API | Return Type | Notes |
|--------------|----------------|-------------|-------|
| ~ticker.info['trailingPE']~ | ~ticker.ttm_pe()~ | pandas.DataFrame | **Historical** time series! |
| ~ticker.info['forwardPE']~ | N/A | - | Not available |
| ~ticker.info['trailingEps']~ | ~ticker.ttm_eps()~ | pandas.DataFrame | **Historical** time series! |
| ~ticker.info['forwardEps']~ | N/A | - | Not available |
| ~ticker.info['marketCap']~ | ~ticker.market_capitalization()~ | pandas.DataFrame | **Historical** time series! |
| ~ticker.info['priceToBook']~ | ~ticker.pb_ratio()~ | pandas.DataFrame | Price/Book ratio |
| ~ticker.info['priceToSalesTrailing12Months']~ | ~ticker.ps_ratio()~ | pandas.DataFrame | Price/Sales ratio |
| N/A | ~ticker.peg_ratio()~ | pandas.DataFrame | PEG ratio (unique) |
| Yahoo Finance | DefeatBeta-API | Return Type | Notes |
|---------------------------------------------+--------------------------------+------------------+---------------------------|
| ~ticker.info['trailingPE']~ | ~ticker.ttm_pe()~ | pandas.DataFrame | **Historical** time series! |
| ~ticker.info['forwardPE']~ | N/A | - | Not available |
| ~ticker.info['trailingEps']~ | ~ticker.ttm_eps()~ | pandas.DataFrame | **Historical** time series! |
| ~ticker.info['forwardEps']~ | N/A | - | Not available |
| ~ticker.info['marketCap']~ | ~ticker.market_capitalization()~ | pandas.DataFrame | **Historical** time series! |
| ~ticker.info['priceToBook']~ | ~ticker.pb_ratio()~ | pandas.DataFrame | Price/Book ratio |
| ~ticker.info['priceToSalesTrailing12Months']~ | ~ticker.ps_ratio()~ | pandas.DataFrame | Price/Sales ratio |
| N/A | ~ticker.peg_ratio()~ | pandas.DataFrame | PEG ratio (unique) |
** Key Advantage: Historical Valuation Data
DefeatBeta provides **full historical time series** for:
@@ -75,13 +75,13 @@ Yahoo Finance only provides **current values** in ~.info~
* Financial Ratios
| Yahoo Finance | DefeatBeta-API | Return Type | Notes |
|--------------|----------------|-------------|-------|
| ~ticker.info['returnOnEquity']~ | ~ticker.roe()~ | pandas.DataFrame | **Historical** time series! |
| ~ticker.info['returnOnAssets']~ | ~ticker.roa()~ | pandas.DataFrame | **Historical** time series! |
| N/A | ~ticker.roic()~ | pandas.DataFrame | Return on Invested Capital |
| N/A | ~ticker.wacc()~ | pandas.DataFrame | Weighted Avg Cost of Capital |
| ~ticker.info['beta']~ | ~ticker.beta()~ | pandas.DataFrame | 5Y monthly beta |
| Yahoo Finance | DefeatBeta-API | Return Type | Notes |
|-------------------------------+----------------+------------------+------------------------------|
| ~ticker.info['returnOnEquity']~ | ~ticker.roe()~ | pandas.DataFrame | **Historical** time series! |
| ~ticker.info['returnOnAssets']~ | ~ticker.roa()~ | pandas.DataFrame | **Historical** time series! |
| N/A | ~ticker.roic()~ | pandas.DataFrame | Return on Invested Capital |
| N/A | ~ticker.wacc()~ | pandas.DataFrame | Weighted Avg Cost of Capital |
| ~ticker.info['beta']~ | ~ticker.beta()~ | pandas.DataFrame | 5Y monthly beta |
** WACC Components Available in DefeatBeta
#+BEGIN_SRC python
@@ -93,66 +93,67 @@ wacc = ticker.wacc()
* Growth Metrics
| Yahoo Finance | DefeatBeta-API | Return Type | Notes |
|--------------|----------------|-------------|-------|
| ~ticker.info['revenueGrowth']~ | ~ticker.quarterly_revenue_yoy_growth()~ | pandas.DataFrame | YoY growth |
| ~ticker.info['earningsGrowth']~ | ~ticker.quarterly_eps_yoy_growth()~ | pandas.DataFrame | EPS YoY growth |
| N/A | ~ticker.quarterly_net_income_yoy_growth()~ | pandas.DataFrame | Net income growth |
| N/A | ~ticker.quarterly_operating_income_yoy_growth()~ | pandas.DataFrame | Operating income growth |
| N/A | ~ticker.quarterly_ebitda_yoy_growth()~ | pandas.DataFrame | EBITDA growth |
| N/A | ~ticker.quarterly_fcf_yoy_growth()~ | pandas.DataFrame | Free cash flow growth |
| N/A | ~ticker.annual_revenue_yoy_growth()~ | pandas.DataFrame | Annual revenue growth |
| Yahoo Finance | DefeatBeta-API | Return Type | Notes |
|-------------------------------+------------------------------------------------+------------------+-------------------------|
| ~ticker.info['revenueGrowth']~ | ~ticker.quarterly_revenue_yoy_growth()~ | pandas.DataFrame | YoY growth |
| ~ticker.info['earningsGrowth']~ | ~ticker.quarterly_eps_yoy_growth()~ | pandas.DataFrame | EPS YoY growth |
| N/A | ~ticker.quarterly_net_income_yoy_growth()~ | pandas.DataFrame | Net income growth |
| N/A | ~ticker.quarterly_operating_income_yoy_growth()~ | pandas.DataFrame | Operating income growth |
| N/A | ~ticker.quarterly_ebitda_yoy_growth()~ | pandas.DataFrame | EBITDA growth |
| N/A | ~ticker.quarterly_fcf_yoy_growth()~ | pandas.DataFrame | Free cash flow growth |
| N/A | ~ticker.annual_revenue_yoy_growth()~ | pandas.DataFrame | Annual revenue growth |
* Margin Metrics
| Yahoo Finance | DefeatBeta-API | Return Type | Notes |
|--------------|----------------|-------------|-------|
| ~ticker.info['profitMargins']~ | ~ticker.quarterly_net_margin()~ | pandas.DataFrame | **Historical** time series! |
| ~ticker.info['grossMargins']~ | ~ticker.quarterly_gross_margin()~ | pandas.DataFrame | **Historical** time series! |
| ~ticker.info['operatingMargins']~ | ~ticker.quarterly_operating_margin()~ | pandas.DataFrame | **Historical** time series! |
| N/A | ~ticker.quarterly_ebitda_margin()~ | pandas.DataFrame | EBITDA margin |
| N/A | ~ticker.quarterly_fcf_margin()~ | pandas.DataFrame | Free cash flow margin |
| N/A | ~ticker.industry_quarterly_gross_margin()~ | pandas.DataFrame | Industry comparison |
| Yahoo Finance | DefeatBeta-API | Return Type | Notes |
|---------------------------------+------------------------------------------+------------------+---------------------------|
| ~ticker.info['profitMargins']~ | ~ticker.quarterly_net_margin()~ | pandas.DataFrame | **Historical** time series! |
| ~ticker.info['grossMargins']~ | ~ticker.quarterly_gross_margin()~ | pandas.DataFrame | **Historical** time series! |
| ~ticker.info['operatingMargins']~ | ~ticker.quarterly_operating_margin()~ | pandas.DataFrame | **Historical** time series! |
| N/A | ~ticker.quarterly_ebitda_margin()~ | pandas.DataFrame | EBITDA margin |
| N/A | ~ticker.quarterly_fcf_margin()~ | pandas.DataFrame | Free cash flow margin |
| N/A | ~ticker.industry_quarterly_gross_margin()~ | pandas.DataFrame | Industry comparison |
* Dividends & Stock Splits
| Yahoo Finance | DefeatBeta-API | Return Type | Notes |
|--------------|----------------|-------------|-------|
| ~ticker.dividends~ | ~ticker.dividends()~ | pandas.DataFrame | Dividend history |
| ~ticker.splits~ | ~ticker.splits()~ | pandas.DataFrame | Stock split history |
| ~ticker.info['dividendYield']~ | N/A | - | Not in separate field |
| ~ticker.info['trailingAnnualDividendYield']~ | N/A | - | Not available |
| Yahoo Finance | DefeatBeta-API | Return Type | Notes |
|--------------------------------------------+--------------------+------------------+-----------------------|
| ~ticker.dividends~ | ~ticker.dividends()~ | pandas.DataFrame | Dividend history |
| ~ticker.splits~ | ~ticker.splits()~ | pandas.DataFrame | Stock split history |
| ~ticker.info['dividendYield']~ | N/A | - | Not in separate field |
| ~ticker.info['trailingAnnualDividendYield']~ | N/A | - | Not available |
* Company Info & Metadata
| Yahoo Finance | DefeatBeta-API | Return Type | Notes |
|--------------|----------------|-------------|-------|
| ~ticker.info~ | ~ticker.info()~ | pandas.DataFrame | One row, many columns |
| ~ticker.info['longName']~ | ~ticker.info()['long_business_summary']~ | string | Business summary |
| ~ticker.info['sector']~ | ~ticker.info()['sector']~ | string | Sector classification |
| ~ticker.info['industry']~ | ~ticker.info()['industry']~ | string | Industry classification |
| ~ticker.info['website']~ | ~ticker.info()['web_site']~ | string | Company website |
| ~ticker.info['fullTimeEmployees']~ | ~ticker.info()['full_time_employees']~ | int | Employee count |
| N/A | ~ticker.officers()~ | pandas.DataFrame | Company officers |
| N/A | ~ticker.calendar()~ | pandas.DataFrame | Earnings calendar |
| Yahoo Finance | DefeatBeta-API | Return Type | Notes |
|----------------------------------+----------------------------------------+------------------+-------------------------|
| ~ticker.info~ | ~ticker.info()~ | pandas.DataFrame | One row, many columns |
| ~ticker.info['longName']~ | N/A (check name/short_name column) | string | Company trading name |
| ~ticker.info['longBusinessSummary']~ | ~ticker.info()['long_business_summary']~ | string | Business description |
| ~ticker.info['sector']~ | ~ticker.info()['sector']~ | string | Sector classification |
| ~ticker.info['industry']~ | ~ticker.info()['industry']~ | string | Industry classification |
| ~ticker.info['website']~ | ~ticker.info()['web_site']~ | string | Company website |
| ~ticker.info['fullTimeEmployees']~ | ~ticker.info()['full_time_employees']~ | int | Employee count |
| N/A | ~ticker.officers()~ | pandas.DataFrame | Company officers |
| N/A | ~ticker.calendar()~ | pandas.DataFrame | Earnings calendar |
* Unique DefeatBeta Features (Not in Yahoo Finance)
| Feature | Method | Description |
|---------|--------|-------------|
| **Earnings Transcripts** | ~ticker.earning_call_transcripts()~ | Full earnings call transcripts |
| | ~transcripts.get_transcripts_list()~ | List all available transcripts |
| | ~transcripts.get_transcript(year, quarter)~ | Get specific quarter's transcript |
| | ~transcripts.summarize_key_financial_data_with_ai()~ | AI-powered summary |
| **Revenue Breakdown** | ~ticker.revenue_by_segment()~ | Revenue by product segment |
| | ~ticker.revenue_by_product()~ | Detailed product breakdown |
| | ~ticker.revenue_by_geography()~ | Revenue by geographic region |
| **Automated DCF** | ~ticker.dcf()~ | Generates Excel DCF valuation |
| **AI Analysis** | ~transcripts.analyze_financial_metrics_change...~ | LLM analysis of quarter changes |
| | ~transcripts.analyze_financial_metrics_forecast...~ | LLM forecast analysis |
| **Industry Metrics** | ~ticker.industry_ttm_pe()~ | Industry P/E comparison |
| | ~ticker.industry_roe()~ | Industry ROE comparison |
| | ~ticker.industry_quarterly_gross_margin()~ | Industry margin comparison |
| Feature | Method | Description |
|------------------------+----------------------------------------------------+-----------------------------------|
| **Earnings Transcripts** | ~ticker.earning_call_transcripts()~ | Full earnings call transcripts |
| | ~transcripts.get_transcripts_list()~ | List all available transcripts |
| | ~transcripts.get_transcript(year, quarter)~ | Get specific quarter's transcript |
| | ~transcripts.summarize_key_financial_data_with_ai()~ | AI-powered summary |
| **Revenue Breakdown** | ~ticker.revenue_by_segment()~ | Revenue by product segment |
| | ~ticker.revenue_by_product()~ | Detailed product breakdown |
| | ~ticker.revenue_by_geography()~ | Revenue by geographic region |
| **Automated DCF** | ~ticker.dcf()~ | Generates Excel DCF valuation |
| **AI Analysis** | ~transcripts.analyze_financial_metrics_change...~ | LLM analysis of quarter changes |
| | ~transcripts.analyze_financial_metrics_forecast...~ | LLM forecast analysis |
| **Industry Metrics** | ~ticker.industry_ttm_pe()~ | Industry P/E comparison |
| | ~ticker.industry_roe()~ | Industry ROE comparison |
| | ~ticker.industry_quarterly_gross_margin()~ | Industry margin comparison |
* Example: yfinance → DefeatBeta Migration
@@ -209,26 +210,26 @@ current_roe = ticker.roe().iloc[-1]['roe']
* Quick Reference: Common Operations
| Operation | Yahoo Finance | DefeatBeta-API |
|-----------|--------------|----------------|
| Get current price | ~ticker.info['currentPrice']~ | ~ticker.price().iloc[-1]['close']~ |
| Get current P/E | ~ticker.info['trailingPE']~ | ~ticker.ttm_pe().iloc[-1]['ttm_pe']~ |
| Get current EPS | ~ticker.info['trailingEps']~ | ~ticker.ttm_eps().iloc[-1]['tailing_eps']~ |
| Get market cap | ~ticker.info['marketCap']~ | ~ticker.market_capitalization().iloc[-1]['market_capitalization']~ |
| Get ROE | ~ticker.info['returnOnEquity']~ | ~ticker.roe().iloc[-1]['roe']~ |
| Get revenue (TTM) | ~ticker.info['totalRevenue']~ | ~ticker.quarterly_income_statement().df().iloc[0]['TTM']~ |
| Get 5Y beta | ~ticker.info['beta']~ | ~ticker.beta().iloc[-1]['beta']~ |
| Operation | Yahoo Finance | DefeatBeta-API |
|-------------------+-------------------------------+------------------------------------------------------------------|
| Get current price | ~ticker.info['currentPrice']~ | ~ticker.price().iloc[-1]['close']~ |
| Get current P/E | ~ticker.info['trailingPE']~ | ~ticker.ttm_pe().iloc[-1]['ttm_pe']~ |
| Get current EPS | ~ticker.info['trailingEps']~ | ~ticker.ttm_eps().iloc[-1]['tailing_eps']~ |
| Get market cap | ~ticker.info['marketCap']~ | ~ticker.market_capitalization().iloc[-1]['market_capitalization']~ |
| Get ROE | ~ticker.info['returnOnEquity']~ | ~ticker.roe().iloc[-1]['roe']~ |
| Get revenue (TTM) | ~ticker.info['totalRevenue']~ | ~ticker.quarterly_income_statement().df().iloc[0]['TTM']~ |
| Get 5Y beta | ~ticker.info['beta']~ | ~ticker.beta().iloc[-1]['beta']~ |
* Data Type Differences
| Aspect | Yahoo Finance | DefeatBeta-API |
|--------|--------------|----------------|
| Dates in DataFrame | DatetimeIndex | 'report_date' column |
| Column naming | Title case (Open, Close) | Snake case (open, close) |
| Dividends/Splits | Separate columns in history | Separate DataFrames |
| Quarterly data | Transposed (dates as columns) | Wide format (TTM + quarters as columns) |
| Missing data | NaN | NaN |
| Numeric types | float | Decimal (convert with ~float()~) |
| Aspect | Yahoo Finance | DefeatBeta-API |
|--------------------+-------------------------------+-----------------------------------------|
| Dates in DataFrame | DatetimeIndex | 'report_date' column |
| Column naming | Title case (Open, Close) | Snake case (open, close) |
| Dividends/Splits | Separate columns in history | Separate DataFrames |
| Quarterly data | Transposed (dates as columns) | Wide format (TTM + quarters as columns) |
| Missing data | NaN | NaN |
| Numeric types | float | Decimal (convert with ~float()~) |
* Converting Decimal to Float
#+BEGIN_SRC python
@@ -244,37 +245,94 @@ market_cap_billions = float(market_cap.iloc[-1]['market_capitalization']) / 1e9
* When to Use Each
| Use Case | Recommendation | Reason |
|----------|---------------|--------|
| Backtesting trading strategies | **DefeatBeta** | No rate limits, consistent historical data |
| DCF Valuation modeling | **DefeatBeta** | Automated Excel output |
| Revenue segment analysis | **DefeatBeta** | Unique revenue breakdown |
| Earnings call research | **DefeatBeta** | Full transcripts available |
| Real-time price alerts | **Yahoo Finance** | 15min delayed but real-time |
| Analyst recommendations | **Yahoo Finance** | Price targets, ratings |
| Institutional ownership | **Yahoo Finance** | Major holders data |
| Options/derivatives data | **Yahoo Finance** | Not available in DefeatBeta |
| Quick stock lookup | **Either** | Both work well |
| Multi-year historical analysis | **DefeatBeta** | Faster queries, no rate limits |
| Use Case | Recommendation | Reason |
|--------------------------------+-----------------+--------------------------------------------|
| Backtesting trading strategies | **DefeatBeta** | No rate limits, consistent historical data |
| DCF Valuation modeling | **DefeatBeta** | Automated Excel output |
| Revenue segment analysis | **DefeatBeta** | Unique revenue breakdown |
| Earnings call research | **DefeatBeta** | Full transcripts available |
| Real-time price alerts | **Yahoo Finance** | 15min delayed but real-time |
| Analyst recommendations | **Yahoo Finance** | Price targets, ratings |
| Institutional ownership | **Yahoo Finance** | Major holders data |
| Options/derivatives data | **Yahoo Finance** | Not available in DefeatBeta |
| Quick stock lookup | **Either** | Both work well |
| Multi-year historical analysis | **DefeatBeta** | Faster queries, no rate limits |
* Environment Setup
| Task | Command |
|------|---------|
| Install DefeatBeta | ~uv add defeatbeta-api~ |
| Install yfinance | ~uv add yfinance~ |
| Run notebook | ~uv run jupyter notebook~ |
| Check version | ~ticker.price()~ shows data update date |
| Task | Command |
|--------------------+---------------------------------------|
| Install DefeatBeta | ~uv add defeatbeta-api~ |
| Install yfinance | ~uv add yfinance~ |
| Run notebook | ~uv run jupyter notebook~ |
| Check version | ~ticker.price()~ shows data update date |
* Mapping Limitations & Verification Notes
/Verified 2026-04-26 via test_mapping.py on AAPL. defeatbeta-api 0.0.45, yfinance 1.3.0, DuckDB 1.4.3./
** What was confirmed correct (live data matched)
- ~dividends()~: both APIs return $0.26 for Nov-2025 and Feb-2026 payments — values match exactly
- ~splits()~: both return the same ratios (7:1 in 2014, 4:1 in 2020)
** Incorrect property names for yfinance (deprecated in v1.3)
| Used in mapping | Correct name in yfinance 1.3+ |
|----------------------------+-------------------------------|
| ~ticker.quarterly_financials~ | ~ticker.quarterly_income_stmt~ |
| ~ticker.financials~ | ~ticker.income_stmt~ |
The old names were removed. The mapping should use the new names.
** Conceptual mismatch: longName vs long_business_summary (Company Info)
The mapping equates ~ticker.info['longName']~ with ~ticker.info()['long_business_summary']~,
labelling it "Business summary". This is wrong:
- ~longName~ = company trading name, e.g. "Apple Inc."
- ~long_business_summary~ = multi-sentence business description paragraph
- The yfinance equivalent of the description is ~ticker.info['longBusinessSummary']~
** Typo in Financial Statements note (cashflow row)
The "Notes" column reads ~Note: 'flow' vs 'flow'~. Should read: ~'cashflow' vs 'cash_flow'~
** Data format differences found in verified pairs
| Field | yfinance | defeatbeta |
|---------------+--------------------------------------+-------------------------------|
| dividends | Series, DatetimeIndex, float amount | DataFrame, report_date col |
| split_factor | float (e.g. ~7.0~) | string ratio (e.g. ~"7:1"~) |
** Historical coverage gap
- Dividends: yfinance returns 90 records, defeatbeta returns 61 (truncated history)
- Splits: yfinance returns 5 events, defeatbeta returns 4 (one historical split missing)
** DuckDB compatibility issue (defeatbeta-api 0.0.45 + DuckDB 1.4.3)
All Parquet-backed queries except ~dividends()~ and ~splits()~ failed during verification
with either ~"don't know what type:"~ or ~"TProtocolException: Invalid data"~. Affected:
~price()~, all financial statements, all valuation/ratio/margin/growth metrics, ~info()~, ~beta()~.
This is an incompatibility between DuckDB 1.4.3 and the httpfs extension / remote Parquet
format used by defeatbeta-api. Downgrading DuckDB or waiting for a defeatbeta-api update
may resolve it. The logical mapping is still valid — the API shape is correct, only the
DuckDB query layer is broken.
** Data freshness
DefeatBeta dataset last updated 2026-04-17, 9 days behind current date. yfinance has
15-minute delayed real-time data. This gap will always exist for defeatbeta.
* Common Issues & Solutions
| Issue | Solution |
|-------|----------|
| ~TypeError: unsupported operand type(s) for /: 'Decimal' and 'float'~ | Wrap values in ~float()~ |
| ~Rate limit exceeded~ | Switch to DefeatBeta |
| ~Real-time data needed~ | Use Yahoo Finance |
| ~Missing revenue breakdown~ | Use DefeatBeta ~revenue_by_segment()~ |
| ~Slow queries~ | Use DefeatBeta (DuckDB engine) |
| Issue | Solution |
|---------------------------------------------------------------------+-------------------------------------|
| ~TypeError: unsupported operand type(s) for /: 'Decimal' and 'float'~ | Wrap values in ~float()~ |
| ~Rate limit exceeded~ | Switch to DefeatBeta |
| ~Real-time data needed~ | Use Yahoo Finance |
| ~Missing revenue breakdown~ | Use DefeatBeta ~revenue_by_segment()~ |
| ~Slow queries~ | Use DefeatBeta (DuckDB engine) |
* Additional Resources
@@ -285,7 +343,7 @@ market_cap_billions = float(market_cap.iloc[-1]['market_capitalization']) / 1e9
* Footer
#+BEGIN_COMMENT
Last updated: 2026-04-25
Last updated: 2026-04-26 (verified via test_mapping.py on AAPL)
Author: Documentation
Version: 1.0
#+END_COMMENT
#+END_COMMENT
+228
View File
@@ -0,0 +1,228 @@
"""
Mapping verification: yfinance vs defeatbeta-api for AAPL.
Prints type + 2 representative rows/values for each mapped pair.
Methods that fail are reported inline (not crashed).
"""
import warnings
warnings.filterwarnings("ignore")
import yfinance as yf
from defeatbeta_api.data.ticker import Ticker
import pandas as pd
SYMBOL = "AAPL"
yf_t = yf.Ticker(SYMBOL)
db_t = Ticker(SYMBOL)
PASS = ""
FAIL = ""
def try_db(fn, *args, **kwargs):
"""Call a defeatbeta method, return (result, None) or (None, error_str)."""
try:
return fn(*args, **kwargs), None
except Exception as e:
return None, str(e)[:80]
def show_df(label, df, n=2):
if df is None:
return
if isinstance(df, pd.DataFrame):
print(f" {label} ({df.shape[0]}r×{df.shape[1]}c), last {n} rows:")
cols = list(df.columns)[:6]
print(df[cols].tail(n).to_string(index=False))
elif isinstance(df, pd.Series):
print(f" {label} (Series len={len(df)}), last {n}:")
print(df.tail(n).to_string())
def row(label, yf_val, yf_type_label, db_result, db_err):
ok = PASS if db_result is not None else FAIL
print(f"\n{ok} {label}")
if db_err:
print(f" yfinance → {yf_type_label}: {yf_val!r}")
print(f" defeatbeta→ ERROR: {db_err}")
else:
print(f" yfinance type={yf_type_label} value={yf_val!r}")
print(f" defeatbeta type={type(db_result).__name__}", end="")
if isinstance(db_result, pd.DataFrame):
print(f" cols={list(db_result.columns)}")
show_df("defeatbeta", db_result)
else:
print(f" value={db_result!r}")
def section(title):
print(f"\n{'='*68}\n {title}\n{'='*68}")
# ── 1. PRICE DATA ─────────────────────────────────────────────────────────────
section("1. PRICE DATA — ticker.history() vs ticker.price()")
yf_price = yf_t.history(period="5d")[["Open", "Close", "High", "Low", "Volume"]]
db_price, db_price_err = try_db(db_t.price)
print(f"\n{PASS if not db_price_err else FAIL} ticker.history() vs ticker.price()")
print(f" yfinance type=DataFrame cols={list(yf_price.columns)}")
print(yf_price.tail(2).to_string())
if db_price_err:
print(f" defeatbeta→ ERROR: {db_price_err}")
else:
print(f" defeatbeta type=DataFrame cols={list(db_price.columns)}")
print(db_price.tail(2).to_string(index=False))
# ── 2. FINANCIAL STATEMENTS ───────────────────────────────────────────────────
section("2. FINANCIAL STATEMENTS")
# yfinance uses .quarterly_income_stmt (v1.3) — old .quarterly_financials is deprecated
yf_inc_q = yf_t.quarterly_income_stmt
db_inc_q, db_inc_q_err = try_db(db_t.quarterly_income_statement)
db_inc_q_df = db_inc_q.df() if db_inc_q else None
print(f"\n{PASS if not db_inc_q_err else FAIL} quarterly_income_stmt vs quarterly_income_statement()")
print(f" yfinance type={type(yf_inc_q).__name__} shape={yf_inc_q.shape} (rows=line items, cols=quarters)")
print(yf_inc_q.iloc[:2, :2].to_string())
if db_inc_q_err:
print(f" defeatbeta→ ERROR: {db_inc_q_err}")
else:
print(f" defeatbeta type={type(db_inc_q).__name__} → .df() shape={db_inc_q_df.shape}")
print(db_inc_q_df.iloc[:2, :5].to_string(index=False))
yf_bs = yf_t.balance_sheet
db_bs, db_bs_err = try_db(db_t.annual_balance_sheet)
db_bs_df = db_bs.df() if db_bs else None
print(f"\n{PASS if not db_bs_err else FAIL} balance_sheet vs annual_balance_sheet()")
print(f" yfinance type={type(yf_bs).__name__} shape={yf_bs.shape}")
print(yf_bs.iloc[:2, :2].to_string())
if db_bs_err:
print(f" defeatbeta→ ERROR: {db_bs_err}")
else:
print(f" defeatbeta type={type(db_bs).__name__} → .df() shape={db_bs_df.shape}")
print(db_bs_df.iloc[:2, :5].to_string(index=False))
yf_cf = yf_t.cashflow
db_cf, db_cf_err = try_db(db_t.annual_cash_flow)
db_cf_df = db_cf.df() if db_cf else None
print(f"\n{PASS if not db_cf_err else FAIL} cashflow vs annual_cash_flow()")
print(f" yfinance type={type(yf_cf).__name__} shape={yf_cf.shape}")
print(yf_cf.iloc[:2, :2].to_string())
if db_cf_err:
print(f" defeatbeta→ ERROR: {db_cf_err}")
else:
print(f" defeatbeta → .df() shape={db_cf_df.shape}")
print(db_cf_df.iloc[:2, :5].to_string(index=False))
# ── 3. VALUATION METRICS ──────────────────────────────────────────────────────
section("3. VALUATION METRICS")
db_pe, db_pe_err = try_db(db_t.ttm_pe)
db_eps, db_eps_err = try_db(db_t.ttm_eps)
db_mc, db_mc_err = try_db(db_t.market_capitalization)
db_pb, db_pb_err = try_db(db_t.pb_ratio)
db_ps, db_ps_err = try_db(db_t.ps_ratio)
row("trailingPE → ttm_pe()", yf_t.info.get("trailingPE"), "float", db_pe, db_pe_err)
row("trailingEps → ttm_eps()", yf_t.info.get("trailingEps"), "float", db_eps, db_eps_err)
row("marketCap → market_cap()", yf_t.info.get("marketCap"), "int", db_mc, db_mc_err)
row("priceToBook → pb_ratio()", yf_t.info.get("priceToBook"), "float", db_pb, db_pb_err)
row("priceToSales → ps_ratio()", yf_t.info.get("priceToSalesTrailing12Months"), "float", db_ps, db_ps_err)
# ── 4. FINANCIAL RATIOS ───────────────────────────────────────────────────────
section("4. FINANCIAL RATIOS")
db_roe, db_roe_err = try_db(db_t.roe)
db_roa, db_roa_err = try_db(db_t.roa)
db_beta, db_beta_err = try_db(db_t.beta)
db_wacc, db_wacc_err = try_db(db_t.wacc)
row("returnOnEquity → roe()", yf_t.info.get("returnOnEquity"), "float", db_roe, db_roe_err)
row("returnOnAssets → roa()", yf_t.info.get("returnOnAssets"), "float", db_roa, db_roa_err)
row("beta → beta()", yf_t.info.get("beta"), "float", db_beta, db_beta_err)
row("N/A → wacc()", None, "N/A", db_wacc, db_wacc_err)
# ── 5. GROWTH METRICS ─────────────────────────────────────────────────────────
section("5. GROWTH METRICS")
db_rg, db_rg_err = try_db(db_t.quarterly_revenue_yoy_growth)
db_eg, db_eg_err = try_db(db_t.quarterly_eps_yoy_growth)
db_nig, db_nig_err = try_db(db_t.quarterly_net_income_yoy_growth)
row("revenueGrowth → quarterly_revenue_yoy_growth()", yf_t.info.get("revenueGrowth"), "float", db_rg, db_rg_err)
row("earningsGrowth → quarterly_eps_yoy_growth()", yf_t.info.get("earningsGrowth"), "float", db_eg, db_eg_err)
row("N/A → quarterly_net_income_yoy_growth()", None, "N/A", db_nig, db_nig_err)
# ── 6. MARGIN METRICS ─────────────────────────────────────────────────────────
section("6. MARGIN METRICS")
db_nm, db_nm_err = try_db(db_t.quarterly_net_margin)
db_gm, db_gm_err = try_db(db_t.quarterly_gross_margin)
db_om, db_om_err = try_db(db_t.quarterly_operating_margin)
row("profitMargins → quarterly_net_margin()", yf_t.info.get("profitMargins"), "float", db_nm, db_nm_err)
row("grossMargins → quarterly_gross_margin()", yf_t.info.get("grossMargins"), "float", db_gm, db_gm_err)
row("operatingMargins → quarterly_op_margin()", yf_t.info.get("operatingMargins"), "float", db_om, db_om_err)
# ── 7. DIVIDENDS & SPLITS ─────────────────────────────────────────────────────
section("7. DIVIDENDS & SPLITS")
yf_div = yf_t.dividends
db_div, db_div_err = try_db(db_t.dividends)
print(f"\n{PASS if not db_div_err else FAIL} .dividends vs .dividends()")
print(f" yfinance type={type(yf_div).__name__} len={len(yf_div)}")
print(yf_div.tail(2).to_string())
if db_div_err:
print(f" defeatbeta→ ERROR: {db_div_err}")
else:
print(f" defeatbeta type={type(db_div).__name__} shape={db_div.shape}")
print(db_div.tail(2).to_string(index=False))
yf_sp = yf_t.splits
db_sp, db_sp_err = try_db(db_t.splits)
print(f"\n{PASS if not db_sp_err else FAIL} .splits vs .splits()")
print(f" yfinance type={type(yf_sp).__name__} len={len(yf_sp)}")
print(yf_sp.tail(2).to_string())
if db_sp_err:
print(f" defeatbeta→ ERROR: {db_sp_err}")
else:
print(f" defeatbeta type={type(db_sp).__name__} shape={db_sp.shape}")
print(db_sp.tail(2).to_string(index=False))
# ── 8. COMPANY INFO ───────────────────────────────────────────────────────────
section("8. COMPANY INFO — .info vs .info()")
yf_info = yf_t.info
db_info, db_info_err = try_db(db_t.info)
if db_info_err:
print(f" defeatbeta→ ERROR: {db_info_err}")
else:
fields = [
("sector", "sector", yf_info.get("sector")),
("industry", "industry", yf_info.get("industry")),
("employees", "full_time_employees", yf_info.get("fullTimeEmployees")),
("website", "web_site", yf_info.get("website")),
# Note: yf longName = company name; longBusinessSummary = description
("longName", None, yf_info.get("longName")),
("longBusinessSummary", "long_business_summary", yf_info.get("longBusinessSummary", "")[:60]),
]
print(f"\n {'Field':<30} {'yfinance':<35} {'defeatbeta'}")
print(f" {'-'*30} {'-'*35} {'-'*30}")
for label, db_col, yf_val in fields:
db_val = db_info[db_col].iloc[0] if db_col and db_col in db_info.columns else ""
if isinstance(db_val, str) and len(db_val) > 40:
db_val = db_val[:40] + ""
if isinstance(yf_val, str) and len(yf_val) > 34:
yf_val = yf_val[:34] + ""
print(f" {label:<30} {str(yf_val):<35} {str(db_val)}")
# ── SUMMARY ───────────────────────────────────────────────────────────────────
print(f"\n{'='*68}")
print(" ALL CHECKS COMPLETE")
print(f"{'='*68}\n")
+302
View File
@@ -0,0 +1,302 @@
#+title: yfinance API Reference
#+subtitle: Version 1.3.0
#+author: Ran Aroussi
#+date: 2026-04-25
* Overview
yfinance offers a Pythonic way to fetch financial & market data from Yahoo! Finance.
** Installation
#+begin_src sh
pip install yfinance
#+end_src
** Quick Start
#+begin_src python
import yfinance as yf
# Single ticker
dat = yf.Ticker("MSFT")
dat.info
dat.history(period='1mo')
dat.option_chain(dat.options[0]).calls
# Multiple tickers
tickers = yf.Tickers('MSFT AAPL GOOG')
tickers.tickers['MSFT'].info
yf.download(['MSFT', 'AAPL', 'GOOG'], period='1mo')
# Funds
spy = yf.Ticker('SPY').funds_data
spy.description
spy.top_holdings
#+end_src
* Top-Level Functions
| Function | Description |
|--------------------------------+-------------------------------------------|
| ~yf.download(tickers, ...)~ | Download market data for multiple tickers |
| ~yf.enable_debug_mode()~ | Enable verbose debug logging |
| ~yf.set_tz_cache_location(path)~ | Set timezone cache directory |
| ~yf.screen(query)~ | Run equity/fund/ETF screener queries |
* Config
| Setting | Description |
|---------------------------------+----------------------|
| ~yf.config.debug.logging = True~ | Enable debug logging |
| ~yf.config.user_agent = 'custom'~ | Custom user agent |
* Ticker(symbol)
** Price History
| Property/Method | Returns |
|---------------------------------------------+--------------------------------------|
| ~.history(period, start, end, interval, ...)~ | OHLCV DataFrame |
| ~.get_history_metadata()~ | Dict with currency, exchange, etc. |
| ~.get_dividends()~ | Dividend history (Series) |
| ~.dividends~ | Cached dividend history |
| ~.get_splits()~ | Stock split history (Series) |
| ~.splits~ | Cached split history |
| ~.get_actions()~ | Dividends + splits combined (Series) |
| ~.actions~ | Cached actions history |
| ~.get_capital_gains()~ | Capital gains distributions (Series) |
| ~.capital_gains~ | Cached capital gains |
| ~.get_shares_full()~ | Full shares outstanding history |
** Info & News
| Property/Method | Returns |
|-------------------------------+----------------------------------|
| ~.get_info()~ / ~.info~ | Full company info dict |
| ~.get_fast_info()~ / ~.fast_info~ | Quick-access key metrics |
| ~.get_news()~ / ~.news~ | Recent news articles (DataFrame) |
| ~.isin~ | ISIN identifier |
| ~.get_isin()~ | ISIN as string |
** Financial Statements
| Property/Method | Returns |
|------------------------+-----------------------------------------|
| ~.income_stmt~ | Annual income statement |
| ~.quarterly_income_stmt~ | Quarterly income statement |
| ~.ttm_income_stmt~ | Trailing-twelve-months income statement |
| ~.balance_sheet~ | Annual balance sheet |
| ~.cashflow~ | Annual cash flow statement |
| ~.quarterly_cashflow~ | Quarterly cash flow |
| ~.ttm_cashflow~ | TTM cash flow |
| ~.get_income_stmt()~ | Alias for income_stmt |
| ~.get_balance_sheet()~ | Alias for balance_sheet |
| ~.get_cashflow()~ | Alias for cashflow |
** Earnings & Calendar
| Property/Method | Returns |
|-----------------------+--------------------------------------|
| ~.earnings~ | Annual earnings summary |
| ~.calendar~ | Upcoming earnings/dividends dates |
| ~.get_earnings_dates()~ | Historical & upcoming earnings dates |
| ~.earnings_dates~ | Cached earnings dates |
| ~.get_sec_filings()~ | SEC filing history |
| ~.sec_filings~ | Cached SEC filings |
** Analysis & Estimates
| Property/Method | Returns |
|--------------------------------+------------------------------------|
| ~.get_recommendations()~ | Historical analyst recommendations |
| ~.recommendations~ | Cached recommendations |
| ~.get_recommendations_summary()~ | Summary of buy/hold/sell |
| ~.recommendations_summary~ | Cached summary |
| ~.get_upgrades_downgrades()~ | Analyst upgrades/downgrades |
| ~.upgrades_downgrades~ | Cached upgrades/downgrades |
| ~.get_sustainability()~ | ESG scores |
| ~.sustainability~ | Cached ESG |
| ~.get_analyst_price_targets()~ | Price target estimates |
| ~.analyst_price_targets~ | Cached price targets |
| ~.get_earnings_estimate()~ | Earnings estimates |
| ~.earnings_estimate~ | Cached earnings estimates |
| ~.get_revenue_estimate()~ | Revenue estimates |
| ~.revenue_estimate~ | Cached revenue estimates |
| ~.get_earnings_history()~ | Earnings surprise history |
| ~.earnings_history~ | Cached earnings history |
| ~.get_eps_trend()~ | EPS trend revisions |
| ~.eps_trend~ | Cached EPS trend |
| ~.get_eps_revisions()~ | EPS revision counts |
| ~.eps_revisions~ | Cached EPS revisions |
| ~.get_growth_estimates()~ | Growth rate estimates |
| ~.growth_estimates~ | Cached growth estimates |
** Holdings & Insider Activity
| Property/Method | Returns |
|---------------------------------------------------------+-----------------------------------|
| ~.get_funds_data()~ / ~.funds_data~ | Fund info (for ETFs/mutual funds) |
| ~.get_insider_purchases()~ / ~.insider_purchases~ | Insider purchase records |
| ~.get_insider_transactions()~ / ~.insider_transactions~ | Insider trade history |
| ~.get_insider_roster_holders()~ / ~.insider_roster_holders~ | Insider roster |
| ~.get_major_holders()~ / ~.major_holders~ | Ownership breakdown |
| ~.get_institutional_holders()~ / ~.institutional_holders~ | Institutional holders |
| ~.get_mutualfund_holders()~ / ~.mutualfund_holders~ | Mutual fund holders |
** Options
| Method | Returns |
|---------------------+-------------------------------------|
| ~.options~ | Tuple of available expiration dates |
| ~.option_chain(date)~ | Calls & puts DataFrame for a date |
| | |
* Tickers('SYM1 SYM2 ...')
Multiple tickers class.
| Property | Returns |
|---------------------------+----------------------------------|
| ~.tickers['SYM'].info~ | Access individual Ticker objects |
| ~.tickers['SYM'].history()~ | Get history per ticker |
* Market(market_code)
Market summary class.
| Method/Property | Returns |
|-----------------+---------------------------|
| ~.status~ | Market open/closed status |
| ~.summary()~ | Market summary data |
* Calendars
Calendar events class.
| Method | Returns |
|--------------+-------------------|
| ~.earnings()~ | Earnings calendar |
| ~.dividends()~ | Dividend calendar |
| ~.splits()~ | Splits calendar |
| ~.ipo()~ | IPO calendar |
* Search(query)
Search class for quotes and news.
| Property/Method | Returns |
|-----------------+----------------------|
| ~.quotes~ | Search result quotes |
| ~.news~ | Search result news |
| ~.lists~ | Watchlists/lists |
| ~.nav~ | Navigation results |
| ~.research~ | Research reports |
| ~.get_quotes()~ | Fetch quotes |
| ~.get_news()~ | Fetch news |
* Lookup(query)
Ticker lookup class.
| Method | Returns |
|---------------+------------------------|
| ~.get_quotes()~ | Lookup matching quotes |
* WebSocket(symbols, ...)
Live streaming data (synchronous).
| Method | Description |
|-----------------------+---------------------------|
| ~.connect()~ | Open WebSocket connection |
| ~.subscribe(symbols)~ | Subscribe to symbols |
| ~.unsubscribe(symbols)~ | Unsubscribe from symbols |
| ~.close()~ | Close connection |
* AsyncWebSocket(symbols, ...)
Live streaming data (asynchronous).
Same methods as ~WebSocket~, but async.
* Sector(sector_key)
Sector information class.
| Property/Method | Returns |
|-----------------+--------------------------|
| ~.key~ | Sector identifier |
| ~.name~ | Sector name |
| ~.symbol~ | Associated ETF symbol |
| ~.top_etfs~ | Top ETFs in sector |
| ~.top_companies~ | Top companies in sector |
| ~.industries~ | Industries within sector |
* Industry(industry_key)
Industry information class.
| Property/Method | Returns |
|-----------------+---------------------------|
| ~.key~ | Industry identifier |
| ~.name~ | Industry name |
| ~.sector_key~ | Parent sector |
| ~.top_companies~ | Top companies in industry |
* Query Builders (Screener)
| Class | Description |
|------------------+------------------------------------|
| ~EquityQuery~ | Build equity filter queries |
| ~FundQuery~ | Build mutual fund filter queries |
| ~ETFQuery~ | Build ETF filter queries |
| ~yf.screen(query)~ | Execute a query and return results |
* download() Parameters
#+begin_src python
yf.download(
tickers, # str or list of tickers
period="1mo", # 1d, 5d, 1mo, 3mo, 6mo, 1y, 2y, 5y, 10y, ytd, max
start=None, # datetime or str "YYYY-MM-DD"
end=None,
interval="1d", # 1m, 2m, 5m, 15m, 30m, 60m, 90m, 1h, 1d, 5d, 1wk, 1mo, 3mo
group_by="column", # "column" or "ticker"
auto_adjust=False,
back_adjust=False,
repair=False, # Enable price repair
keepna=False,
proxy=None,
timeout=10,
threads=True,
progress=True,
)
#+end_src
* Advanced Features
** Logging
Enable debug logging:
#+begin_src python
yf.config.debug.logging = True
#+end_src
** Caching
- Persistent cache is enabled by default
- Set custom cache location: ~yf.set_tz_cache_location(path)~
** Price Repair
- Enable with ~repair=True~ in ~download()~ or ~history()~
- Fixes NaN values, bad splits, and dividend adjustments
- Dividend repair also available
** Multi-Level Column Index
- When downloading multiple tickers, columns are MultiIndex
- ~group_by="column"~ or ~group_by="ticker"~
* Legal Disclaimer
Yahoo!, Y!Finance, and Yahoo! finance are registered trademarks of Yahoo, Inc.
yfinance is /not/ affiliated, endorsed, or vetted by Yahoo, Inc. It's an open-source tool that uses Yahoo's publicly available APIs, and is intended for research and educational purposes.
You should refer to Yahoo!'s terms of use for details on your rights to use the actual data downloaded. The Yahoo! finance API is intended for personal use only.