PáginasDatos fundamentales · 11 / 29
Datos fundamentales
Trabajo en curso: los datos fundamentales aún no son totalmente funcionales. Usar esta función en el IDE o en los backtests puede devolver datos fundamentales inconsistentes (campos ausentes, fechas de informe que no coinciden o instantáneas alineadas con las barras inestables). Trata los resultados como experimentales hasta que una versión futura marque los datos fundamentales como estables.
Las estrategias de QuantCraft pueden usar datos financieros de empresas junto con las barras de precio OHLCV: balances, estados de flujo de caja, cuentas de resultados e historial / estimaciones de resultados. Los datos se cargan una vez por símbolo desde el servicio de datos fundamentales de QuantCraft, se organizan en tablas indexadas por fecha y se ponen a disposición de tu estrategia como instantáneas alineadas con las barras durante un backtest. El momento de los callbacks sigue el Ciclo de vida de la estrategia; configura símbolos y fechas en Test (Ejecutar código).
Además de los tres estados financieros, obtienes ratios (91 en total), valores por acción, múltiplos y rendimientos de valoración y puntuaciones de calidad (Piotroski F, Altman Z-prime, Beneish M), todo point-in-time y todo opcional. Se van desplegando símbolo a símbolo, así que protege cada acceso: raw["metricsInputs"] is None significa que un paquete es anterior a ellos.
Esta página cubre:
- Qué datos de estados financieros hay disponibles
- Cómo se organizan las tablas indexadas por fecha
- Cómo llegan las cargas alineadas con las barras a tus callbacks durante un backtest
Relacionado: los conjuntos de datos globales de rendimientos de factores Fama-French (no por ticker) son una función aparte; consulta Factores Fama-French (
fama_french.qc, sin argumento de callback). Lasrowsde factores están indexadas por cadenasYYYYMM, no por índices de lista.
Qué obtienes
Cada paquete de datos fundamentales es un único objeto JSON de un ticker, que contiene:
- Balance: informes
quarterlyyyearly. - Flujo de caja: informes
quarterlyyyearly. - Cuenta de resultados: informes
quarterlyyyearly. - Resultados (earnings):
- History: BPA publicado frente a estimaciones y sorpresas por fecha de informe.
- Trend: estimaciones futuras, tendencia del BPA y revisiones de analistas.
- Annual:
epsActualpor ejercicio fiscal.
- Ratios: ratios financieros
quarterlyyyearly(márgenes, rentabilidades, liquidez, apalancamiento). - Financials extended: métricas extendidas
quarterlyyyearlyque no están en los estados básicos de resultados, balance o flujo de caja. - Por acción: valores por acción
quarterlyyyearlytal como se presentaron (número de acciones sobre la base de split de ese periodo). - Valoración: capitalización bursátil, valor empresarial, múltiplos y rendimientos
quarterlyyyearly, más un objetolatestsin fecha. - Puntuaciones: Piotroski F, Altman Z-prime y Beneish M
quarterlyyyearly, másnotApplicableReason. - TTM: un único objeto de los últimos doce meses (no agrupado por periodo).
- Procedencia de las métricas: objetos planos
metricsInputs/metricsHealth.metricsInputsesNoneen un paquete anterior a la ampliación de métricas. - Historial de presentaciones: metadatos de presentación
quarterlyyyearly(tipo de formulario, fecha de presentación, indexados por fin de periodo). También se incluye en las instantáneas alineadas con las barrascurrent(...)cuando está presente en el paquete; las tablas brutas siguen disponibles mediantef.tables["filingHistory.quarterly"]. - Información de la empresa: metadatos planos de la entidad (nombre, CIK, SIC, dirección, bolsas, tickers). No indexados por fecha y ausentes de las instantáneas alineadas con las barras; se accede mediante
f.raw["companyInfo"].
Cada informe es una fila de métricas en camelCase; por ejemplo totalAssets, cash, freeCashFlow, totalRevenue, netIncome, epsActual, epsEstimate, surprisePercent. Los valores numéricos pueden llegar como cadenas en el JSON subyacente, y cualquier campo ausente se devuelve como None.
Un ticker concreto puede no exponer todas las secciones. Consulta el Explorador de cobertura de datos fundamentales para ver qué campos hay disponibles para un ticker.
Tablas indexadas por fecha
Para cada sección anterior, los datos fundamentales se organizan como una tabla indexada por fecha: las filas se indexan por fecha de informe (YYYY-MM-DD) y las métricas se exponen como listas paralelas que puedes indexar como un historial de precios.
Las rutas de tabla estándar son:
| Ruta | Significado |
|---|---|
balanceSheet.quarterly / balanceSheet.yearly | Instantáneas del balance |
cashFlow.quarterly / cashFlow.yearly | Estados de flujo de caja |
incomeStatement.quarterly / incomeStatement.yearly | Cuentas de resultados |
earnings.History | BPA publicado, estimaciones, sorpresa por informe |
earnings.Trend | Estimaciones de analistas, tendencia del BPA, revisiones |
earnings.Annual | epsActual anual |
ratios.quarterly / ratios.yearly | Ratios financieros (márgenes, rentabilidades, liquidez, apalancamiento) |
financialsExtended.quarterly / financialsExtended.yearly | Métricas financieras extendidas |
perShare.quarterly / perShare.yearly | Valores por acción (tal como se presentaron) |
valuation.quarterly / valuation.yearly | Múltiplos y rendimientos de valoración |
scores.quarterly / scores.yearly | Piotroski / Altman / Beneish |
filingHistory.quarterly / filingHistory.yearly | Metadatos de presentación (tipo de formulario, fecha de presentación) |
No son tablas. valuation.latest, scores.notApplicableReason, ttm, metricsInputs, metricsHealth y companyInfo no están indexados por fecha, así que no aparecen en tables, lists ni en ninguna instantánea a la hora de una barra; es intencionado:
| No es una tabla | Por qué |
|---|---|
valuation.latest | Un único objeto junto a las claves de fecha, no un periodo |
scores.notApplicableReason | Una cadena junto a las claves de fecha |
ttm | Un único objeto; los valores son escalares y no dicts de filas |
metricsInputs / metricsHealth | Objetos planos de procedencia |
companyInfo | Metadatos planos de la entidad |
Todos son a fecha de la subida y no por periodo, así que mantenerlos fuera de tables también los mantiene fuera de toda instantánea a la hora de una barra: un backtest no puede leer por accidente el precio de hoy en una barra de 2019. Accede a ellos mediante f.raw. Un bloque vacío ({"quarterly": {}, "yearly": {}}, que es el aspecto de los scores de un declarante del sector financiero) no registra ninguna tabla.
Convención de índices: primero lo más reciente
Dentro de cualquiera de estas tablas, el índice 0 es el periodo elegible más reciente, el índice 1 es el anterior, y así sucesivamente. Coincide con el funcionamiento de las series de precios en el resto de QuantCraft.
Si quieres cargar un paquete directamente (por ejemplo, fuera de un backtest), la forma básica es:
from quantcraft.fundamentals import QcFundamentals
f = QcFundamentals(token, "fundamentals/AAPL.json.gz")
latest_total_assets = f.tables["balanceSheet.quarterly"]["totalAssets"][0]
prior_total_assets = f.tables["balanceSheet.quarterly"]["totalAssets"][1]
same = f.lists["balanceSheet.quarterly.totalAssets"][0]
whole = f.rawLo que puedes leer de un paquete cargado:
| Atributo | Qué te da |
|---|---|
f.raw | El árbol JSON decodificado completo. |
f.symbol | Ticker resuelto (p. ej. "AAPL"). |
f.tables | Dict de objetos DateKeyedTable indexado por ruta con puntos (p. ej. "balanceSheet.quarterly"). |
f.table(path) | Acceso cómodo a una sola DateKeyedTable. |
f.lists | Mapa plano indexado por "<tablePath>.<fieldName>", con valores alineados de más reciente a más antiguo. |
Una DateKeyedTable expone periods (las claves YYYY-MM-DD, de más reciente a más antigua), columns (campo → valores) y admite la indexación table["fieldName"].
Descubrir campos en tiempo de ejecución es fácil:
sorted(f.lists.keys())muestra cada serie plana ysorted(t.columns.keys())muestra las columnas de una tabla; es útil cuando un servidor añade o elimina campos.
Cargas alineadas con las barras en backtests
En un backtest no lees los datos fundamentales como tablas brutas: el motor selecciona el informe adecuado para la barra actual y se lo entrega a tus callbacks como una instantánea. Eso se llama la carga alineada con las barras.
Configurar los datos fundamentales para un backtest
En la pestaña Symbol & data de Run backtest:
- Marca Uses fundamentals (select if your strategy requires fundamental data) (requiere haber iniciado sesión; QuantCraft envía tu token de sesión para cargar los archivos de datos fundamentales B2). Las ejecuciones forward masivas y sobre el gráfico lo llaman Use fundamentals (optional). La casilla se muestra cuando las funciones de datos fundamentales están disponibles en tu versión, pero está desactivada (con una pista de Premium) salvo que tengas Premium o esté habilitado el acceso a datos gratuitos.
- Elige uno o más paquetes de datos fundamentales en la selección múltiple (rutas como
fundamentals/AAPL.json.gz).
Con una fuente de símbolos Screener (backtest) o un objetivo Screener (ejecuciones masivas de AutoTrading / QuantCloud) no necesitas elegir nada: activa los datos fundamentales y cada símbolo que seleccione el filtro recibe su propio paquete, de modo que fundamentals.current(bar["t"], symbol=symbol) funciona para cada uno. Los paquetes proceden de la propia descarga del Screener (nada se obtiene dos veces) y un símbolo que el Screener aún no ha descargado se obtiene una vez y se conserva. En una ejecución en vivo, los paquetes siguen cada nuevo filtrado. Las selecciones manuales se siguen aceptando como extras (p. ej. un ticker de referencia). Un símbolo cuyos datos no se pueden cargar devuelve None en lugar de hacer fallar la ejecución; el panel Output indica cuántos se cargaron.
Los símbolos OHLCV y los símbolos de datos fundamentales son independientes. Puedes hacer backtest de RNMBY mediante el feed del bróker mientras cargas los datos fundamentales de RHM.XETRA: pasa el ticker correcto a fundamentals.current(..., symbol="RHM.XETRA") (o equivalente) en el código.
Cuando hay varios paquetes seleccionados, usa un symbol= explícito en fundamentals.current / get_data_with_offset cuando necesites un paquete concreto. El paquete principal usado para las instantáneas alineadas con las barras es por defecto el primer símbolo OHLCV de tu lista de símbolos, salvo que el motor aplique otra regla.
Para el acceso de bajo nivel a las tablas fuera de los callbacks, usa qc_fundamentals de quantcraft.process.runtime cuando no sea None (p. ej. qc_fundamentals.raw["companyInfo"]). Contiene solo el paquete principal; usa el manejador fundamentals del callback con symbol= para cualquier otro ticker.
Si los datos fundamentales no están configurados, el motor simplemente pasa fundamentals=None a tus callbacks y tú lo proteges con una comprobación.
Point-in-time (backtest): tanto el motor de backtest como Debug Test construyen BacktestFundamentals(..., backtest_mode=True), así que current / get_data_with_offset usan el filtrado por fecha de presentación (use_filing_date=True): un periodo se excluye si su filing_date es posterior a la hora de la barra. Cuando un periodo no tiene un filing_date utilizable, se usa en su lugar una fecha límite de presentación supuesta: 45 días después del fin de periodo en las tablas trimestrales y 90 días en las anuales (default_filing_lag_days), en lugar de hacer visible el informe el día en que cierra su periodo. Las ejecuciones forward usan la elegibilidad por fin de periodo (backtest_mode=False). Prefiere el manejador fundamentals del callback en los backtests del IDE; llamar directamente a qc_fundamentals.get_data_with_offset(...) sin use_filing_date=True puede anticiparse respecto a las fechas de presentación.
Ejecuciones forward: una ejecución en vivo recarga sus datos fundamentales aproximadamente cada hora, y en unos 5 minutos después de que se actualicen los datos del Screener. Una recarga fallida conserva los datos anteriores. Como el "ahora" de una ejecución forward es realmente hoy, los bloques a fecha de la subida (raw["ttm"], raw["valuation"]["latest"], …) son allí datos actuales, no anticipación.
Callbacks heredados: las estrategias antiguas pueden usar un argumento
qc_fundamentalsaparte o un dict bruto en lugar deBacktestFundamentals. La firma moderna pasafundamentalscomo tercer argumento deon_bar/on_tick. El alias a nivel de módulofundamentals_as_of_barcorresponde a la misma forma de carga alineada con las barras.
El parámetro de callback fundamentals
Cuando se cargan los datos fundamentales, el motor pasa un manejador BacktestFundamentals como argumento fundamentals a on_bar, on_tick y (cuando se usa en ejecuciones forward) on_timer:
def on_bar(bar_index, bar, fundamentals=None, symbol=None):
if fundamentals is None:
return
snap = fundamentals.current(bar["t"])
bs_q = (snap.get("balanceSheet") or {}).get("quarterly") or {}
total_assets = bs_q.get("totalAssets")| Método / miembro | Propósito |
|---|---|
fundamentals.current(bar_time, symbol=None) | Dict de instantánea a la hora de esa barra (filtrado por fecha de presentación en backtest). El symbol opcional selecciona qué paquete cargado; omítelo para el principal. Incluye filingHistory cuando está presente en el paquete. |
fundamentals.get_data_with_offset(bar_time, offset, *, symbol=None, print_on_shortfall=True) | Periodo N anterior por subtabla para el paquete elegido (mismo modo de fecha de presentación que current). |
fundamentals.symbols | Tupla de claves en mayúsculas de cada paquete cargado. |
fundamentals.primary_symbol() | Clave principal usada cuando se omite symbol. |
fundamentals.reload_all() | Vuelve a descargar todos los paquetes. Las ejecuciones forward lo llaman por ti; rara vez lo necesitarás. |
Qué aspecto tiene la instantánea
Una instantánea alineada con las barras es un dict anidado con solo los periodos válidos a la hora de esa barra (filtrados por fecha de presentación en los backtests del IDE). Cada sección no nula incluye un periodEnd más las métricas del informe:
{
"barTime": "2026-06-01T00:00:00+00:00",
"symbol": "AAPL",
"balanceSheet": {
"quarterly": { "periodEnd": "2026-03-31", "totalAssets": 352000000.0, "cash": 51000000.0 },
"yearly": { "periodEnd": "2025-09-30", "totalAssets": 344000000.0 }
},
"cashFlow": {
"quarterly": { "periodEnd": "2026-03-31", "freeCashFlow": 24500000.0 }
},
"incomeStatement": {
"quarterly": { "periodEnd": "2026-03-31", "totalRevenue": 95000000.0, "netIncome": 23000000.0 }
},
"earnings": {
"History": { "periodEnd": "2026-03-31", "reportDate": "2026-05-02", "epsActual": 1.53 },
"Trend": null,
"Annual": { "periodEnd": "2025-09-30", "epsActual": 6.13 }
},
"ratios": {
"quarterly": { "periodEnd": "2026-03-31", "grossMargin": 0.47, "operatingMargin": 0.31, "currentRatio": 1.04 },
"yearly": { "periodEnd": "2025-09-30", "grossMargin": 0.46, "currentRatio": 0.87 }
},
"financialsExtended": {
"quarterly": { "periodEnd": "2026-03-31", "ebitda": 38000000000.0, "ebitdaMargin": 0.40 },
"yearly": { "periodEnd": "2025-09-30", "ebitda": 134000000000.0 }
},
"perShare": {
"quarterly": { "periodEnd": "2026-03-31", "bookValuePerShare": 4.3, "grahamNumber": null },
"yearly": null
},
"valuation": {
"quarterly": {
"periodEnd": "2026-03-31",
"marketCap": 3812000000.0,
"priceToEarningsRatio": null,
"earningsYield": -5.0,
"priceBasis": "split-adjusted",
"approximate": true
},
"yearly": null
},
"scores": {
"quarterly": { "periodEnd": "2026-03-31", "piotroskiFScore": 3, "beneishMScore": -1.94 },
"yearly": null
},
"filingHistory": {
"quarterly": { "periodEnd": "2026-03-31", "formType": "10-Q", "filedAt": "2026-05-02" },
"yearly": { "periodEnd": "2025-09-30", "formType": "10-K", "filedAt": "2025-10-31" }
}
}Trend puede ser null cuando ningún periodo cumple en la hora de la barra o antes. El priceToEarningsRatio: null junto a earningsYield: -5.0 de arriba corresponde a una empresa con pérdidas, no a datos ausentes; consulta Valoración.
Nunca en la instantánea: ttm, valuation.latest, scores.notApplicableReason, metricsInputs, metricsHealth, companyInfo. Son a fecha de la subida y no por periodo; adjuntarlos a una barra filtraría información futura a un backtest. Léelos de qc_fundamentals.raw[...].
El mismo dict por barra aparece en el campo fundamentals de cada fila del resultado de backtest estructurado, así que lo que ves en tu estrategia coincide con lo que aparece en los datos del resultado.
Consultar periodos anteriores (get_data_with_offset)
A veces no quieres el último informe a la hora de una barra, sino uno anterior: el trimestre previo, el ejercicio previo, la línea de resultados anterior:
prior = fundamentals.get_data_with_offset(bar["t"], 1)
prev_bs_q = (prior or {}).get("balanceSheet", {}).get("quarterly")Comportamiento:
- Cada subtabla se indexa de forma independiente. Con
offset=1, la secciónbalanceSheet.quarterlyretrocede un trimestre, mientras quebalanceSheet.yearlyretrocede un ejercicio, y así sucesivamente. - Si una subtabla no tiene suficiente historial antes de la barra actual, su sección es
nullen el dict devuelto (y puede imprimirse una nota de una línea). - La forma es la misma que
current(...), más un"offset": <int>de nivel superior. - En la API bruta
QcFundamentals, la firma preferida esf.get_data_with_offset(bar_time, offset, *, print_on_shortfall=True, use_filing_date=False). La función a nivel de móduloget_data_with_offset(qc, bar_time, offset, *, print_on_shortfall=True)no tiene el parámetrouse_filing_date: siempre usa la elegibilidad por fin de periodo, así que llama al método conuse_filing_date=True(o usa el manejador del callback) para datos point-in-time. El valor por defectouse_filing_date=Falsesignifica solo elegibilidad por fin de periodo (puede anticiparse respecto a las fechas de presentación). Conuse_filing_date=True, un periodo cuyofiling_datefalta recurre a una fecha límite supuesta de 45 días (trimestral) / 90 días (anual) tras el fin de periodo. Prefiere el manejadorfundamentalsdel callback en los backtests del IDE, que usa el filtrado por fecha de presentación automáticamente.
Datos fundamentales con varios símbolos
Cuando cargas varios paquetes (para estrategias transversales o de comparación), puedes elegir de cuál leer con symbol="TICKER":
def on_bar(bar_index, bar, fundamentals=None, symbol=None):
if fundamentals is None:
return
primary_snap = fundamentals.current(bar["t"])
msft_snap = fundamentals.current(bar["t"], symbol="MSFT")
aapl_prior = fundamentals.get_data_with_offset(bar["t"], 1, symbol="AAPL")- Omitir
symbolusa el paquete principal: el único cargado; si no,fundamentals.primarysi está definido, si no el símbolo operado, si no el ticker cargado primero por orden alfabético. En una ejecución con varios símbolos o Screener, ese respaldo puede ser en silencio la empresa equivocada: pasa siempresymbol=symbolallí. fundamentals.symbolslista cada clave de ticker en mayúsculas actualmente cargada.fundamentals.primary_symbol()devuelve la clave principal.- El símbolo que operas en el backtest puede ser distinto del o de los símbolos de datos fundamentales que cargas; por ejemplo, operar
SPYmientras lees los datos fundamentales deAAPLyMSFT.
Horas de barra aceptadas
Tanto current(...) como get_data_with_offset(...) aceptan varios formatos de hora para que puedas pasar bar["t"], bar.t[0] o tu propio valor:
datetime(el ingenuo se trata como UTC),date,- cadena ISO (incluida una
Zfinal), - segundos epoch UNIX (
int/float).
Patrones prácticos
Algunas formas habituales:
def on_bar(bar_index, bar, fundamentals=None, symbol=None):
if fundamentals is None:
return
snap = fundamentals.current(bar["t"])
if not snap:
return
bs_q = (snap.get("balanceSheet") or {}).get("quarterly") or {}
is_q = (snap.get("incomeStatement") or {}).get("quarterly") or {}
if (bs_q.get("totalAssets") or 0) > 0 and (is_q.get("netIncome") or 0) > 0:
...def on_bar(bar_index, bar, fundamentals=None, symbol=None):
if fundamentals is None:
return
snap = fundamentals.current(bar["t"]) or {}
prior = fundamentals.get_data_with_offset(bar["t"], 1) or {}
cur = ((snap.get("incomeStatement") or {}).get("quarterly") or {}).get("totalRevenue")
prev = ((prior.get("incomeStatement") or {}).get("quarterly") or {}).get("totalRevenue")
if cur and prev:
revenue_growth = (cur - prev) / prevReferencia de campos de datos fundamentales
La disponibilidad de los campos depende del símbolo: no todos los emisores informan cada línea. Usa
sorted(f.lists.keys())osorted(t.columns.keys())en tiempo de ejecución para ver qué expone realmente un paquete concreto. Los valores numéricos pueden llegar como cadenas; conviértelos confloat(...)para operar.
Balance
Tablas: balanceSheet.quarterly, balanceSheet.yearly
| Campo | Campo |
|---|---|
accountsPayable | longTermInvestments |
accumulatedAmortization | negativeGoodwill |
accumulatedDepreciation | netDebt |
accumulatedOtherComprehensiveIncome | netInvestedCapital |
additionalPaidInCapital | netReceivables |
capitalLeaseObligations | netTangibleAssets |
capitalStock | netWorkingCapital |
capitalSurpluse | noncontrollingInterestInConsolidatedEntity |
cash | nonCurrrentAssetsOther |
cashAndEquivalents | nonCurrentAssetsTotal |
cashAndShortTermInvestments | nonCurrentLiabilitiesOther |
commonStock | nonCurrentLiabilitiesTotal |
commonStockSharesOutstanding | otherAssets |
commonStockTotalEquity | otherCurrentAssets |
currency_symbol | otherCurrentLiab |
currentDeferredRevenue | otherLiab |
date | otherStockholderEquity |
deferredLongTermAssetCharges | preferredStockRedeemable |
deferredLongTermLiab | preferredStockTotalEquity |
earningAssets | propertyPlantAndEquipmentGross |
filing_date | propertyPlantAndEquipmentNet |
goodWill | propertyPlantEquipment |
intangibleAssets | retainedEarnings |
inventory | retainedEarningsTotalEquity |
liabilitiesAndStockholdersEquity | shortLongTermDebt |
longTermDebt | shortLongTermDebtTotal |
longTermDebtTotal | shortTermDebt |
shortTermInvestments | temporaryEquityRedeemableNoncontrollingInterests |
totalAssets | totalCurrentAssets |
totalCurrentLiabilities | totalLiab |
totalPermanentEquity | totalStockholderEquity |
treasuryStock | warrants |
Flujo de caja
Tablas: cashFlow.quarterly, cashFlow.yearly
| Campo | Campo |
|---|---|
beginPeriodCashFlow | endPeriodCashFlow |
capitalExpenditures | exchangeRateChanges |
cashAndCashEquivalentsChanges | filing_date |
cashFlowsOtherOperating | freeCashFlow |
changeInCash | investments |
changeInWorkingCapital | issuanceOfCapitalStock |
changeReceivables | netBorrowings |
changeToAccountReceivables | netIncome |
changeToInventory | otherCashflowsFromFinancingActivities |
changeToLiabilities | otherCashflowsFromInvestingActivities |
changeToNetincome | otherNonCashItems |
changeToOperatingActivities | salePurchaseOfStock |
currency_symbol | stockBasedCompensation |
date | totalCashflowsFromInvestingActivities |
depreciation | totalCashFromFinancingActivities |
dividendsPaid | totalCashFromOperatingActivities |
Cuenta de resultados
Tablas: incomeStatement.quarterly, incomeStatement.yearly
| Campo | Campo |
|---|---|
costOfRevenue | netIncomeFromContinuingOps |
currency_symbol | netInterestIncome |
date | nonOperatingIncomeNetOther |
depreciationAndAmortization | nonRecurring |
discontinuedOperations | operatingIncome |
effectOfAccountingCharges | otherItems |
ebit | otherOperatingExpenses |
ebitda | preferredStockAndOtherAdjustments |
extraordinaryItems | reconciledDepreciation |
filing_date | researchDevelopment |
grossProfit | sellingAndMarketingExpenses |
incomeBeforeTax | sellingGeneralAdministrative |
incomeTaxExpense | taxProvision |
interestExpense | totalOperatingExpenses |
interestIncome | totalOtherIncomeExpenseNet |
minorityInterest | totalRevenue |
netIncome | |
netIncomeApplicableToCommonShares |
Resultados — History
Tabla: earnings.History (BPA publicado frente a estimaciones por fecha de informe)
| Campo | Descripción |
|---|---|
beforeAfterMarket | Cuándo se publicó el informe en relación con el horario de mercado |
currency | Divisa del informe |
date | Fecha de fin de periodo |
epsActual | BPA publicado |
epsEstimate | Estimación de consenso del BPA |
epsDifference | epsActual − epsEstimate |
reportDate | Fecha en que se publicaron las cifras |
surprisePercent | Sorpresa del BPA como porcentaje |
Resultados — Trend
Tabla: earnings.Trend (estimaciones futuras y revisiones)
| Campo | Campo |
|---|---|
date | epsTrendCurrent |
period | epsTrend7daysAgo |
growth | epsTrend30daysAgo |
earningsEstimateAvg | epsTrend60daysAgo |
earningsEstimateLow | epsTrend90daysAgo |
earningsEstimateHigh | epsRevisionsUpLast7days |
earningsEstimateYearAgoEps | epsRevisionsUpLast30days |
earningsEstimateNumberOfAnalysts | epsRevisionsDownLast7days |
earningsEstimateGrowth | epsRevisionsDownLast30days |
revenueEstimateAvg | |
revenueEstimateLow | |
revenueEstimateHigh | |
revenueEstimateYearAgoEps | |
revenueEstimateNumberOfAnalysts | |
revenueEstimateGrowth |
Resultados — Annual
Tabla: earnings.Annual (BPA anual publicado)
| Campo | Descripción |
|---|---|
date | Fecha de fin del ejercicio fiscal |
epsActual | BPA anual publicado |
Ratios
Tablas: ratios.quarterly, ratios.yearly
91 métricas desde la ampliación de métricas (94 claves contando date, currency_symbol y filing_date). Primero se lista el conjunto original; todo lo que va desde Capital de trabajo hacia abajo es nuevo. Un símbolo a mitad de despliegue puede llevar solo el conjunto original, así que descubre la lista real con sorted(f.table("ratios.quarterly").columns.keys()).
Conjunto original
Los campos de margen y rentabilidad de este grupo (
grossMargin,operatingMargin, etc.) son fracciones decimales: multiplica por 100 para obtener un porcentaje.debtToEquityse renombró adebtToEquityRatio.
| Campo | Campo |
|---|---|
grossMargin | currentRatio |
operatingMargin | quickRatio |
netProfitMargin | cashRatio |
returnOnAssets | debtToEquityRatio |
returnOnEquity | debtToAssetsRatio |
operatingCashFlowMargin | interestCoverageRatio |
freeCashFlowMargin | assetTurnover |
freeCashFlowToNetIncome | inventoryTurnover |
receivablesTurnover |
Capital de trabajo
| Campo | Notas |
|---|---|
daysSalesOutstanding | Días, 2 dec. |
daysInventoryOutstanding | Días, 2 dec. |
daysPayablesOutstanding | Días, 2 dec. |
cashConversionCycle | Días, 2 dec. — con signo; un valor negativo (cobrar antes de pagar) es deseable, no un error |
operatingCycle | Días, 2 dec. |
payablesTurnover | Decimal simple |
workingCapitalTurnover | Decimal simple |
fixedAssetTurnover | Decimal simple |
netWorkingCapitalToAssets | Decimal simple |
defensiveIntervalRatio | Decimal simple |
Apalancamiento y cobertura
Todos son decimales simples (4 dec.).
| Campo | Campo |
|---|---|
totalDebtToEquityRatio | netDebtToFreeCashFlowRatio |
netDebtToEquityRatio | equityMultiplier |
longTermDebtToEquityRatio | ebitdaInterestCoverageRatio |
longTermDebtToCapitalRatio | cashFlowInterestCoverageRatio |
capitalizationRatio | cashFlowToDebtRatio |
debtToEbitdaRatio | debtServiceCoverageRatio |
netDebtToEbitdaRatio |
Rentabilidades
| Campo | Notas |
|---|---|
effectiveTaxRate | % |
returnOnInvestedCapital | % |
returnOnCapitalEmployed | % |
returnOnTangibleEquity | % |
cashReturnOnInvestedCapital | % |
operatingReturnOnAssets | % |
returnOnEquityDupontMargin | % |
returnOnEquityDupontTurnover | Decimal simple |
returnOnEquityDupontLeverage | Decimal simple |
nopat | Cadena monetaria, 2 dec. — la excepción en un bloque por lo demás totalmente numérico |
investedCapital | Cadena monetaria, 2 dec. |
capitalEmployed | Cadena monetaria, 2 dec. |
Márgenes e intensidad de capital
| Campo | Notas |
|---|---|
ebitMargin | % |
ebitdaMargin | % |
pretaxMargin | % |
researchAndDevelopmentToRevenue | % |
sellingGeneralAdministrativeToRevenue | % |
stockBasedCompensationToRevenue | % |
capexToRevenue | % |
capexToOperatingCashFlow | % |
accrualsRatio | % |
assetQualityRatio | % |
capexToDepreciationRatio | Decimal simple (4 dec.) |
cashConversionRatio | Decimal simple (4 dec.) |
Reparto
Todos son porcentajes (2 dec.): dividendPayoutRatio, freeCashFlowPayoutRatio, shareholderPayoutToFreeCashFlow, retentionRatio, sustainableGrowthRate.
Crecimiento interanual
Todos son porcentajes (2 dec.). El crecimiento de ingresos / beneficio neto / BPA no se duplica aquí: está en earnings.Trend.
| Campo | Campo |
|---|---|
grossProfitGrowthYoY | totalAssetsGrowthYoY |
operatingIncomeGrowthYoY | totalStockholderEquityGrowthYoY |
ebitdaGrowthYoY | totalDebtGrowthYoY |
operatingCashFlowGrowthYoY | dividendsPaidGrowthYoY |
freeCashFlowGrowthYoY | sharesDilutedGrowthYoY — negativo significa recompras |
capitalExpendituresGrowthYoY | bookValuePerShareGrowthYoY |
TCAC — solo yearly
Todos son porcentajes (2 dec.) y null en cada periodo quarterly: un filtro o una regla que pida uno en un periodo trimestral hace fallar a todos los símbolos.
revenueCagr3y / revenueCagr5y, netIncomeCagr3y / netIncomeCagr5y, epsCagr3y / epsCagr5y, freeCashFlowCagr3y / freeCashFlowCagr5y, dividendCagr3y / dividendCagr5y.
Financials extended
Tablas: financialsExtended.quarterly, financialsExtended.yearly
Los campos varían según el símbolo y no se enumeran aquí. Descubre lo que expone un paquete cargado en tiempo de ejecución:
t = f.table("financialsExtended.quarterly")
if t:
print(sorted(t.columns.keys()))Los campos habituales incluyen métricas de EBITDA extendidas, componentes del capital de trabajo y datos por acción que no están en la cuenta de resultados básica.
Campos retirados:
ebitda,ebitdaMargin,enterpriseValue,priceToEarnings,priceToBook,priceToSales,evToEbitdayevToRevenuese están retirando de Financials extended en favor de las versiones de Valoración y de Ratios, que se calculan sobre los últimos doce meses (por lo que los valores difieren).
Por acción
Tablas: perShare.quarterly, perShare.yearly
Un registro tal como se presentó: sharesOutstanding está sobre la base de split que se informó para ese periodo, así que no es comparable a ambos lados de un split. Usa Valoración para cualquier comparación. Los valores son cadenas de 4 decimales salvo que se indique lo contrario.
| Campo | Notas |
|---|---|
date | Fecha de fin de periodo |
sharesOutstanding | Cadena de 2 decimales |
sharesBasis | "dei" / "weightedAverageSharesDiluted" / "weightedAverageSharesBasic" |
bookValuePerShare, tangibleBookValuePerShare | |
revenuePerShare, ebitdaPerShare | |
operatingCashFlowPerShare, freeCashFlowPerShare | |
cashPerShare, netCashPerShare | |
netDebtPerShare, totalDebtPerShare | |
workingCapitalPerShare, retainedEarningsPerShare | |
dividendsPaidPerShare | |
netCurrentAssetValuePerShare | NCAV de Graham |
grahamNumber |
Valoración
Tablas: valuation.quarterly, valuation.yearly (más el valuation.latest, que no es una tabla)
Tres reglas:
- Los múltiplos son
marketCap / agregado, noprice / perShare. No los recalcules a partir deperShare: los comparativos reexpresados hacen que ambos discrepen en los periodos más antiguos. - Un múltiplo
Nonejunto a un rendimiento con signo es correcto, no un error. Los múltiplos marcados como null con denominador no positivo más abajo pasan aNonecuando su denominador no es positivo, mientras que los rendimientos ybookToMarketRatioconservan su signo. Una empresa con pérdidas muestrapriceToEarningsRatio: NoneyearningsYield: -5.0. - Los múltiplos son de los últimos doce meses, incluso en periodos trimestrales: un PER trimestral es un auténtico PER de los últimos doce meses, no un trimestre anualizado.
Metadatos
| Campo | Notas |
|---|---|
date | Fecha de fin de periodo |
sharePrice | Cadena de 4 decimales |
priceDate | YYYY-MM-DD |
priceLagDays | Entero |
priceBasis | "as-quoted" (último) / "split-adjusted" / "unreconciled" — desconfía de "unreconciled" |
approximate | true en periodos históricos (ajuste retroactivo residual de dividendos) |
sharesRebased | El número de acciones se pasó a la base de split actual |
sharesOutstanding | Cadena de 2 decimales, base de split actual — difiere de perShare.sharesOutstanding (tal como se presentó) en periodos más antiguos |
Tamaño: marketCap, enterpriseValue — cadenas monetarias de 2 decimales.
Múltiplos (números de 4 decimales)
| Campo | Null con denominador no positivo |
|---|---|
priceToEarningsRatio | sí |
priceToBookRatio | sí |
priceToTangibleBookRatio | sí |
priceToSalesRatio | |
priceToFreeCashFlowRatio | sí |
priceToOperatingCashFlowRatio | sí |
pegRatioTrailing | sí |
enterpriseValueToEbitdaRatio | sí |
enterpriseValueToEbitRatio | sí |
enterpriseValueToSalesRatio | |
enterpriseValueToFreeCashFlowRatio | sí |
enterpriseValueToOperatingCashFlowRatio | |
enterpriseValueToInvestedCapitalRatio | |
bookToMarketRatio | conserva su signo |
netDebtToMarketCapRatio | |
marketCapToTotalAssets | |
altmanZScore |
Rendimientos — porcentajes de 2 decimales, con signo: earningsYield, ebitToEnterpriseValueYield, freeCashFlowYield, operatingCashFlowYield, dividendYield, buybackYield, shareholderYield.
valuation.latest — no es un periodo. Un único objeto que lleva todos los campos anteriores más priceAsOf, priceAgeDays, priceSource, fundamentalsAsOf y ttmBasis. Está junto a las claves de fecha, así que no es una entrada de tabla y nunca aparece en una instantánea a la hora de una barra: leerlo en un backtest sería anticipación. Accede a él mediante qc_fundamentals.raw["valuation"]["latest"]; es None cuando no hay precio disponible.
Puntuaciones
Tablas: scores.quarterly, scores.yearly
| Campo | Notas |
|---|---|
date | Fecha de fin de periodo |
piotroskiFScore | Entero de 0 a 9 |
piotroskiComponents | Objeto o None — claves roaPositive, cfoPositive, roaImproved, accrualQuality, leverageImproved, currentRatioImproved, noShareIssuance, grossMarginImproved, assetTurnoverImproved, cada una 1, 0 o None |
altmanZScorePrivate | 4 dec. — Z-prime, patrimonio contable |
beneishMScore | 4 dec. |
beneishComponents | Objeto o None — claves dsri, gmi, aqi, sgi, depi, sgai, tata, lvgi (números de 4 dec.) |
Dos ausencias esperadas, ninguna de las cuales es un error:
- El primer periodo de un declarante no lleva puntuaciones: necesitan un año previo con el que comparar.
- Para los SIC 6000–6799 (bancos, corredurías, aseguradoras, REIT) ambos grupos están vacíos y
scores.notApplicableReasones"financial-sector-sic". Trátalo como "no aplicable", no como "sin datos". Léelo deqc_fundamentals.raw["scores"]["notApplicableReason"].
TTM
ttm es un único objeto, no una tabla: agregados de los últimos doce meses a fecha de la subida, no a fecha de ninguna barra. Nunca aparece en una instantánea; accede a él mediante qc_fundamentals.raw["ttm"] (seguro en ejecuciones forward, anticipación en un backtest).
- Metadatos:
basis("quarterly"/"annual"),asOf,periodsUsed(list[str]),complete(bool),synthetic(bool — se reconstruyó el 4T fiscal; normal, normalmentetrue),coverageDays(unos 365). - Flujos — sumados sobre 4 trimestres, cadenas de 2 decimales salvo
epsBasic/epsDiluted(4 dec.):totalRevenue,grossProfit,operatingIncome,ebit,ebitda,netIncome,epsBasic,epsDiluted,depreciationAndAmortization,interestExpense,incomeBeforeTax,incomeTaxExpense,costOfRevenue,sellingGeneralAdministrative,researchDevelopment,taxProvision,totalCashFromOperatingActivities,totalCashflowsFromInvestingActivities,capitalExpenditures,freeCashFlow,dividendsPaid,stockBasedCompensation,paymentsForRepurchaseOfCommonStock,proceedsFromIssuanceOfCommonStock,repaymentsOfLongTermDebt. - Saldos puntuales — último periodo, nunca sumados, cadenas de 2 decimales:
totalAssets,totalLiab,totalStockholderEquity,totalCurrentAssets,totalCurrentLiabilities,totalDebt,netDebt,cashAndShortTermInvestments,goodWill,intangibleAssets,netWorkingCapital,retainedEarnings,netReceivables,inventory,accountsPayable,propertyPlantAndEquipmentNet,preferredStockTotalEquity,commonStockSharesOutstanding,minorityInterest.
Procedencia de las métricas (metricsInputs / metricsHealth)
Objetos planos que describen de dónde proceden las métricas:
"metricsInputs": {
"metricsVersion": 1,
"priceAsOf": "2026-08-21",
"priceSource": "…" | null, // source of valuation.latest
"historicalPriceSource": "stooq" | null, // source of valuation.quarterly/yearly
"sharesSource": "dei" | "weightedAverageSharesDiluted" | "weightedAverageSharesBasic" | null,
"dividendSource": "nasdaq" | "edgar-xbrl" | "cash-flow" | null,
"ttmBasis": "quarterly" | "annual" | null,
"historicalValuation": true
}
"metricsHealth": {
"prices": "ok" | "stale" | "absent", // current price for valuation.latest
"historicalPrices": "ok" | "absent",
"splits": "ok" | "absent",
"calendar": "ok" | "absent"
}Comprueba metricsHealth["prices"] != "absent" antes de apoyarte en campos basados en precios; "stale" sigue siendo utilizable: compara con priceAsOf. metricsInputs is None significa un paquete anterior a la ampliación de métricas. Los campos aparecen símbolo a símbolo a medida que se vuelve a subir, así que la cobertura es irregular durante un tiempo: trata cada bloque anterior como opcional.
Convenciones de tipos de los bloques de métricas
| Clase | Tipo JSON | Decimales | Ejemplo |
|---|---|---|---|
| Agregados monetarios | cadena | 2 | "4519282704050.00" |
Valores por acción, sharePrice | cadena | 4 | "309.3500" |
| Número de acciones | cadena | 2 | "14608963000.00" |
| Ratios / múltiplos / rotación / cobertura / puntuaciones | número | 4 | 28.0462 |
| Porcentajes (márgenes, rentabilidades, rendimientos, reparto, crecimiento, TCAC, tasa impositiva) | número | 2 | 42.35 significa 42,35 % |
| Días (DSO / DIO / DPO / CCC / ciclo operativo) | número | 2 | 29.2 |
Recuentos (piotroskiFScore, priceLagDays) | número | entero | 8 |
| Fechas | cadena | — | YYYY-MM-DD |
Cada métrica es anulable de forma independiente. Un objeto de periodo se omite por completo cuando todas sus claves que no son metadatos son nulas. Un bloque es {"quarterly": {}, "yearly": {}} cuando está vacío: nunca null, nunca eliminado. NaN / Infinity no aparecen jamás.
Información de la empresa
companyInfo es un objeto plano: no está indexado por fecha y no aparece en las instantáneas current(...) / get_data_with_offset(...). Accede a él directamente:
info = f.raw["companyInfo"]| Campo | Tipo | Notas |
|---|---|---|
entityType | string | null | p. ej. "operating" |
entityName | string | null | Denominación legal de la entidad |
cik | string | null | Clave de índice central de la SEC |
sic | string | null | Código de industria SIC |
sicDescription | string | null | Categoría SIC legible |
stateOfIncorporation | string | null | Código de estado de dos letras |
fiscalYearEnd | string | null | Formato "MMDD", p. ej. "0926" = 26 sept. |
category | string | null | Categoría del declarante |
phone | string | null | Teléfono de contacto |
exchanges | string[] | Códigos de bolsa |
tickers | string[] | Símbolos bursátiles |
businessAddress | object | null | street1, street2, city, stateOrCountry, zipCode |
Notas y trampas
- Protege siempre contra
None. Si los datos fundamentales no están configurados,fundamentalsesNone. Dentro de una instantánea, secciones individuales (p. ej.earnings.Trend,scores) también pueden sernullen algunas barras, y los bloques de la ampliación de métricas pueden faltar por completo en paquetes antiguos. - Pasa siempre
symbol=en ejecuciones con varios símbolos y Screener: el respaldo del paquete principal puede no ser el ticker en el que estás. - Los números pueden ser cadenas. El JSON subyacente suele enviar las métricas numéricas como cadenas; conviértelas con
float(...)al operar. - La indexación de más reciente a más antiguo se aplica a las tablas indexadas por fecha y a las consultas por desplazamiento: el índice
0es el periodo elegible más reciente a la hora de la barra,1el anterior, etc. - La marca de tiempo de la barra es la fuente de verdad para saber qué informe es el "actual": pasa
bar["t"](obar.t[0]) directamente; no necesitas analizarla tú.

