""" 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")