Appearance
Forensic Screening
EqtyTrk's Health Check card computes three academic forensic scores — Altman Z, Piotroski F, and Beneish M — and classifies each company into a risk zone. Together, the three scores cover different failure modes: financial distress (Altman), fundamental deterioration (Piotroski), and earnings quality (Beneish). No single score is sufficient; the three together form a triangulated view of financial health.
Altman Z-Score
Definition
The Altman Z-Score (1968) is a discriminant-analysis model trained to separate manufacturing companies that went bankrupt within two years from those that survived. The model combines five accounting ratios into a single weighted score:
Decomposition
| Variable | Formula | Interpretation |
|---|---|---|
| Working Capital / Total Assets | Short-term liquidity relative to asset base | |
| Retained Earnings / Total Assets | Cumulative profitability (also proxies for age — young firms have low RE) | |
| EBIT / Total Assets | Operating efficiency, unleveraged | |
| Market Value of Equity / Total Liabilities | Market-based solvency cushion | |
| Revenue / Total Assets | Asset utilization (total asset turnover) |
Where:
- Working Capital = Current Assets − Current Liabilities
- EBIT is mapped from EDGAR's
OperatingIncomeLoss(i.e., Operating Income) - Market Value of Equity =
market_capfromcompanies(refreshed on each ingest) - Total Liabilities from
us-gaap:Liabilities - Revenue from the canonical
revenuechain
Thresholds
| Zone | Score | Interpretation |
|---|---|---|
| Safe | > 2.99 | Low predicted bankruptcy risk |
| Gray | 1.81 – 2.99 | Ambiguous; monitor closely |
| Distress | < 1.81 | High predicted bankruptcy risk |
Implementation detail
altman_z_score() requires a non-None, positive market_cap. It also requires positive total assets and positive total liabilities (zero-debt companies produce a degenerate None rather than a misleading extreme). All five accounting inputs must be present; any missing concept returns None (ungradable rather than false positive).
Piotroski F-Score
Definition
The Piotroski F-Score (2000) is a nine-point binary scoring system designed to identify companies with improving fundamentals among high book-to-market (value) stocks. Each of the nine criteria earns one point if met, zero otherwise. The score ranges from 0 to 9.
Decomposition
The nine signals span three categories:
Profitability (4 points)
| Signal | Condition | Interpretation |
|---|---|---|
| P1 | Net Income > 0 | Currently profitable |
| P2 | Operating Cash Flow > 0 | Cash generation positive |
| P3 | ROA improving YoY | Asset returns trending up |
| P4 | OCF > Net Income | Accruals small (cash quality) |
ROA for the signal is computed inline as Net Income / Total Assets (not the averaged version used in the standalone roa() metric).
Leverage and Liquidity (3 points)
| Signal | Condition | Interpretation |
|---|---|---|
| P5 | Long-Term Debt decreased YoY | Deleveraging |
| P6 | Current Ratio improved YoY | Liquidity improving |
| P7 | Shares outstanding not increased YoY | No dilution |
The shares comparison uses _per_share_denominator() at both the current and prior FY end to tolerate companies that switch between weighted-average-diluted and shares-outstanding tagging across filing years.
Operating Efficiency (2 points)
| Signal | Condition | Interpretation |
|---|---|---|
| P8 | Gross Margin improved YoY | Pricing power or cost discipline |
| P9 | Asset Turnover (Revenue/TA) improved YoY | More productive asset base |
Thresholds
| Zone | Score | Interpretation |
|---|---|---|
| Strong | ≥ 7 | Improving fundamentals across the board |
| Mid | 4 – 6 | Mixed signals |
| Weak | ≤ 3 | Broad deterioration |
Note: Piotroski's original paper used 8–9 as "strong" and 0–2 as "weak." EqtyTrk widens the strong zone to ≥ 7 to avoid the card reading "Mid" for companies with eight of nine signals positive. The two boundaries in the frontend code are ≥ 7 for Strong and ≥ 4 for Mid.
Implementation detail
piotroski_f_score() requires the prior fiscal year anchor, resolved via _prior_fy_end("assets", ...). If no prior-year fact exists within a ±60-day window, the function returns None — six of the nine signals require YoY comparisons and cannot be computed without a prior anchor. Signals that depend on balance-sheet items with no prior fact (e.g., P5, P6, P7) default to 0 rather than propagating None to avoid losing the profitability signals.
Beneish M-Score
Definition
The Beneish M-Score (1999) is an eight-variable probabilistic model trained to detect companies that manipulated their reported earnings. The model output is a continuous score; a cutoff of −1.78 separates likely manipulators from companies likely reporting cleanly.
Decomposition
Each index compares this year to the prior year to identify anomalous changes:
| Index | Formula | Anomaly signal |
|---|---|---|
| DSRI | Days sales in receivables rising (revenue pulled forward) | |
| GMI | Gross margin deteriorating | |
| AQI | Asset quality declining (more soft assets) | |
| SGI | Sales growth accelerating (high-growth firms more likely to manipulate) | |
| DEPI | Depreciation rate slowing (extending useful lives) | |
| SGAI | SG&A efficiency deteriorating | |
| LVGI | Leverage increasing | |
| TATA | Total accruals relative to assets (core manipulation proxy) |
Where: AR = Accounts Receivable, GM = Gross Margin, CA = Current Assets, PPE = Net PP&E, TA = Total Assets, DA = Depreciation & Amortization, SGA = SG&A expense, TL = Total Liabilities, NI = Net Income, OCF = Operating Cash Flow.
Thresholds
| Zone | Score | Interpretation |
|---|---|---|
| Flagged (likely manipulator) | > −1.78 | Elevated earnings-manipulation risk |
| Clean | ≤ −1.78 | Consistent with honest reporting |
Implementation detail
beneish_m_score() requires every index to be computable: if any of the eight canonical concepts is absent for either the current or prior year, the function returns None. The function also returns None when any ratio involves division by zero or when an index denominator is non-positive (a ratio of ratios with a zero denominator produces infinite or undefined results that are not meaningful as manipulation signals). This strictness means the M-Score is frequently None for companies in capital-light industries without conventional PPE or SG&A line items.
The TATA index is computed as
Unified Health Check card
The three scores are displayed together in the Health Check card in the Fundamentals bento. The card uses color coding consistent across all three:
- Forest green — favorable zone (Safe / Strong / Clean)
- Neutral gray — ambiguous zone (Gray / Mid)
- Brick red — adverse zone (Distress / Weak / Flagged)
Note the direction reversal for Beneish: a higher M-Score is worse (more likely to be a manipulator), so Flagged maps to brick even though the numeric value is higher.
Limitations
- Manufacturing-firm bias in Altman Z. The original 1968 model was calibrated on manufacturing companies. It tends to produce low scores for asset-light firms (technology, software, professional services) that have high revenue-to-assets ratios but low physical asset bases. Altman later published modified versions for non-manufacturing and private firms; EqtyTrk uses only the original public-company manufacturing variant.
- Value-stock context for Piotroski F. Piotroski designed the F-Score to separate winners from losers within the high-book-to-market population. Applied to growth stocks (low book-to-market), the signals — especially P1 (positive net income) — may penalize early-stage, pre-profitability companies that are otherwise healthy.
- Base rate for Beneish M. Actual earnings manipulation is rare (single-digit percentage of public companies in any given year). Even a well-calibrated model applied to a base rate of ~3% will produce a substantial fraction of false positives at any reasonable sensitivity threshold. A "Flagged" score is a prompt to investigate further, not a confirmed finding of manipulation.
- Lookback only one year. All three scores compare the current FY to the immediately prior FY. Longer deterioration patterns (gradual margin compression over three to five years) are not captured.
- All three return None for some companies. Financial-sector companies (banks, insurance) have fundamentally different balance-sheet structures. The formulas were not designed for them and often produce
Nonedue to degenerate denominators or missing canonical concepts. The card renders "—" for missing scores rather than substituting a misleading value.
Implementation notes
altman_z_score(),piotroski_f_score(),beneish_m_score()insrc/eqtytrk/metrics/ratios.py(forensic scores section)- Threshold constants are encoded in frontend rendering functions
altmanTone(),piotroskiTone(),beneishTone()infrontend/src/components/FundamentalsBento.tsx - Piotroski is displayed as
{score}/9(integer/9 format); Altman and Beneish as two-decimal floats - All three are included in the standard metrics engine output and stored in
company_metrics_cache
References
- Altman, E.I. (1968). "Financial Ratios, Discriminant Analysis and the Prediction of Corporate Bankruptcy." Journal of Finance, 23(4), 589–609.
- Piotroski, J.D. (2000). "Value Investing: The Use of Historical Financial Statement Information to Separate Winners from Losers." Journal of Accounting Research, 38(Supplement), 1–41.
- Beneish, M.D. (1999). "The Detection of Earnings Manipulation." Financial Analysts Journal, 55(5), 24–36.