""" 5-Year Quarter-by-Quarter Comparison: Stock Oracle vs YFinance_plus """ import requests import yfinance_plus as yf from datetime import datetime, timezone import pandas as pd import json from typing import Dict, Any, List # API configuration API_URL = "http://localhost:18001/api/v1" def get_yfinance_plus_5year_data(ticker: str) -> Dict[str, Any]: """Get 5 years of quarterly financial data from yfinance_plus""" print(f"\n=== Getting 5-year yfinance_plus data for {ticker} ===") stock = yf.Ticker(ticker) # Get quarterly financial statements quarterly_income = stock.quarterly_income_stmt quarterly_balance = stock.quarterly_balance_sheet quarterly_cashflow = stock.quarterly_cashflow # Get company info info = stock.info print(f"Company: {info.get('longName', 'N/A')}") print(f"Shares Outstanding: {info.get('sharesOutstanding', 0):,.0f}") print(f"Available quarters in income statement: {len(quarterly_income.columns)}") print(f"Date range: {quarterly_income.columns[-1]} to {quarterly_income.columns[0]}") # Process quarterly data quarterly_data = [] for quarter_date in quarterly_income.columns: try: # Income statement revenue = quarterly_income.loc['Total Revenue', quarter_date] if 'Total Revenue' in quarterly_income.index else None net_income = quarterly_income.loc['Net Income', quarter_date] if 'Net Income' in quarterly_income.index else None gross_profit = quarterly_income.loc['Gross Profit', quarter_date] if 'Gross Profit' in quarterly_income.index else None operating_income = quarterly_income.loc['Operating Income', quarter_date] if 'Operating Income' in quarterly_income.index else None # Balance sheet (if available for this quarter) total_assets = None total_equity = None total_debt = None cash = None if not quarterly_balance.empty and quarter_date in quarterly_balance.columns: total_assets = quarterly_balance.loc['Total Assets', quarter_date] if 'Total Assets' in quarterly_balance.index else None total_equity = quarterly_balance.loc['Total Equity Gross Minority Interest', quarter_date] if 'Total Equity Gross Minority Interest' in quarterly_balance.index else None total_debt = quarterly_balance.loc['Total Debt', quarter_date] if 'Total Debt' in quarterly_balance.index else None cash = quarterly_balance.loc['Cash And Cash Equivalents', quarter_date] if 'Cash And Cash Equivalents' in quarterly_balance.index else None # Cash flow (if available for this quarter) operating_cash_flow = None capex = None if not quarterly_cashflow.empty and quarter_date in quarterly_cashflow.columns: operating_cash_flow = quarterly_cashflow.loc['Operating Cash Flow', quarter_date] if 'Operating Cash Flow' in quarterly_cashflow.index else None capex = quarterly_cashflow.loc['Capital Expenditure', quarter_date] if 'Capital Expenditure' in quarterly_cashflow.index else None # Calculate EPS shares_outstanding = info.get('sharesOutstanding', info.get('impliedSharesOutstanding', 0)) eps = net_income / shares_outstanding if net_income and shares_outstanding > 0 else None quarterly_data.append({ 'quarter_date': quarter_date, 'revenue': revenue, 'gross_profit': gross_profit, 'operating_income': operating_income, 'net_income': net_income, 'eps': eps, 'total_assets': total_assets, 'total_equity': total_equity, 'total_debt': total_debt, 'cash': cash, 'operating_cash_flow': operating_cash_flow, 'capex': capex, 'shares_outstanding': shares_outstanding }) except Exception as e: print(f"Error processing quarter {quarter_date}: {e}") continue return { 'info': info, 'quarterly_data': quarterly_data } def get_stock_oracle_5year_data(ticker: str) -> Dict[str, Any]: """Get 5 years of quarterly financial data from Stock Oracle""" print(f"\n=== Getting 5-year Stock Oracle data for {ticker} ===") # Request 5 years of data start_date = "2019-01-01" end_date = "2024-12-31" response = requests.post( f"{API_URL}/financial/data", json={ "ticker": ticker, "start_date": start_date, "end_date": end_date, "period_type": "all", "include_metrics": True, "force_refresh": True # Force refresh to get latest data } ) if response.status_code == 200: data = response.json() print(f"Company: {data['company']['name']}") print(f"Number of periods: {len(data['financial_data'])}") # Check real vs estimated data real_data_count = sum(1 for fd in data['financial_data'] if not fd.get('is_estimated', True)) print(f"Real data periods: {real_data_count}") print(f"Estimated data periods: {len(data['financial_data']) - real_data_count}") return data else: print(f"Error: {response.status_code} - {response.text}") return None def find_matching_quarters(yfinance_data: List[Dict], oracle_data: List[Dict]) -> List[tuple]: """Find quarters that exist in both datasets""" # Convert YFinance quarter dates to comparable format yf_quarters = set() for qd in yfinance_data: quarter_date = qd['quarter_date'] if hasattr(quarter_date, 'strftime'): yf_quarters.add(quarter_date.strftime('%Y-%m-%d')) else: yf_quarters.add(str(quarter_date)[:10]) # Convert Oracle quarter dates to comparable format oracle_quarters = set() for fd in oracle_data: period_date = fd['period_date'] oracle_quarters.add(period_date[:10]) # Take YYYY-MM-DD part # Find intersection common_quarters = yf_quarters.intersection(oracle_quarters) print(f"\nCommon quarters found: {len(common_quarters)}") print(f"YFinance quarters: {len(yf_quarters)}") print(f"Oracle quarters: {len(oracle_quarters)}") return sorted(list(common_quarters)) def compare_quarter_by_quarter(yfinance_data: Dict, oracle_data: Dict, ticker: str): """Compare quarter by quarter for exact matches""" print(f"\n=== QUARTER-BY-QUARTER COMPARISON FOR {ticker} ===") if not oracle_data or 'financial_data' not in oracle_data: print("No Stock Oracle data to compare") return yf_quarterly = yfinance_data['quarterly_data'] oracle_quarterly = oracle_data['financial_data'] # Find matching quarters common_quarters = find_matching_quarters(yf_quarterly, oracle_quarterly) if not common_quarters: print("No matching quarters found between datasets") return print(f"\nComparing {len(common_quarters)} matching quarters:") print("=" * 100) total_revenue_diff = 0 total_net_income_diff = 0 total_eps_diff = 0 compared_quarters = 0 for quarter_str in common_quarters[:20]: # Limit to 20 quarters for readability # Find YFinance data for this quarter yf_quarter = None for qd in yf_quarterly: quarter_date = qd['quarter_date'] if hasattr(quarter_date, 'strftime'): qd_str = quarter_date.strftime('%Y-%m-%d') else: qd_str = str(quarter_date)[:10] if qd_str == quarter_str: yf_quarter = qd break # Find Oracle data for this quarter oracle_quarter = None for fd in oracle_quarterly: if fd['period_date'][:10] == quarter_str: oracle_quarter = fd break if not yf_quarter or not oracle_quarter: continue print(f"\nšŸ“… Quarter: {quarter_str}") print(f"Oracle Data Source: {oracle_quarter.get('data_source', 'Unknown')}") print(f"Oracle Is Estimated: {oracle_quarter.get('is_estimated', 'Unknown')}") # Compare Revenue oracle_revenue = oracle_quarter.get('revenue', 0) or 0 yf_revenue = yf_quarter.get('revenue', 0) or 0 if oracle_revenue > 0 and yf_revenue > 0: revenue_diff = ((oracle_revenue - yf_revenue) / yf_revenue) * 100 total_revenue_diff += abs(revenue_diff) print(f"šŸ’° Revenue:") print(f" Oracle: ${oracle_revenue:,.0f}") print(f" YFinance: ${yf_revenue:,.0f}") print(f" Difference: {revenue_diff:+.2f}%") # Compare Net Income oracle_net = oracle_quarter.get('net_income', 0) or 0 yf_net = yf_quarter.get('net_income', 0) or 0 if oracle_net != 0 and yf_net != 0: net_diff = ((oracle_net - yf_net) / yf_net) * 100 total_net_income_diff += abs(net_diff) print(f"šŸ“ˆ Net Income:") print(f" Oracle: ${oracle_net:,.0f}") print(f" YFinance: ${yf_net:,.0f}") print(f" Difference: {net_diff:+.2f}%") # Compare EPS oracle_eps = oracle_quarter.get('eps', 0) or 0 yf_eps = yf_quarter.get('eps', 0) or 0 if oracle_eps > 0 and yf_eps > 0: eps_diff = ((oracle_eps - yf_eps) / yf_eps) * 100 total_eps_diff += abs(eps_diff) print(f"šŸ“Š EPS:") print(f" Oracle: ${oracle_eps:.2f}") print(f" YFinance: ${yf_eps:.2f}") print(f" Difference: {eps_diff:+.2f}%") # Compare Shares Outstanding oracle_shares = oracle_quarter.get('shares_outstanding', 0) or 0 yf_shares = yf_quarter.get('shares_outstanding', 0) or 0 if oracle_shares > 0 and yf_shares > 0: shares_diff = ((oracle_shares - yf_shares) / yf_shares) * 100 print(f"šŸ¢ Shares Outstanding:") print(f" Oracle: {oracle_shares:,.0f}") print(f" YFinance: {yf_shares:,.0f}") print(f" Difference: {shares_diff:+.2f}%") compared_quarters += 1 print("-" * 80) # Summary statistics if compared_quarters > 0: print(f"\nšŸ“Š SUMMARY STATISTICS ({compared_quarters} quarters)") print("=" * 50) print(f"Average Revenue Difference: {total_revenue_diff/compared_quarters:.2f}%") print(f"Average Net Income Difference: {total_net_income_diff/compared_quarters:.2f}%") print(f"Average EPS Difference: {total_eps_diff/compared_quarters:.2f}%") def main(): """Main comparison function""" tickers = ["AAPL", "MSFT"] for ticker in tickers: print(f"\n{'='*100}") print(f"5-YEAR QUARTER-BY-QUARTER COMPARISON: {ticker}") print(f"{'='*100}") # Get data from both sources yfinance_data = get_yfinance_plus_5year_data(ticker) oracle_data = get_stock_oracle_5year_data(ticker) # Compare quarter by quarter compare_quarter_by_quarter(yfinance_data, oracle_data, ticker) print(f"\n{'='*100}") if __name__ == "__main__": main()