Systemicalpha

Fundamental: Piotroski F-Score

systemic:core-pfsIndicatorsfunction1 cr

Inputs

NameTypeDescription
Year Lag (4 for quarterly data)integerHow many grid positions back each signal compares against, walked positionally (not by calendar date — see the module description).
Net IncomefloatarrayTrailing-twelve-month net income.
Cash Flow From OperationsfloatarrayTrailing-twelve-month operating cash flow.
Total Assetsfloatarray| Property | Value |
Long-Term Debtfloatarray| Property | Value |
Current Assetsfloatarray| Property | Value |
Current Liabilitiesfloatarray| Property | Value |
Shares Outstandingfloatarray| Property | Value |
Gross ProfitfloatarrayTrailing-twelve-month gross profit.
RevenuefloatarrayTrailing-twelve-month revenue, in dollars (not per-share).

Outputs

NameTypeDescription
F-ScorefloatarrayThe Piotroski fundamental-quality score, 0–9.

The Piotroski F-Score (Joseph Piotroski, 2000) grades a company's fundamental health on a 0–9 scale, built from nine binary tests spanning profitability, leverage/liquidity, and operating efficiency — each comparing the current period against the same period one year (year_lag periods) earlier.

CategorySignals
Profitability (4)ROA positive · Cash flow from operations positive · ROA improved YoY · Accruals (CFO > Net Income)
Leverage & Liquidity (3)Long-term debt ratio improved YoY · Current ratio improved YoY · No new shares issued
Operating Efficiency (2)Gross margin improved YoY · Asset turnover improved YoY

Each test that passes contributes one point.


Interpreting the Score

F-ScoreReading
8 – 9Strong fundamentals
3 – 7Mixed / average
0 – 2Weak fundamentals

Piotroski's own research applied the score within a value-stock universe (high book-to-market) to separate future winners from losers — pair it with a valuation filter for that use case, or use it standalone as a quality screen.


Year-over-Year Mechanics

Every signal compares index i against index i − year_lag, walked positionally across the input grid — it does not look for "the same fiscal quarter a year ago" by date, it looks year_lag positions back. On a quarterly TTM grid (the EDGAR nodes' cadence), year_lag = 4 compares each quarter to four quarters earlier.

This is a deliberate choice: compacting the series down to only its observed (non-null) datapoints before lagging would silently compare against whichever quarter happens to be four observed slots back — the wrong fiscal quarter whenever an intervening quarter is missing. Comparing by raw position instead means a missing quarter costs you that one comparison (both its own score and any later score that would have lagged into it), never a mismatched comparison.

The first year_lag positions of every series have no prior period to compare against and are always null.


Missing Data — All-or-Nothing

The F-Score follows the honest-null doctrine: if any of the nine signals cannot be determined at a position — a missing input at i or at i − year_lag, or a zero/negative denominator — the entire score at that position is null. A partial sum (e.g. "6 out of the 7 determinable signals") would silently change what the 0–9 scale means; the module never does this.

Denominator guards (each requires the value to be strictly positive at both i and i − year_lag): Total Assets (ROA, leverage, and turnover signals), Current Liabilities (current-ratio signal), Revenue (gross-margin and turnover signals).

In live execution the module returns exactly one datapoint — the newest position — which is null when it cannot be determined (including whenever fewer than year_lag datapoints have been served).


The Leverage Signal's Zero-Debt Corner

The long-term-debt signal uses a strict less-than comparison (LTD/TA at i less than at i − year_lag), matching Piotroski's original formulation. If a company carries zero long-term debt in both periods, the ratio is 0 in both — 0 < 0 is false, so this signal scores 0, not 1. A debt-free company does not get free credit here; it needs to demonstrate an actual reduction to earn the point.


Wiring

From Stock: Income and Cash Flow (TTM): ni → Net Income, cfo → Cash Flow from Operations, gp → Gross Profit. From Stock: Balance Sheet (Quarter-End): ta → Total Assets, ltd → Long-Term Debt, ca → Current Assets, cl → Current Liabilities. From Stock: Fundamentals: shr → Shares Outstanding. All already trailing-twelve-month or point-in-time as appropriate. Select the same company on every node — mixing issuers across nodes silently produces a nonsense score.

Build Revenue with a Multiply module: rps (revenue per share) × shr (shares outstanding).

Coverage note: ltd is not published for every covered ticker (it depends on which EDGAR concept the company tags) — the F-Score is null wherever it is unavailable, same as any other missing input.


  • ALTZ / ALTZDP — Altman Z-Score family (bankruptcy risk)
  • GRAHAM — Graham Number (fair-value benchmark)
© 2026 WanoLabs. All rights reservedAlpha build v0.1.5