Published 2026-10-14 · Updated 2026-10-25
Screen Stocks With Factors, Not Opinions
A screener turns a vague idea — "cheap, quality, small" — into a reproducible filter. The discipline is in stating each factor precisely, and in knowing what the screen cannot tell you.
On this page
The idea
“I want cheap, quality, small-cap stocks” is a sentence. A screen is the same sentence written so a machine can run it — and re-run it.
The difference matters, because a screen can be checked and a sentence cannot.
Step 1 — Turn adjectives into factors
Every vague word hides a measurable definition. The work is choosing one, and saying so.
| Adjective | Becomes a factor | Needs stating |
|---|---|---|
| “Cheap” | Low price-to-book, or low PE | Which ratio, measured when |
| “Quality” | High ROE, stable earnings | Which metric, over what window |
| “Small” | Market cap below a threshold | The threshold, in which currency |
| “Momentum” | Return over the last N periods | N, and whether it skips the most recent period |
A factor without a stated definition is not a filter — it is a word.
Step 2 — Write it as a filter
Once each adjective is a factor with a range, the screen is just conditions joined together — all of which must hold:
intersect([
TotalMV <= 20000000000, # "small" — market cap, in yuan
PB < 1.5, # "cheap" — price to book
ROETTM > 15, # "quality" — return on equity, in percent
])
Each line states three things, not one: the field name, the unit, and the comparison. ROETTM > 0.15 does not mean “ROE above 15%” — it means “ROE above 0.15%”. A screen with the wrong unit is not a weaker screen; it is a different one.
intersect([...]) is only how this endpoint spells “all of these must hold”. The part that carries the meaning is inside the brackets.
This is checkable. Someone else can run it, get the same list, and disagree with the choice — rather than with the meaning.
That is the whole benefit: the disagreement moves from “what do you mean” to “do you agree”.
Step 3 — Run it, and reproduce it
The screen is only reusable if the same input gives the same output. That means the data pull must be reproducible too — stated parameters, same series.
# This endpoint requires a paid API key — add yours as the `key` parameter.
# Same request, same result — the basis of a screen you can defend.
curl -G "https://api.ashareapi.com/v1/screen" \
--data-urlencode "expr=intersect([TotalMV<=20000000000, PB<1.5, ROETTM>15])" \
--data-urlencode "key=YOUR_KEY"
If the run cannot be reproduced, the list is not a screen — it is a snapshot of a moment that has already passed.
Step 4 — Know what the screen cannot tell you
This is the part that separates a useful screen from a misleading one.
| The screen does not say | Because |
|---|---|
| That the stocks will go up | A screen is a filter, not a forecast |
| That the factors will keep working | Factors decay once widely known |
| That the list is complete | It only contains what the data contained |
| That the ranking is stable | Small input changes can reorder the output |
A screen answers exactly one question: “which instruments match these stated conditions?” Everything else is a leap you are making, not something the screen told you.
Step 5 — State the sources
A factor is only as good as the data behind it. For each one, know:
- Where the input came from — and whether it was restated after the fact
- When it was known — point in time, not as revised
- Whether delisted names are included — or the survivors-only problem is hidden
A screen built on restated data over today’s universe is not a screen. It is a description of a market that never existed.
See point-in-time data and survivorship bias.
What you have
You turned an opinion into something runnable, reproducible, and falsifiable — and you can now say exactly what it does and does not claim.
That is the difference between a screen and a stock tip, and it is not a small one.
Next
- Test a rule without fooling yourself → what to check before acting on a screen
- Factor → the glossary entry behind this guide