Piotroski F-Score in Excel: Build the 9-Point Screener (2026)
Joseph Piotroski's 2000 University of Chicago paper found that a simple 9-signal score, applied to high book-to-market stocks, would have generated 7.5% annual excess returns between 1976 and 1996 — with the top-quintile firms outperforming the bottom quintile by 23% per year. Twenty-five years later, the Piotroski F-Score in Excel is still one of the most cited fundamental screeners on Wall Street, precisely because it converts nine accounting tests into a single 0–9 number that any analyst can compute from a 10-K.
This guide walks you through building the F-Score from scratch in Excel — the exact inputs, the nine formulas, the thresholds, and the screening workflow — using nothing more than income statement, balance sheet, and cash flow line items. By the end, you will have a template you can point at any ticker.
What Is the Piotroski F-Score?
The Piotroski F-Score is a 0-to-9 measure of financial strength built from nine binary signals across three categories: profitability, leverage/liquidity/source of funds, and operating efficiency. Each signal that "passes" scores 1, each that "fails" scores 0. Firms scoring 8–9 are historically the strongest; 0–2 are the weakest.
The score was designed as a filter on top of value screens — Piotroski applied it to firms in the highest book-to-market quintile — where roughly 44% of names are what he called "financial losers." The F-Score's job is to separate the value stocks that are cheap because they are recovering from the ones that are cheap because they are dying.
ℹ️ Note: The F-Score is a fundamental strength score, not a bankruptcy predictor. For distress prediction, use the Altman Z-Score in Excel instead. The two are complementary — many analysts run both.
The 9 Signals at a Glance
| # | Category | Signal | Passes When |
|---|---|---|---|
| 1 | Profitability | Return on Assets (ROA) | ROA > 0 |
| 2 | Profitability | Cash flow from operations (CFO) | CFO > 0 |
| 3 | Profitability | Change in ROA | ROA(t) > ROA(t-1) |
| 4 | Profitability | Accruals | CFO > Net Income |
| 5 | Leverage | Change in long-term debt / assets | Ratio(t) < Ratio(t-1) |
| 6 | Liquidity | Change in current ratio | Ratio(t) > Ratio(t-1) |
| 7 | Source of funds | Change in shares outstanding | Shares(t) ≤ Shares(t-1) |
| 8 | Efficiency | Change in gross margin | Margin(t) > Margin(t-1) |
| 9 | Efficiency | Change in asset turnover | Turnover(t) > Turnover(t-1) |
The sum is the F-Score. Piotroski's original rule: long the top quintile (F ≥ 8), short the bottom (F ≤ 1).
How Do You Calculate the Piotroski F-Score in Excel?
To calculate the Piotroski F-Score in Excel, enter two years of financial statement line items in a structured range, compute the nine ratios and their year-over-year changes using SUM, IF, and simple arithmetic, then sum the nine 0/1 binary results with a single SUM or SUMPRODUCT formula. Total time to set up: about 20 minutes per ticker.
Here is the workflow at a glance:
graph TD
A[Pull 10-K/10-Q line items] --> B[Enter Y-1 and Y financials]
B --> C[Compute 4 profitability tests]
B --> D[Compute 3 leverage/liquidity/share tests]
B --> E[Compute 2 efficiency tests]
C --> F[Sum 9 binary flags]
D --> F
E --> F
F --> G{F-Score 0-9}
G -->|8-9| H[High quality — long candidate]
G -->|3-7| I[Middle — no signal]
G -->|0-2| J[Weak — avoid or short]
Piotroski F-Score decision flow: nine accounting signals summed into a 0–9 strength grade with long/short thresholds.
Setting Up the Excel Template
Create three sheets: Inputs, Signals, and Score. On the Inputs sheet, lay out two columns — one for the prior fiscal year (Y-1) and one for the current fiscal year (Y). You need the following line items (all from the 10-K, values in millions):
Y-1 Y
Total Assets A5 B5
Total Long-Term Debt A6 B6
Current Assets A7 B7
Current Liabilities A8 B8
Common Shares Outstanding A9 B9
Revenue A10 B10
Cost of Goods Sold A11 B11
Net Income A12 B12
Cash Flow from Operations A13 B13
That's nine input rows. Everything else is derived.
💡 Pro Tip: Use average total assets —
(A5+B5)/2— as the denominator for ROA and asset turnover. Piotroski's paper uses beginning-of-year assets, but most modern implementations use averages to reduce noise from mid-year acquisitions and divestitures. Pick one convention and document it.
The 9 Formulas in Excel
Below are the exact formulas. Each returns 1 (pass) or 0 (fail). Sum them at the end.
Signal 1 — Return on Assets (ROA > 0)
=IF(B12/((A5+B5)/2)>0, 1, 0)
Net income divided by average total assets. Positive earnings on the asset base is the most basic profitability hurdle.
Signal 2 — Operating Cash Flow (CFO > 0)
=IF(B13>0, 1, 0)
Positive operating cash flow. This catches firms that are earnings-positive on paper but burning cash operationally — a common red flag Piotroski found useful for identifying imminent underperformers.
Signal 3 — Change in ROA
=IF((B12/((A5+B5)/2)) > (A12/A5), 1, 0)
Current-year ROA must exceed prior-year ROA. Note the denominator for Y-1 ROA uses only A5 because you would have used the average of A5 and the year before it — which we do not have here. If you have three years of assets, extend the model; otherwise the single-year denominator is the standard simplification.
Signal 4 — Accruals (CFO > Net Income)
=IF(B13>B12, 1, 0)
This is the quality-of-earnings check. When CFO exceeds net income, earnings are backed by cash. When it doesn't, the delta is accruals — which can be manipulated. Piotroski singled this out as one of the highest-signal tests.
⚠️ Warning: The accrual test is where accounting shenanigans surface. A firm that consistently reports net income above CFO may be pulling revenue forward, capitalizing costs, or under-provisioning for bad debt. Cross-check with the Beneish M-Score if this signal fails.
Signal 5 — Change in Leverage
=IF((B6/((A5+B5)/2)) < (A6/A5), 1, 0)
Long-term debt over average total assets should decrease year over year. Piotroski's logic: firms that increase leverage during a distressed period are signaling weakness — healthy recoverers deleverage.
Signal 6 — Change in Current Ratio
=IF((B7/B8) > (A7/A8), 1, 0)
Current assets divided by current liabilities. Improving short-term liquidity is a positive signal — the firm can meet near-term obligations.
Signal 7 — Change in Shares Outstanding
=IF(B9<=A9, 1, 0)
No net share issuance. Firms in distress often raise equity at depressed prices, diluting existing shareholders. A flat or declining share count means the recovery is self-funded.
Example: A specialty retailer reports 128M shares at year-end vs. 125M the prior year. Signal 7 fails (0). If instead they had bought back 3M shares, Signal 7 would pass — the market rewards this consistently in Piotroski's backtests.
Signal 8 — Change in Gross Margin
=IF(((B10-B11)/B10) > ((A10-A11)/A10), 1, 0)
Expanding gross margin signals pricing power, cost discipline, or mix improvement. All three are hallmarks of a genuine operational turn.
Signal 9 — Change in Asset Turnover
=IF((B10/((A5+B5)/2)) > (A10/A5), 1, 0)
Revenue over average total assets. Rising turnover means the firm is generating more sales per dollar of assets — efficiency is improving.
Aggregating the F-Score
On the Score sheet, drop a single cell:
=SUM(Signals!B2:B10)
Where Signals!B2:B10 holds the nine binary flags from above. The result is your F-Score, 0 to 9. For a cleaner UI, wrap in a conditional label:
=CHOOSE(MATCH(SUM(Signals!B2:B10),{0,3,8},1),
"Weak","Neutral","Strong")
This buckets the score into Piotroski's three published tiers.
Scaling to a Full Screen with LET and LAMBDA
The single-ticker template is fine for a deep dive, but the F-Score's real value is at scale — running it across a universe of 500 or 5,000 tickers. In Excel 365, you can wrap the entire computation in a single reusable LAMBDA function:
=LAMBDA(assets_prior, assets_curr, debt_prior, debt_curr,
ca_prior, ca_curr, cl_prior, cl_curr,
shares_prior, shares_curr,
rev_prior, rev_curr, cogs_prior, cogs_curr,
ni_prior, ni_curr, cfo_curr,
LET(
avg_assets, (assets_prior+assets_curr)/2,
roa_curr, ni_curr/avg_assets,
roa_prior, ni_prior/assets_prior,
s1, IF(roa_curr>0,1,0),
s2, IF(cfo_curr>0,1,0),
s3, IF(roa_curr>roa_prior,1,0),
s4, IF(cfo_curr>ni_curr,1,0),
s5, IF(debt_curr/avg_assets < debt_prior/assets_prior,1,0),
s6, IF(ca_curr/cl_curr > ca_prior/cl_prior,1,0),
s7, IF(shares_curr<=shares_prior,1,0),
s8, IF((rev_curr-cogs_curr)/rev_curr > (rev_prior-cogs_prior)/rev_prior,1,0),
s9, IF(rev_curr/avg_assets > rev_prior/assets_prior,1,0),
s1+s2+s3+s4+s5+s6+s7+s8+s9
)
)
Save it in the Name Manager as FSCORE, then call it as a single-cell formula across your data table. See the LET function guide for why the intermediate names matter here — they make the audit trail visible when a signal fires unexpectedly.
Piotroski F-Score vs Altman Z-Score vs Beneish M-Score
Every fundamental analyst should know when to reach for which score. Here is how the three most-cited quantitative screens compare:
| Feature | Piotroski F-Score | Altman Z-Score | Beneish M-Score |
|---|---|---|---|
| Purpose | Financial strength | Bankruptcy risk | Earnings manipulation detection |
| Range | 0 to 9 | Continuous (higher = safer) | Continuous (higher = manipulator) |
| Inputs | 9 line items × 2 years | 5 ratios | 8 ratios × 2 years |
| Best used on | Value stocks (high B/M) | Manufacturers, all industries | Any firm with unusual accruals |
| Signal | 8–9 long, 0–2 avoid | <1.8 distress zone | > -1.78 flags manipulation risk |
| Published | 2000 | 1968 | 1999 |
In practice, run all three: F-Score for quality, Z-Score for solvency, M-Score for accounting integrity. Firms passing all three are rare — and historically outperform on multi-year holds.
Backtesting Your Screen
Once the template is built, backtest it. Pull 5–10 years of point-in-time financials from a data provider (Compustat, Sharadar, WRDS), compute the F-Score for every firm in each year, and simulate the long-only "F ≥ 8" portfolio against a value benchmark like the Russell 1000 Value.
Three things to watch for:
- Look-ahead bias. Use financials as they were reported, with a 3–4 month reporting lag. A firm's Dec 2025 10-K isn't public until March or April 2026.
- Survivorship bias. Include delisted firms. Delisted names disproportionately populate the low-F-Score bucket, and excluding them makes the strategy look better than it was.
- Base rate. Piotroski applied his score only to the top book-to-market quintile. Applied to growth stocks, the score has weaker predictive power.
💡 Pro Tip: If you are building this in Excel and running out of room, use Power Query to pull the raw financials from a CSV or database, then let the LAMBDA
FSCOREcompute each row automatically. You can screen 3,000+ tickers this way without hitting Excel's calculation walls.
Common Pitfalls
Even seasoned analysts trip on the F-Score:
- Using LTM vs fiscal-year data inconsistently. Piotroski uses fiscal-year financials. Mixing LTM into some signals and FY into others creates ghost signals — either commit to one or the other for all nine tests.
- Ignoring segments. For diversified conglomerates, aggregate ratios can wash out an actual signal. Some funds run F-Scores at the segment level and then market-cap-weight them.
- Applying to financials or REITs. The score was calibrated on non-financial firms. Banks, insurers, and REITs have fundamentally different balance sheets — asset turnover and current ratio don't have the same meaning.
- Treating 8–9 as a buy signal in isolation. The score works as a filter within a value universe, not as a standalone recommendation. A strong F-Score on an overvalued growth name doesn't create alpha.
Where AI Fits In
The mechanical parts of F-Score construction — pulling line items from a 10-K, checking for restatements, running the nine tests — are exactly the workflow AI tools are transforming. Instead of manually retyping balance sheet numbers from EDGAR into your template, you can point VeloraAI at a filing PDF and get the 17 inputs populated in your sheet, with citations back to the source line, in one prompt.
This matters most at scale. Screening 500 firms means 500 filings × 17 line items = 8,500 numbers to source correctly. AI shrinks that from a two-week analyst project to an afternoon, and it makes the signals traceable — which is where most quant screens quietly fall apart under audit.
Frequently Asked Questions
What is a good Piotroski F-Score?
Scores of 8 or 9 are considered strong — these firms passed 8+ of the 9 tests, indicating improving fundamentals across profitability, leverage, and efficiency. Scores of 0–2 are weak. Piotroski's original strategy went long the 8–9 bucket and short the 0–1 bucket, generating documented excess returns of over 20% annually during his backtest window.
Does the Piotroski F-Score still work?
Multiple replications through the 2010s and early 2020s — including studies published in the Journal of Portfolio Management — confirm the F-Score continues to generate excess returns when applied to high book-to-market stocks, though the magnitude has compressed from Piotroski's original 23% spread to roughly 5–8% annually. It works best as a filter within a value strategy, not as a standalone signal.
Can you compute the Piotroski F-Score for financial firms?
Not directly. The score was calibrated on non-financial firms. Ratios like asset turnover and current ratio don't translate cleanly to banks, insurers, or REITs, whose balance sheets are dominated by financial instruments. For banks, use CAMELS or a modified score with regulatory capital ratios; for REITs, use FFO-based measures instead.
How is the Piotroski F-Score different from the Altman Z-Score?
The F-Score measures financial strength and improvement — is the firm getting healthier — while the Z-Score measures bankruptcy probability — is the firm about to fail. They answer different questions. A firm can have a strong Z-Score (low bankruptcy risk) and a weak F-Score (deteriorating fundamentals), which is often the setup for future underperformance without outright distress.
What data do you need to calculate the Piotroski F-Score?
You need two consecutive years of nine line items: total assets, long-term debt, current assets, current liabilities, shares outstanding, revenue, cost of goods sold, net income, and cash flow from operations. All are available on standard 10-K/10-Q filings — no proprietary data required. Total setup time in Excel is under 20 minutes per ticker.
Bringing It Together
The F-Score's staying power comes from its simplicity: nine transparent tests, one interpretable number, and a workflow that fits on a single Excel sheet. Wrap the logic in a LAMBDA, point Power Query at your data source, and you have a screening engine that would have taken a research team weeks to build a decade ago.
The next step is running it. Pick a value universe — Russell 1000 Value, MSCI World Value, or your own screen — pull the fiscal-year financials, compute the F-Score for every name, and sort the top and bottom deciles. That comparison is where the alpha lives, and the answer is one SUM away.