- 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>
21 KiB
- Price & Volume Data
- DefeatBeta Price Data Structure
- Financial Statements
- Valuation Metrics
- Financial Ratios
- Growth Metrics
- Margin Metrics
- Dividends & Stock Splits
- Company Info & Metadata
- Unique DefeatBeta Features (Not in Yahoo Finance)
- Example: yfinance → DefeatBeta Migration
- Quick Reference: Common Operations
- Data Type Differences
- Converting Decimal to Float
- When to Use Each
- Environment Setup
- Mapping Limitations & Verification Notes
- What was confirmed correct (live data matched)
- Incorrect property names for yfinance (deprecated in v1.3)
- Conceptual mismatch: longName vs long_business_summary (Company Info)
- Typo in Financial Statements note (cashflow row)
- Data format differences found in verified pairs
- Historical coverage gap
- DuckDB compatibility issue (defeatbeta-api 0.0.45 + DuckDB 1.4.3)
- Data freshness
- Common Issues & Solutions
- Additional Resources
- Footer
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 |
ticker.history(start='...', end='...') |
ticker.price() (filter) |
pandas.DataFrame | Date filtering available |
DefeatBeta Price Data Structure
# Columns: ['symbol', 'report_date', 'open', 'close', 'high', 'low', 'volume']
# Example:
symbol report_date open close high low volume
0 AAPL 2026-04-17 266.96 270.23 272.30 266.72 61314800
Financial Statements
| 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
# DefeatBeta Statement objects have these methods:
income_stmt = ticker.quarterly_income_statement()
income_stmt.df() # Returns pandas.DataFrame
income_stmt.data() # Alternative access
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) |
Key Advantage: Historical Valuation Data
DefeatBeta provides full historical time series for:
- TTM P/E ratios (all daily closes)
- TTM EPS history
- Market cap history
- Price/Book, Price/Sales ratios
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 |
WACC Components Available in DefeatBeta
# Full breakdown of WACC calculation:
wacc = ticker.wacc()
# Columns: market_capitalization, beta_5y, sp500_10y_cagr, treasure_10y_yield,
# weight_of_debt, weight_of_equity, cost_of_debt, cost_of_equity, 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 |
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 |
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 |
Company Info & Metadata
| 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 |
Example: yfinance → DefeatBeta Migration
Yahoo Finance Style
import yfinance as yf
ticker = yf.Ticker('AAPL')
# Current valuation
pe = ticker.info['trailingPE']
eps = ticker.info['trailingEps']
market_cap = ticker.info['marketCap']
# Financial statements
quarterly_financials = ticker.quarterly_financials
quarterly_balance = ticker.quarterly_balance_sheet
# Growth
revenue_growth = ticker.info['revenueGrowth']
DefeatBeta Equivalent
from defeatbeta_api.data.ticker import Ticker
ticker = Ticker('AAPL')
# Historical valuation time series
ttm_pe = ticker.ttm_pe() # Full daily P/E history
ttm_eps = ticker.ttm_eps() # Full EPS history
market_cap = ticker.market_capitalization() # Daily market cap
# Financial statements
quarterly_income = ticker.quarterly_income_statement()
quarterly_balance = ticker.quarterly_balance_sheet()
# Convert to DataFrame
income_df = quarterly_income.df()
# Growth metrics (time series!)
revenue_growth = ticker.quarterly_revenue_yoy_growth()
eps_growth = ticker.quarterly_eps_yoy_growth()
Getting Current Values from DefeatBeta
# DefeatBeta provides time series, but getting current value is easy:
current_pe = ticker.ttm_pe().iloc[-1]['ttm_pe']
current_eps = ticker.ttm_eps().iloc[-1]['tailing_eps']
current_mcap = ticker.market_capitalization().iloc[-1]['market_capitalization']
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'] |
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()) |
Converting Decimal to Float
# DefeatBeta returns Decimal types for financial data
# Always convert before arithmetic operations
value = ticker.ttm_eps().iloc[-1]['tailing_eps']
value_float = float(value) # Convert Decimal → float
# Use in calculations
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 |
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 |
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 exactlysplits(): 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) |
Additional Resources
- DefeatBeta-API: https://github.com/defeat-beta/defeatbeta-api
- Documentation: https://github.com/defeat-beta/defeatbeta-api/tree/main/doc
- DCF Examples: https://github.com/defeat-beta/defeatbeta-api/tree/main/doc/api/DCF_Examples.md
- Value Examples: https://github.com/defeat-beta/defeatbeta-api/tree/main/doc/api/Value_Examples.md
Footer
Last updated: 2026-04-26 (verified via test_mapping.py on AAPL) Author: Documentation Version: 1.0