![]()
InĀ [1]:
from datetime import datetime
import pandas as pd
import numpy as np
# =====================================================
# 1. INITIALIZATION & SETUP
# =====================================================
qb = QuantBook()
# Define your list of tickers here
tickers = ["NVDA", "AMZN", "JPM"]
# Data Window
start = datetime(1998, 1, 1)
end = datetime(2026, 3, 28)
folder_name = "Data_Financials"
# Define Field Map (Strictly raw data for Go backend processing)
field_map = {
"CompanyProfile.SharesOutstanding": "SharesOutstanding",
"CompanyReference.FiscalYearEnd": "LatestFiscalYearEndMonth",
"CompanyReference.ExpectedFiscalYearEnd": "ExpectedFiscalYearEndMonth",
"FinancialStatements.IncomeStatement.TotalRevenue.ThreeMonths": "Revenue",
"FinancialStatements.IncomeStatement.GrossProfit.ThreeMonths": "GrossProfit",
"FinancialStatements.IncomeStatement.OperatingIncome.ThreeMonths": "OperatingIncome",
"FinancialStatements.IncomeStatement.NetIncome.ThreeMonths": "NetIncome",
"FinancialStatements.IncomeStatement.PretaxIncome.ThreeMonths": "PretaxIncome",
"FinancialStatements.IncomeStatement.TaxProvision.ThreeMonths": "TaxProvision",
"FinancialStatements.IncomeStatement.OtherNonOperatingIncomeExpenses.ThreeMonths": "OtherNonOp",
"FinancialStatements.IncomeStatement.EBIT.ThreeMonths": "EBIT",
"FinancialStatements.IncomeStatement.EBITDA.ThreeMonths": "EBITDA",
"FinancialStatements.IncomeStatement.InterestExpense.ThreeMonths": "InterestExpense",
"FinancialStatements.IncomeStatement.ResearchAndDevelopment.ThreeMonths": "ResearchAndDevelopment",
"FinancialStatements.IncomeStatement.SellingGeneralAndAdministration.ThreeMonths": "SGA_Expense",
"FinancialStatements.IncomeStatement.NetInterestIncome.ThreeMonths": "NetInterestIncome",
"FinancialStatements.IncomeStatement.CreditLossesProvision.ThreeMonths": "CreditLossesProvision",
"FinancialStatements.BalanceSheet.CurrentAssets.ThreeMonths": "CurrentAssets",
"FinancialStatements.BalanceSheet.CurrentLiabilities.ThreeMonths": "CurrentLiabilities",
"FinancialStatements.BalanceSheet.StockholdersEquity.ThreeMonths": "StockholdersEquity",
"FinancialStatements.BalanceSheet.TotalEquity.ThreeMonths": "TotalEquity",
"FinancialStatements.BalanceSheet.TotalAssets.ThreeMonths": "TotalAssets",
"FinancialStatements.BalanceSheet.TotalDebt.ThreeMonths": "TotalDebt",
"FinancialStatements.BalanceSheet.CurrentDebt.ThreeMonths": "ShortTermDebt",
"FinancialStatements.BalanceSheet.LongTermDebt.ThreeMonths": "LongTermDebt",
"FinancialStatements.BalanceSheet.CashAndCashEquivalents.ThreeMonths": "CashAndCashEquivalents",
"FinancialStatements.BalanceSheet.Cash.ThreeMonths": "Cash",
"FinancialStatements.BalanceSheet.CashEquivalents.ThreeMonths": "CashEquivalents",
"FinancialStatements.BalanceSheet.OtherShortTermInvestments.ThreeMonths": "OtherShortTermInvestments",
"FinancialStatements.BalanceSheet.GoodwillAndOtherIntangibleAssets.ThreeMonths": "IntangibleAssets",
"FinancialStatements.BalanceSheet.PreferredStock.ThreeMonths": "PreferredStock",
"FinancialStatements.BalanceSheet.AccountsReceivable.ThreeMonths": "AccountsReceivable",
"FinancialStatements.BalanceSheet.CapitalLeaseObligations.ThreeMonths": "CapitalLeaseObligations",
"FinancialStatements.BalanceSheet.Inventory.ThreeMonths": "Inventory",
"FinancialStatements.BalanceSheet.AccountsPayable.ThreeMonths": "AccountsPayable",
"FinancialStatements.BalanceSheet.RetainedEarnings.ThreeMonths": "RetainedEarnings",
"FinancialStatements.CashFlowStatement.FreeCashFlow.ThreeMonths": "FreeCashFlow",
"FinancialStatements.CashFlowStatement.OperatingCashFlow.ThreeMonths": "OperatingCashFlow",
"FinancialStatements.CashFlowStatement.InvestingCashFlow.ThreeMonths": "InvestingCashFlow",
"FinancialStatements.CashFlowStatement.FinancingCashFlow.ThreeMonths": "FinancingCashFlow",
"FinancialStatements.CashFlowStatement.StockBasedCompensation.ThreeMonths": "StockBasedCompensation",
"FinancialStatements.CashFlowStatement.CapitalExpenditure.ThreeMonths": "CapitalExpenditure",
"FinancialStatements.CashFlowStatement.DepreciationAndAmortization.ThreeMonths": "DepreciationAndAmortization",
"FinancialStatements.CashFlowStatement.Depreciation.ThreeMonths": "Depreciation",
"FinancialStatements.CashFlowStatement.RepurchaseOfCapitalStock.ThreeMonths": "Buybacks_CommonAndPreferredStock",
"FinancialStatements.CashFlowStatement.CommonStockPayments.ThreeMonths": "Buybacks_CommonStock",
"EarningReports.PeriodEndingDate.ThreeMonths": "FiscalPeriodEnd",
"EarningReports.TotalDividendPerShare.ThreeMonths": "TotalDividend_PerShare",
"EarningReports.DilutedEPS.ThreeMonths": "DilutedEPS",
"EarningReports.DilutedAverageShares.ThreeMonths": "DilutedSharesOutstanding",
"OperationRatios.InventoryTurnover.ThreeMonths": "InventoryTurnover",
"OperationRatios.ReceivableTurnover.ThreeMonths": "ReceivableTurnover",
"OperationRatios.PaymentTurnover.ThreeMonths": "PaymentTurnover",
"OperationRatios.DaysInInventory.ThreeMonths": "DaysInInventory",
"OperationRatios.DaysInPayment.ThreeMonths": "DaysInPayables",
"OperationRatios.DaysInSales.ThreeMonths": "DaysInReceivables",
"OperationRatios.TaxRate.ThreeMonths": "TaxRate",
"ValuationRatios.ForwardPERatio": "ForwardPE_Ratio",
"ValuationRatios.TwoYearsForwardPERatio": "TwoYearsForwardPERatio",
"ValuationRatios.FirstYearEstimatedEPSGrowth": "FirstYearEstimatedEPSGrowth",
"ValuationRatios.SecondYearEstimatedEPSGrowth": "SecondYearEstimatedEPSGrowth",
"ValuationRatios.BuyBackYield": "BuyBackYield",
"ValuationRatios.TotalYield": "TotalYield",
"ValuationRatios.PEGRatio": "PEGRatio",
}
cols = [
"ReportDate", "FiscalPeriodEnd", "SharesOutstanding", "LatestFiscalYearEndMonth", "ExpectedFiscalYearEndMonth",
"Revenue", "GrossProfit", "OperatingIncome", "NetIncome", "PretaxIncome", "TaxProvision",
"OtherNonOp", "EBIT", "EBITDA", "InterestExpense", "ResearchAndDevelopment", "SGA_Expense", "NetInterestIncome",
"CreditLossesProvision", "CurrentAssets", "CurrentLiabilities", "StockholdersEquity", "TotalEquity", "TotalAssets",
"TotalDebt", "ShortTermDebt", "LongTermDebt", "CashAndCashEquivalents", "Cash", "CashEquivalents", "OtherShortTermInvestments",
"IntangibleAssets", "PreferredStock", "AccountsReceivable", "CapitalLeaseObligations", "Inventory", "AccountsPayable",
"RetainedEarnings", "FreeCashFlow", "OperatingCashFlow", "InvestingCashFlow", "FinancingCashFlow", "StockBasedCompensation",
"CapitalExpenditure", "DepreciationAndAmortization", "Depreciation", "Buybacks_CommonAndPreferredStock", "Buybacks_CommonStock",
"TotalDividend_PerShare", "DilutedEPS", "DilutedSharesOutstanding", "InventoryTurnover", "ReceivableTurnover", "PaymentTurnover",
"DaysInInventory", "DaysInPayables", "DaysInReceivables", "TaxRate", "ForwardPE_Ratio", "TwoYearsForwardPERatio",
"FirstYearEstimatedEPSGrowth", "SecondYearEstimatedEPSGrowth", "BuyBackYield", "TotalYield", "PEGRatio",
]
print(f"Beginning fundamental data extraction for {len(tickers)} tickers...\n")
# =====================================================
# 2. MASTER LOOP FOR ALL TICKERS
# =====================================================
for ticker in tickers:
print(f"Processing {ticker}...")
try:
# Add Equity for the specific ticker
symbol = qb.AddEquity(ticker, Resolution.Daily).Symbol
# --- DATA EXTRACTION & ALIGNMENT ---
all_data = []
for selector, clean_name in field_map.items():
df = qb.GetFundamental([symbol], selector, start, end)
if not df.empty:
df.index = df.index.normalize()
df.columns = [clean_name]
df = df[~df.index.duplicated(keep='last')]
all_data.append(df)
if not all_data:
print(f"No fundamental data found for {ticker}. Skipping.")
continue
fund_df = pd.concat(all_data, axis=1).sort_index()
fund_df = fund_df[~fund_df.index.duplicated(keep='last')]
fund_df = fund_df.ffill()
# SAFETY CHECK: Ensure Revenue exists before masking
if "Revenue" not in fund_df.columns:
print(f"{ticker} is missing 'Revenue' data. Cannot isolate quarters. Skipping.")
continue
# --- QUARTERLY ISOLATION MASK ---
report_mask = fund_df["Revenue"].ne(fund_df["Revenue"].shift()) & fund_df["Revenue"].notna()
q_data = fund_df.loc[report_mask].copy()
if q_data.empty:
print(f"No quarterly changes detected for {ticker}. Skipping.")
continue
# --- DATE FORMATTING ---
q_data = q_data.reset_index().rename(columns={"index": "Date"})
q_data["Date"] = pd.to_datetime(q_data["Date"])
if q_data["Date"].dt.tz is None:
q_data["Date"] = q_data["Date"].dt.tz_localize('UTC')
q_data["Date"] = q_data["Date"].dt.tz_convert('US/Eastern')
q_data["ReportDate"] = q_data["Date"].dt.strftime('%Y-%m-%d')
# SAFETY CHECKS: Only format these columns if they actually exist for this stock
if "FiscalPeriodEnd" in q_data.columns:
q_data["FiscalPeriodEnd"] = pd.to_datetime(q_data["FiscalPeriodEnd"]).dt.strftime('%Y-%m-%d')
if 'ExpectedFiscalYearEndMonth' in q_data.columns:
q_data['ExpectedFiscalYearEndMonth'] = q_data['ExpectedFiscalYearEndMonth'].astype(str).str.split('.').str[0]
if 'LatestFiscalYearEndMonth' in q_data.columns:
q_data['LatestFiscalYearEndMonth'] = q_data['LatestFiscalYearEndMonth'].astype(str).str.split('.').str[0]
# --- FINAL TABLE SELECTION & EXPORT ---
# Only select columns that actually exist in our q_data to prevent KeyErrors
final_cols = [c for c in cols if c in q_data.columns]
# Ensure ReportDate is always first
if "ReportDate" not in final_cols:
final_cols.insert(0, "ReportDate")
final_table = q_data[final_cols].copy()
final_table.insert(0, "Symbol", ticker)
csv_output = final_table.to_csv(index=False, na_rep="", lineterminator='\n').strip()
file_name = f"financials_quarterly_{ticker}.csv"
object_store_key = f"{folder_name}/{file_name}"
qb.ObjectStore.Save(object_store_key, csv_output)
print(f"Extracted {len(final_table)} quarterly reports for {ticker}.")
except Exception as e:
print(f"Error processing {ticker}: {str(e)}")
print("\nAll fundamental data processing complete!")