Skip to content

Latest commit

 

History

History
265 lines (226 loc) · 44.1 KB

File metadata and controls

265 lines (226 loc) · 44.1 KB

Metrics Catalog

This file is the single source of truth for supported pyvalue metrics.

TTM construction (applies to every "TTM" below). Trailing-twelve-month sums resolve a cadence-aware window over the quarterly-table rows: four consecutive quarterly rows (adjacent end-date gaps 70–110 days) or, for half-yearly reporters (EODHD stores them as Q2/Q4 rows), two consecutive half-year rows (gap 150–220 days). The newest row must be within the 400-day freshness window. Histories whose spacing forms neither shape — a reporting hole right below the anchor, a cadence transition — yield no TTM value at all rather than a sum covering more or less than twelve months. Where a TTM pairs two concepts per period (EBITDA's D&A, gross profit's COGS, interest coverage's interest expense), the companion row must exist for every window period on the same end date.

Cadence is per concept, not per filer. The annual fallback below was written for filers with no quarterly statement at all, but a provider can report one concept quarterly and another only annually for the same listing — EODHD's financing block is a common case (SK Hynix 000660.KO carries dividendsPaid in 37 of 61 quarters, none in Q1/Q2 since 2024, beside a complete quarterly income statement). Two consequences:

  • Where a ratio divides two flows and the numerator resolves through the annual cadence, the denominator is pinned to the same fiscal year rather than resolving a trailing window of its own. Dividing an FY total by a quarterly window ending in a different month compares two different twelve- month spans; on SK Hynix that reads 2.24% against a coherent 3.92%.
  • The annual fallback is opted into per metric, in the metrics layer only. Normalization never synthesizes a missing quarterly row from FY − Q3 − Q4: nothing in the data says how to split that residual across the missing quarters, and financial_facts holds only as-filed provider values.

Sign guard (applies to every EBITDA, owner-earnings and interest-coverage metric below). D&A is always a positive add-back and interest expense a positive denominator, but EODHD sometimes reports them negative — sign errors on operating companies (e.g. Argan/AGX FY2026 depreciationAndAmortization = -4,743,000 beside a positive +1,912,000 cash-flow figure; Adobe/ADBE Q1 FY2026 interestExpense = -63,000,000 beside +62/+68/+67/+66M surrounding quarters) and net accretion-of-discount mislabels or scale blow-ups on financials (e.g. SuRo/SSSS cash-flow depreciation -87,445,149,000,000; the worst interest row in the 2026-07 universe is -262.5B). A negative fact for these concepts is treated as unavailable — dropped at read time, never abs()-ed (which would explode the scale-error rows). Concept fallbacks and the TTM-window resolver then engage as if the row were never supplied: D&A falls from DepreciationDepletionAndAmortization to DepreciationFromCashFlow and degrades to NA (EBITDA-family) or a zero add-back (owner earnings); interest coverage recedes to the last clean aligned window (or its cap/FY arbitration). Implemented once in src/pyvalue/metrics/fact_guards.py.

Columns:

  • English Descriptive Name of the Metric
  • pyvalue key
  • How is it calculated
  • Why is it important in identifying quality/value stocks

Liquidity / Balance Sheet

English Descriptive Name of the Metric pyvalue key How is it calculated Why is it important in identifying quality/value stocks
Working Capital working_capital Latest AssetsCurrent - LiabilitiesCurrent. Positive working capital helps a business absorb near-term shocks without forced financing.
Current Ratio current_ratio Latest AssetsCurrent / LiabilitiesCurrent. A business that can comfortably cover short-term obligations is less fragile.
Net Current Asset Value ncav Latest AssetsCurrent - Liabilities (total liabilities, not just current); negative values are emitted. Graham's crudest liquidation proxy: what remains for shareholders after every claim is settled from current assets alone.
Price to NCAV price_to_ncav EODHD-oriented: market_cap / ncav, only when ncav > 0. The Graham net-net test: price_to_ncav <= 0.67 flags stocks trading below two-thirds of liquidation value, the classic deep-value margin of safety.
Net Working Capital (Most Recent Quarter) nwc_mqr EODHD-oriented: (AssetsCurrent - Cash) - (LiabilitiesCurrent - ShortTermDebt) using cash and short-debt fallbacks. Focuses on operating working capital rather than cash hoards or financing noise.
Net Working Capital (Fiscal Year) nwc_fy EODHD-oriented FY version of the same adjusted NWC formula used by nwc_mqr. Gives an annual baseline for working-capital intensity.
Delta Net Working Capital (TTM Style) delta_nwc_ttm EODHD-oriented: NWC(MRQ) - NWC(same fiscal quarter last year) with strict quarter matching. Highlights whether the business is tying up more capital in operations year over year.
Delta Net Working Capital (Fiscal Year) delta_nwc_fy EODHD-oriented: NWC(latest FY) - NWC(prior FY). Shows annual change in operating capital demands.
Net Working Capital Maintenance delta_nwc_maint EODHD-oriented: max(average(last 3 FY deltas of NWC), 0). The FY-series owner-earnings metrics reuse the same rule per fiscal year: maint_nwc_FY(y) is the trailing 3-delta average as of year y, floored at 0, and exists only when NWC points cover y through y-3. Converts multi-year NWC drift into a conservative maintenance drag used in owner-earnings style analysis.

Leverage / Coverage

TotalDebt — one definition, used by every metric below

Providers state debt twice: as components (ShortTermDebt + LongTermDebt) and as a single TotalDebtFromBalanceSheet rollup. They agree on only 24% of listings carrying both. TotalDebt is the larger of the two — the wider scope is the reading that captured more of the balance sheet, most often the finance leases the rollup folds in and the components omit. None (metric NA) when neither is fresh: debt is unknown, not zero.

Taking the larger is the safe direction for a value screen — understated debt shrinks EV and manufactures a cheap-looking yield, while overstated debt only costs an opportunity.

Where an upper bound is allowed instead of NA. enterprise_value and net_debt_to_ebitda fall back to LiabilitiesNoncurrent when no debt row is fresh (balance_sheet.resolve_total_debt_bounded), because both are wrong in a knowable direction when debt is too large: an inflated figure raises EV, lowers every yield built on it, and raises the leverage ratio. The bound can block a gate; it can never clear one. Without it, 5,255 listings lose all three price arms and leave the screen — not because they are expensive but because they are unmeasurable. The substitution is logged at INFO, since the stored metric carries no provenance. short_term_debt_share is excluded and the asymmetry is the point: total debt is its denominator, so a bound understates the share — the flattering direction. long_term_debt, debt_paydown_years and fcf_to_debt are excluded too: there the debt figure is not an input to the conclusion, it is the conclusion.

The rule lives in balance_sheet.broader_debt_reading and is the only place the choice is made; before 2026-08-10 six private copies disagreed, so interest_coverage and enterprise_value could read different debt for the same listing on the same day. Five were merged on 2026-08-10; the sixth — roic_fy_series, which feeds the whole ROIC persistence family and therefore four QARP gates — was found still on the retired components-preferred precedence and merged on 2026-08-11. NetDebt = TotalDebt − cash, and EV-denominated metrics use the same TotalDebt. See MSFT QARP Review for the audit.

English Descriptive Name of the Metric pyvalue key How is it calculated Why is it important in identifying quality/value stocks
Long-Term Debt long_term_debt Latest reported LongTermDebt fact. Reported borrowings only — when the provider nulls its long-term debt fields nothing is stored, and the non-current-liabilities figure that used to be substituted here now lands in LiabilitiesNoncurrent instead. High debt can destroy value when a business hits a downturn or refinancing window.
Short-Term Debt Share short_term_debt_share EODHD-oriented: ShortTermDebt / TotalDebt (see the shared definition above). Because the denominator can no longer be narrower than the numerator, the ratio is bounded by construction; values above one are only reachable through a negative component and are rejected as garbage. Measures refinancing pressure by showing how much debt matures soon.
Debt Paydown Years debt_paydown_years EODHD-oriented: TotalDebt / FCF_TTM (see the shared definition above), where FCF_TTM = OCF_TTM - Capex_TTM. Lower values indicate the balance sheet could be repaired faster with current cash generation.
Free Cash Flow to Debt fcf_to_debt EODHD-oriented reciprocal of debt paydown years: FCF_TTM / TotalDebt. Higher values show stronger debt-service capacity from internally generated cash.
Net Debt to EBITDA net_debt_to_ebitda EODHD-oriented: NetDebt / EBITDA_TTM, where EBITDA_TTM = EBIT_TTM + D&A_TTM and cash/debt use fallback chains. Where no debt row is fresh, debt is bounded above by LiabilitiesNoncurrent (see the shared definition above) rather than resolving NA — overstating debt can only raise this ratio, so the bound blocks the leverage gate rather than clearing it. Annual-only filers (no quarterly income statement) resolve EBITDA_TTM from a single fresh FY row (480-day window) via the resolver's annual cadence; when that path is taken, the net-debt legs widen to the same 480-day window so the balance sheet stays as fresh as the once-a-year income statement. Vendor-EBITDA hole-filler: when the EBIT window resolves but a window period lacks any D&A companion, the vendor-supplied EBITDA line is used instead — accepted only when it is at least the resolved TTM EBIT (a lower figure implies negative D&A, an established provider artifact, and is rejected). A widely used leverage check that compares debt burden to operating cash-earnings power.
Interest Coverage interest_coverage EODHD-oriented: EBIT_TTM / InterestExpense_TTM, with rescue-only fallback from interestIncome - netInterestIncome. Negative interest-expense facts are provider artifacts and are treated as unavailable per the sign guard above (the window recedes to the last clean quarter instead of summing a corrupted denominator). When TTM EBIT is positive and fresh but interest expense is absent, stale, misaligned, or non-positive, the metric emits the documented cap 100.0 instead of NA — but only with fresh no-material-debt evidence: TotalDebt <= 1.0x TTM EBIT (the shared definition above — this cap check and every EV metric now read the same figure). When no debt concept is fresh the check walks an ordered bound ladder, tightest first: LiabilitiesNoncurrent, then total Liabilities; both upper-bound debt, so an inflated bound can only block the cap, never manufacture one. The 1.0x slack absorbs the lease balances EODHD folds into its debt rollup (web-verified debt-free PLTR.US shows 0.29x). Where evidence shows material debt (or is absent) the cap is unsafe, but a levered issuer that dropped its quarterly line often still reports interest annually: the metric then falls back to the same-fiscal-year annual ratio FY EBIT / FY InterestExpense (480-day window; e.g. Hanwha 000880.KO measures 2.64x). This fallback runs only in the material/absent-evidence branches — never where an issuer earns the cap — because annual interest is noise-dominated on small-debt balance sheets (contaminated with FX/financial charges it can imply a triple-digit rate). Only when that annual ratio is also unavailable (no fresh FY interest, no aligned FY EBIT, or a non-positive annual EBIT) does the metric stay NA. The cap is a convention for an economically unbounded ratio, not a measurement; loss-making or stale-EBIT issuers stay NA. Tests whether operating profit comfortably covers financing cost — without excluding the strongest (debt-free) balance sheets from >= screen gates, without letting missing provider data manufacture a pass, and without discarding a usable annual interest line.

Cash Flow / Cash Conversion

English Descriptive Name of the Metric pyvalue key How is it calculated Why is it important in identifying quality/value stocks
CFO to Net Income (TTM) cfo_to_ni_ttm EODHD-oriented: CFO_TTM / NetIncome_TTM, where net income prefers NetIncomeLoss then NetIncomeLossAvailableToCommonStockholdersBasic. Annual-only filers resolve both legs from single fresh FY rows (480-day window) via the annual cadence. High cash conversion suggests reported earnings are backed by real cash generation.
CFO to Net Income (10Y Median) cfo_to_ni_10y_median EODHD-oriented median of CFO_FY / NetIncome_FY over the latest consecutive joint CFO+NI FY chain, capped at 10 years, stopping at the first missing joint year and requiring at least 6 observed years. Loss years (NetIncome_FY <= 0) are skipped — their ratio is sign-ambiguous — and at least ceil(3/5 x chain length) positive-NI points are required (6 on a full 10-year chain, 4 on a 6-year chain): the exact complement of DVG's ni_loss_year_share <= 0.40 gate, so both criteria tolerate the same loss count at every window length. Freshness (480d) and as_of anchor on the latest joint year even when it is a skipped loss year. Shows whether earnings quality is durable across a full cycle, not just one strong year — without letting a single loss year (cyclical trough, one-off writedown) void an otherwise healthy decade; loss years themselves are policed by the stability metrics.
Free Cash Flow Median (5Y FY) fcf_fy_median_5y EODHD-oriented median of latest 5 available FY points, where FCF_FY = OCF_FY - Capex_FY and missing capex is treated as 0. Normalizes free-cash-flow power instead of relying on a single possibly peak year.
Free Cash Flow Negative Years (10Y) fcf_neg_years_10y EODHD-oriented count of years with FCF_FY < 0 across the latest strict 10 consecutive FY window. Frequent negative FCF can indicate weak economics or heavy ongoing reinvestment needs.
Net Income Loss Years (10Y) ni_loss_years_10y Count of years with NetIncome_FY < 0 across the latest strict 10 consecutive FY window, with FY net-income fallback to common-shareholders NI. A quick resilience test: repeated loss years are a warning sign for quality and valuation stability.
Net Income Loss-Year Share (Adaptive 10Y) ni_loss_year_share Share of loss years (NetIncome_FY <= 0 — zero counts as a loss, unlike ni_loss_years_10y's strict < 0) within the latest consecutive FY chain, capped at 10 years, stopping at the first missing year and requiring at least 6 years; freshness (480d) gated on the chain-anchor year. Same FY net-income fallback to common-shareholders NI; stored as a 0..1 fraction. Length-normalized resilience gate: keeps 6-9-year histories screenable while penalizing chronic loss-makers proportionally, so a share threshold keeps one meaning across window lengths.
Accruals Ratio accruals_ratio EODHD-oriented: (NetIncome_TTM - CFO_TTM) / AvgTotalAssets, where AvgTotalAssets uses strict same-quarter prior-year averaging. Lower or negative accruals usually indicate cleaner, cash-backed earnings.
Stock-Based Compensation to Revenue sbc_to_revenue EODHD-oriented: StockBasedCompensation_TTM / Revenues_TTM. Shows how much top-line output is offset by equity compensation and potential dilution.
Stock-Based Compensation to Free Cash Flow sbc_to_fcf EODHD-oriented: StockBasedCompensation_TTM / FCF_TTM, with FCF_TTM = OCF_TTM - Capex_TTM and capex missing treated as 0. Helps judge whether apparent cash generation is being offset by large stock comp.
Free Cash Flow to EBITDA fcf_to_ebitda EODHD-oriented: FCF_TTM / EBITDA_TTM, where FCF_TTM = OCF_TTM - Capex_TTM (missing capex treated as 0) and EBITDA_TTM = EBIT_TTM + D&A_TTM; only when EBITDA_TTM > 0, negative FCF allowed. Both legs resolve from single fresh FY rows (480-day window) via the annual cadence for annual-only filers. Shares the vendor-EBITDA hole-filler (see net_debt_to_ebitda): a D&A-less window period falls back to the vendor EBITDA line when that line is at least the resolved TTM EBIT. Operationalizes Buffett's critique that EBITDA ignores capex: high conversion shows EBITDA is backed by real free cash flow, low or negative conversion flags capital-hungry earnings.

Profitability / Returns

English Descriptive Name of the Metric pyvalue key How is it calculated Why is it important in identifying quality/value stocks
Gross Margin (TTM) gross_margin_ttm (Revenue_TTM - COGS_TTM) / Revenue_TTM, where COGS_TTM prefers normalized CostOfRevenue and falls back to Revenue - GrossProfit; clamped to [-1, 1]. Annual-only filers resolve revenue and its COGS/gross-profit companion from single fresh FY rows (480-day window) via the annual cadence. A high and stable gross margin usually points to pricing power or a structurally advantaged business model.
Operating Margin (TTM) operating_margin_ttm EBIT_TTM / Revenue_TTM. Shows how much revenue survives normal operating costs before financing and tax noise.
Free Cash Flow Margin (TTM) fcf_margin_ttm FCF_TTM / Revenue_TTM, where FCF_TTM = OCF_TTM - Capex_TTM and capex missing is treated as 0. Tests whether accounting profitability is translating into real free cash generation.
Return on Equity (TTM) roe_ttm NetIncome_TTM / AvgCommonEquity, using quarterly same-quarter averaging first and strict FY fallback. Highlights how efficiently management turns common equity into earnings.
Return on Assets (TTM) roa_ttm NetIncome_TTM / AvgTotalAssets, where assets use strict same-quarter prior-year averaging. Helps compare earnings power across firms with different leverage.
Return on Tangible Common Equity (TTM) roetce_ttm NetIncome_TTM / AvgTangibleCommonEquity, where TangibleCommonEquity = CommonEquity - Goodwill - Intangibles with missing goodwill/intangibles treated as 0. Reduces goodwill-driven ROE distortion and is especially useful for acquisitive businesses.
Gross Profit to Assets (TTM) gross_profit_to_assets_ttm (Revenue_TTM - COGS_TTM) / AvgTotalAssets, using the same TTM gross-profit logic as gross_margin_ttm and the accruals-style asset average. Annual-only filers resolve the gross-profit legs via the annual cadence, and the average-assets denominator falls back to a two-point FY average (latest and prior-year balance sheets, 480-day window) when no quarterly assets exist. A strong ratio indicates the asset base is generating a lot of gross economic output before overhead.

Owner Earnings

English Descriptive Name of the Metric pyvalue key How is it calculated Why is it important in identifying quality/value stocks
Owner Earnings Equity (TTM) oe_equity_ttm EODHD-oriented: NI_TTM + D&A_TTM - MCapex_TTM - delta_nwc_maint. Approximates cash earnings available to equity after maintenance reinvestment and working-capital drag.
Owner Earnings Equity (5Y Average) oe_equity_5y_avg EODHD-oriented average of latest 5 available FY points of NI_FY + D&A_FY - MCapex_FY - maint_nwc_FY(y), each year subtracting its own trailing 3-delta maintenance NWC (see delta_nwc_maint); a year without that chain yields no point, so up to 8 consecutive FY of NWC history is needed. Smooths owner earnings over multiple years to reduce one-year noise.
Owner Earnings Enterprise (TTM) oe_ev_ttm EODHD-oriented: NOPAT_TTM + D&A_TTM - MCapex_TTM - delta_nwc_maint, where NOPAT_TTM = EBIT_TTM * (1 - tax_rate). Gives an unlevered owner-earnings view that is less distorted by capital structure.
Owner Earnings Enterprise (5Y Average) oe_ev_5y_avg EODHD-oriented average of latest 5 available FY points of NOPAT_FY + D&A_FY - MCapex_FY - maint_nwc_FY(y), each year subtracting its own trailing 3-delta maintenance NWC (see delta_nwc_maint); a year without that chain yields no point, so up to 8 consecutive FY of NWC history is needed. Normalizes enterprise owner earnings across the cycle.
Owner Earnings Enterprise Median (5Y FY) oe_ev_fy_median_5y EODHD-oriented median of latest 5 available FY enterprise owner-earnings points using the same FY OE formula as oe_ev_5y_avg (per-year maintenance NWC included). Median is more robust than an average when one year is abnormally high or low.
Worst Owner Earnings Enterprise Year (10Y) worst_oe_ev_fy_10y EODHD-oriented minimum FY enterprise owner-earnings point over the latest strict 10 consecutive FY window; each point subtracts its own per-year maintenance NWC, so the strict window needs up to 13 consecutive FY of NWC history. A direct bad-year stress test: it shows what the business looked like in its weakest decade year.

EV / Valuation

English Descriptive Name of the Metric pyvalue key How is it calculated Why is it important in identifying quality/value stocks
Market Capitalization market_cap Computed on demand: the resolved company-total share count x the latest market_data price, so it floats with every price refresh. Shares come from the shared resolver (metrics.share_resolver): the SharesStats snapshot vs the filing-based count, arbitrated by ProviderMarketCapitalization ÷ the close nearest its date (the snapshot is per-class for dual-class issuers; the filing rows are weighted-average/issued for others). Size matters for liquidity, survivability, and practical investability.
Earnings Yield earnings_yield EPS_TTM / latest price. A simple inverse-PE view of how much earnings you get per dollar paid.
PEG Ratio peg_ratio EODHD-oriented: (price / EPS_TTM) / (100 x g), where g is the Graham smoothed CAGR shared with graham_eps_10y_cagr_3y_avg; only when TTM EPS, price, and growth are all positive. Lynch's growth-at-a-reasonable-price yardstick: PEG < 1 flags a multiple more than covered by earnings growth.
PEG Ratio (Dividend-Adjusted) peg_ratio_div_adj EODHD-oriented: (price / EPS_TTM) / (100 x (g + dividend_yield_ttm)); missing dividend data credits zero yield, and the combined growth+yield must be positive. Lynch's refinement for slower growers with fat payouts: total return (growth plus yield) is what has to cover the multiple.
Price to Free Cash Flow price_to_fcf Latest market cap divided by FCF_TTM, where FCF_TTM = OCF_TTM - Capex_TTM. Useful when accounting earnings understate or distort cash generation.
Graham Multiplier graham_multiplier (Price / TTM EPS) * (Price / TBVPS); the TBVPS share denominator uses the same company-total share resolver as market_cap. Enforces discipline against overpaying for both earnings and balance-sheet value.
Price to Book price_to_book EODHD-oriented: price / BVPS, where BVPS = CommonEquity / SharesOutstanding; common equity prefers derived CommonStockholdersEquity with StockholdersEquity fallback, and shares come from the same company-total resolver as market_cap (so a dual-class issuer's BVPS divides by all classes, not the listed class alone); only when equity, shares, and price are positive. Graham's balance-sheet criterion and the academic HML value factor: paying below accounting net worth builds in a margin of safety.
Price to Tangible Book price_to_tangible_book EODHD-oriented: price / TBVPS, where tangible book = common equity − GoodwillIntangibleAssetsNetExcludingGoodwill (missing treated as 0) and shares come from the same company-total resolver as price_to_book; only when tangible equity is positive. Strips acquisition goodwill and intangibles from book value, pricing only assets that tend to hold value in liquidation or distress.
Owner Earnings Yield on Equity (TTM) oey_equity EODHD-oriented: oe_equity_ttm / market_cap. Values the business against a maintenance-adjusted equity cash-earnings proxy.
Owner Earnings Yield on Equity (5Y) oey_equity_5y EODHD-oriented: oe_equity_5y_avg / market_cap. Pairs current equity value with a normalized owner-earnings baseline.
Owner Earnings Yield on EV (TTM) oey_ev EODHD-oriented: oe_ev_ttm / EV, where EV is always computed as market cap + total debt − cash. Debt and cash resolve through the same chains and 400d freshness gate as net_debt_to_ebitda (TotalDebt per the shared definition under Leverage / Coverage; CashAndShortTermInvestments, else CashAndCashEquivalents plus optional ShortTermInvestments), so a listing carries an EV exactly when it carries a net-debt position; this EV policy applies to every EV-denominated metric below. A capital-structure-neutral owner-earnings yield.
Owner Earnings Yield on EV (Normalized) oey_ev_norm EODHD-oriented: oe_ev_fy_median_5y / EV, using the same EV denominator policy as oey_ev. Helps avoid buying a business on peak recent owner earnings.
EBIT Yield on EV ebit_yield_ev EODHD-oriented: EBIT_TTM / EV. A simple enterprise earnings-yield lens before owner-earnings refinements.
Free Cash Flow Yield on EV fcf_yield_ev EODHD-oriented: FCF_TTM / EV. Shows how much enterprise value is backed by trailing free cash flow.
EV to EBIT ev_to_ebit EODHD-oriented: EV / EBIT_TTM, only when EBIT_TTM > 0. Annual-only filers resolve EBIT_TTM from a single fresh FY row (480-day window) via the annual cadence; the EV's debt/cash legs then widen to the same window (market cap is a live price, always fresh). A practical operating multiple that compares companies independent of capital structure.
EV to EBITDA ev_to_ebitda EODHD-oriented: EV / EBITDA_TTM, where EBITDA_TTM = EBIT_TTM + D&A_TTM, only when positive. Shares the vendor-EBITDA hole-filler (see net_debt_to_ebitda): a D&A-less window period falls back to the vendor EBITDA line when that line is at least the resolved TTM EBIT. A common acquisition-style multiple that uses operating cash-earnings proxy.
EV to Sales ev_to_sales EODHD-oriented: EV / Revenues_TTM, only when revenue is positive. Annual-only filers resolve Revenues_TTM from a single fresh FY row (480-day window) via the annual cadence; the EV's debt/cash legs then widen to the same window. Values the enterprise against top-line output, staying usable for margin-trough cyclicals and temporarily unprofitable businesses where EV/EBIT is undefined.

ROIC / Capital Efficiency

The one place a debt bound may stand in for measured debt

Invested capital needs a debt leg for every fiscal period in its window, and providers null all three debt fields for a period rather than reporting a zero. One such gap voids the whole strict 10-year ROIC chain — removing the fabricated LongTermDebt on 2026-08-10 cost the strict-10Y gates ~6,000 listings, including businesses with no borrowings at all (PayPal reported none in FY2015–FY2016).

So the two per-period invested-capital chains — ic_mqr / ic_fy / avg_ic, and the FY series behind every roic_* and iroic_5y metric — and only they, fall back to that period's LiabilitiesNoncurrent when no debt row exists. Reading the gap as zero was rejected on evidence: EODHD does emit explicit zeroes for genuinely debt-free periods (141k LongTermDebt and 88k ShortTermDebt rows are exactly 0), so an absent row means unreported, and on a 1,457-period sample the nearest reported debt exceeded 20% of that period's total liabilities in 48.8% of cases.

The substitution is safe here because the error direction is one-way: non-current liabilities bound borrowings from above, so the bound can only inflate invested capital and therefore only depress every return computed from it. It can cost a company a ROIC gate or a ranking place; it can never win one. No metric that reports a debt figure to a reader may do this — TotalDebt above stays measured-only, and the containment is test-pinned in tests/regression/test_invested_capital_noncurrent_liabilities_bound.py and tests/regression/test_roic_fy_series_shares_the_debt_rule.py.

English Descriptive Name of the Metric pyvalue key How is it calculated Why is it important in identifying quality/value stocks
Invested Capital (Most Recent Quarter) ic_mqr EODHD-oriented: latest quarterly TotalDebt + TotalEquity - Cash, with debt/equity/cash fallback chains. A period carrying no debt row at all uses LiabilitiesNoncurrent as a documented upper bound (see above) rather than dropping the period. Gives a direct snapshot of operating capital committed to the business.
Invested Capital (Fiscal Year) ic_fy EODHD-oriented FY version of the same invested-capital formula used by ic_mqr. Useful as an annual anchor for capital-efficiency analysis.
Average Invested Capital avg_ic EODHD-oriented: (IC_now + IC_same_quarter_last_year) / 2, with strict FY fallback when quarter pairing is unavailable. Smooths balance-sheet timing noise for return-on-capital metrics.
ROIC (TTM) roic_ttm EODHD-oriented: NOPAT_TTM / avg_ic, where NOPAT_TTM = EBIT_TTM * (1 - effective_tax_rate). Measures current after-tax operating efficiency on invested capital.
ROIC 10Y Median roic_10y_median EODHD-oriented median of strict 10 FY ROIC values from 10 consecutive FY invested-capital points: each year averages current and prior FY invested capital, except the oldest year of the observable IC history (and only that year), which uses its own end-of-FY level — no prior balance sheet exists at the history boundary, and end-of-FY IC biases the boundary ROIC low for a growing business. Mid-history IC holes still fail. A year whose average invested capital is non-positive fails (the ratio is undefined at or below a zero capital base and would sign-flip) — it is never emitted as a point. Captures central tendency of long-cycle capital efficiency.
ROIC 7Y Median roic_7y_median EODHD-oriented median of strict 7 FY ROIC values from 7 consecutive FY invested-capital points (history-boundary and non-positive-IC conventions as for roic_10y_median). A shorter-horizon coverage alternative when the 10Y window is too sparse but you still want strict history.
ROIC Median (Adaptive 10Y) roic_10y_median_adaptive EODHD-oriented median FY ROIC over the latest consecutive chain of valid ROIC years, capped at 10 and requiring at least 6 (= 6 FY years under the history-boundary IC convention); the chain stops at the first failed or missing year, and freshness (480d) gates on the chain anchor. Same per-year ROIC construction (and non-positive-IC year rule) as roic_10y_median. Coverage-friendly capital-efficiency gate for the DVG screen: 6-9-year histories stay screenable, with the same 6-year evidence floor as the screen's other adaptive gates. QARP keeps the strict roic_7y_median.
ROIC Years Above 12% (10Y) roic_years_above_12pct EODHD-oriented count of strict-10Y FY ROIC values > 12%. Tests persistence of strong returns rather than just average level.
ROIC 10Y Minimum roic_10y_min EODHD-oriented minimum FY ROIC in the latest strict 10-year window. Requires the same strict 10-year ROIC chain as roic_10y_median (10 FY invested-capital points, history-boundary convention included). A resilience check for how bad capital efficiency got in weak years.
ROIC 7Y Minimum roic_7y_min EODHD-oriented minimum FY ROIC in the latest strict 7-year window. A shorter-horizon downside check that preserves strict consecutive FY semantics.
Incremental ROIC (5Y) iroic_5y EODHD-oriented: DeltaNOPAT_5Y / DeltaIC_5Y when DeltaIC is positive and above a 1%-of-capital materiality floor. When NOPAT grew but DeltaIC sits at or below the floor (including outright shrinkage) — the capital-light growth shape (buyback-heavy compounders, asset-lightening businesses) — the metric emits the documented cap 1.0 (100%) instead of NA. The cap is a convention for an economically unbounded ratio, not a measurement (QARP's ranking clips it at 0.50); non-growing NOPAT on flat/shrinking capital stays NA. Tests whether incremental capital deployed actually created incremental operating profit — without excluding businesses that grew profit while releasing capital.
Greenblatt ROC (5Y Average) roc_greenblatt_5y_avg Average over up to 5 FY of EBIT / TangibleCapital, where tangible capital is based on net PPE and working-capital components. Highlights businesses that earn well on the tangible capital they require.
Return on Capital Employed roce EODHD-oriented: EBIT_TTM / AvgCapitalEmployed, where capital employed = Assets - LiabilitiesCurrent averaged same-quarter-prior-year with strict prior-FY fallback; negative EBIT is emitted as a negative return. Fundsmith's headline quality test: pre-tax operating return on all capital tied up in the business, comparable across capital structures and alongside roic_ttm.
Cash Return on Invested Capital croic EODHD-oriented: FCF_TTM / avg_ic, using the standard FCF policy (OCF_TTM - Capex_TTM, missing capex treated as 0) over the same averaged invested capital as roic_ttm; negative FCF is emitted as a negative return. The Smith/Akre cash lens on capital efficiency: a persistent CROIC-vs-ROIC gap exposes accrual-heavy earnings or capex hunger that NOPAT-based returns miss.
Greenblatt ROE (5Y Average) roe_greenblatt_5y_avg Average over up to 5 FY of net income available to common divided by average common equity. Sustained high equity returns can point to good economics if leverage is controlled.
Maintenance Capex (FY) mcapex_fy EODHD-oriented proxy: min(Capex_FY, 1.1 * D&A_FY) with single-input fallback and absolute-value handling. Estimates recurring reinvestment needs rather than headline capex alone.
Maintenance Capex (5Y Average) mcapex_5y EODHD-oriented average of latest 5 available mcapex_fy values. Smooths capital-spending noise when normalizing free cash flow or owner earnings.
Maintenance Capex (TTM) mcapex_ttm EODHD-oriented TTM version of the same maintenance-capex proxy. Useful when evaluating recent owner earnings and cash flow quality.

Margin Stability / Quality

English Descriptive Name of the Metric pyvalue key How is it calculated Why is it important in identifying quality/value stocks
Gross Margin Standard Deviation (10Y) gm_10y_std EODHD-oriented population standard deviation of FY gross margin over the latest strict 10 consecutive FY years. Lower variability suggests more stable economics and easier valuation work.
Operating Margin Standard Deviation (10Y) opm_10y_std EODHD-oriented population standard deviation of FY operating margin over the latest strict 10 consecutive FY years. Stable operating margins usually indicate a more predictable business.
Operating Margin Minimum (10Y) opm_10y_min EODHD-oriented minimum FY operating margin in the latest strict 10-year window. Shows how bad operating profitability got in the toughest observed year.
Operating Margin Minimum (7Y) opm_7y_min EODHD-oriented minimum FY operating margin in the latest strict 7-year window. A shorter-horizon bad-year check that preserves strict consecutive FY semantics.

Share Count / Capital Allocation

English Descriptive Name of the Metric pyvalue key How is it calculated Why is it important in identifying quality/value stocks
Share Count CAGR (5Y) share_count_cagr_5y Uses point-in-time outstanding shares only: ((Shares_t / Shares_t-5)^(1/5)) - 1, preferring MRQ then falling back to FY. Flags more recent dilution or buyback behavior that may matter more than decade-old capital allocation.
Share Count CAGR (10Y) share_count_cagr_10y Uses point-in-time outstanding shares only: ((Shares_t / Shares_t-10)^(1/10)) - 1, preferring MRQ then falling back to FY. Long-run dilution or shrinkage materially changes per-share value compounding.
Share Count Percentage Change (10Y) shares_10y_pct_change Exact 10-year point-in-time share-count change: (Shares_t / Shares_t-10) - 1, using the same pairing rules as share_count_cagr_10y. Gives a direct measure of dilution or buyback behavior over a decade.
Net Buyback Yield net_buyback_yield EODHD-oriented: primary -TTM(SalePurchaseOfStock) / market_cap, with issuance-only fallback and 1Y share-count fallback. Annual-only filers resolve the financing cash flow from a single fresh FY row (480-day window) via the annual cadence; the year-over-year share-count fallback is already FY-based. Captures whether management is shrinking or diluting the share base in value-relevant terms.

Shareholder Returns / Distribution

English Descriptive Name of the Metric pyvalue key How is it calculated Why is it important in identifying quality/value stocks
Dividend Yield (TTM) dividend_yield_ttm Primary abs(CommonStockDividendsPaid_TTM) / market_cap; fallback CommonStockDividendsPerShareCashPaid / latest price when the cash-dividend path is unavailable. Annual-only filers resolve the cash-dividends leg from a single fresh FY row (480-day window) via the annual cadence. Evidenced non-payers measure 0: when both dividend reads miss, no fresh nonzero dividends-paid row exists, and the operating-cash-flow TTM window resolves (statements are current), the yield is 0 rather than NA — a fresh cash-flow statement without a dividends line is affirmative evidence of a zero payout. Separates actual cash returned to owners from forward-looking provider yield fields; a non-payer has a yield of exactly 0, and the old NA silently voided shareholder_yield_ttm for every non-payer.
Shareholder Yield (TTM) shareholder_yield_ttm dividend_yield_ttm + net_buyback_yield, emitted only when both inputs are available. Both legs opt into the annual cadence, so an annual-only filer with FY dividends and FY financing cash flow is measured. Combines cash dividends and buybacks into one capital-allocation return measure.
Dividend Payout Ratio (TTM) dividend_payout_ratio_ttm abs(CommonStockDividendsPaid_TTM) / NetIncome_TTM, only when NetIncome_TTM > 0. The dividends leg resolves the window — it is the scarce one, so it decides which twelve months the ratio describes — and net income is the companion. Where dividends survive only as an FY row, the window resolves through the annual cadence (480-day freshness) and net income is then pinned to that same fiscal year via an FY companion; no aligned FY net income means NA rather than a cross-cadence ratio. On the quarterly and semi-annual paths net income resolves its own window, unchanged. Evidenced non-payers measure 0: with positive TTM net income, no fresh nonzero dividends-paid row, and a resolving operating-cash-flow TTM window, the payout is 0 rather than NA (same zero-payout inference as dividend_yield_ttm). Loss periods stay NA — a payout ratio is undefined without positive earnings. Flags whether the dividend is comfortably covered by trailing earnings; a profitable non-payer retains everything, which is a measured 0, not missing data. Annually-reported dividends (EODHD's financing block is often quarterly-incomplete) no longer void the metric — SK Hynix 000660.KO measures 3.92% off its FY2025 pair.

Growth / Compounding

English Descriptive Name of the Metric pyvalue key How is it calculated Why is it important in identifying quality/value stocks
Revenue CAGR (10Y) revenue_cagr_10y Strict FY endpoint CAGR: ((Revenue_FY0 / Revenue_FY-10)^(1/10)) - 1. Long-run sales compounding is a basic test of market opportunity and business relevance.
Free Cash Flow per Share CAGR (10Y) fcf_per_share_cagr_10y Strict FY endpoint CAGR of (FCF_FY / SharesOutstanding_FY), where FCF_FY = OCF_FY - Capex_FY. Documented basis deviation: the per-share divisor is period-end CommonStockSharesOutstanding, not weighted-average diluted shares — EODHD never supplies a weighted diluted count (the mapped concept has zero rows), and the outstanding series is split-adjusted, so both endpoints share one consistent basis. Filters out growth that came from dilution rather than improving per-share economics.
Owner Earnings CAGR (10Y) owner_earnings_cagr_10y EODHD-oriented enterprise owner-earnings CAGR over an adaptive chain of 7–10 consecutive FY OE points anchored at the latest FY (each point subtracts its own per-year maintenance NWC, so the 7-point floor corresponds to exactly 10 consecutive FY of fundamentals — the same maturity bar as the strict-10y gates), with 3-year average endpoints and a 1/(points - 3) exponent (1/7 on a full chain), mirroring the Graham-style EPS CAGR approach. Both endpoint 3-year averages must be strictly positive — a compound growth rate has no real solution from a non-positive base — but a single loss year inside an otherwise positive window no longer voids the metric (loss-year exclusion belongs to ni_loss_years_10y / ni_loss_year_share). Tests whether maintenance-adjusted operating cash earnings are compounding over time, not just reported accounting profit.

Screening Utility / Misc

English Descriptive Name of the Metric pyvalue key How is it calculated Why is it important in identifying quality/value stocks
EPS Streak eps_streak Counts consecutive FY periods with positive diluted EPS. Basis caveat: EODHD's EarningsPerShare derives from the Earnings section's epsActual — analyst-adjusted, not GAAP — so the streak can stay positive across GAAP loss years (PLTR 2020-2022). For GAAP earnings stability use ni_loss_years_10y / ni_loss_year_share; no shipped screen gates on this metric. Persistent profitability on the adjusted (analyst) basis; a complementary signal, not a GAAP stability test.
EPS (TTM) eps_ttm Cadence-aware trailing-twelve-month EPS: the shared TTM window resolver sums the latest four quarterly (or two semi-annual) EPS values anchored on the newest reported quarter, with a recent-FY fallback when no window forms. EODHD's unreported-quarter epsActual: 0 placeholders are dropped at normalization, so they can no longer anchor the window (2026-07 audit P4). A quick recent earnings-power view used in valuation and screen rules.
EPS 6Y Average eps_6y_avg Average of the latest six FY EPS values. Smooths cyclicality and provides a normalized per-share earnings baseline.
Graham EPS CAGR (10Y, 3Y Average Endpoints) graham_eps_10y_cagr_3y_avg 10-year EPS CAGR using 3-year average EPS at both the start and end of the measurement window. Rewards long-run earnings compounding while reducing endpoint noise.
Altman Z-Score altman_z EODHD-oriented classic 1968 score: 1.2*(WC/TA) + 1.4*(RetainedEarnings/TA) + 3.3*(EBIT_TTM/TA) + 0.6*(MarketCap/TL) + 1.0*(Revenues_TTM/TA); stocks from the latest balance sheet, flows TTM with FY fallback; all five factors required. The standard bankruptcy / value-trap filter, calibrated for public manufacturers: Z < 1.81 flags distress, Z > 2.99 the safe zone -- essential when screening statistically cheap stocks.
Piotroski F-Score piotroski_f_score EODHD-oriented canonical 9-signal score, FY t vs t-1 with beginning-of-year asset denominators (needs 3 consecutive FY balance sheets): profitability (ROA > 0, CFO > 0, dROA > 0, CFO > NI), leverage/liquidity (LTD/avgAssets down or debt-free, current ratio up, no dilution), efficiency (gross margin up, asset turnover up). Strict: all 9 computable or no score; missing LongTermDebt counts as zero debt. The canonical quality gate for cheap stocks (Piotroski 2000, ~+7.5%/yr on high book-to-market): piotroski_f_score >= 7 separates recovering value from value traps.