Check stock membership as a screening cutoff moves
Stock screening threshold sensitivity asks how research membership changes when one declared cutoff moves while the data and universe stay fixed. Run a small grid chosen before looking at outcomes, compare the actual member sets and identify stocks that always pass versus those near the boundary. This is a workload and rule-boundary check, not a backtest optimization or proof of predictive robustness.
The worked example changes a PE ceiling across three settings and retains a fixed growth requirement. It executes set comparisons on synthetic inputs, checks the expected direction and rejects a deliberately nonnested result. CoTrading’s corresponding threshold preview remains planned or unverified; the local script does not connect to a market feed or choose a profitable investment rule.
Freeze everything except the chosen threshold
Save the universe, input values, field definitions, missing-data policy, rule version and observation date. Choose one parameter to vary, including its operator. A PE rule strictly below a ceiling differs from one allowing equality. Changing both the threshold and the earnings denominator would prevent a clean explanation of membership changes.
Our synthetic rows have PE 17, 18, 20, 21 and 23 for AAA through EEE, with growth 0.12 for each. FFF has PE 19 but growth 0.08. GGG has missing PE and growth 0.12. The shared requirement is observed positive PE and growth at least 0.10. The grid of strict PE ceilings is 18, 20 and 22.
Choose grid values for an operational reason, such as a manageable research scope or the precision of a meaningful business requirement. Do not inspect future returns and select the setting that happens to win. This fixture contains no prices after selection and no performance measure, so it cannot answer which ceiling produces better investment results.
Predict the direction before executing
For a strict upper PE bound, raising the ceiling relaxes the condition. With all other inputs fixed, every stock passing at 18 should also pass at 20, and every stock passing at 20 should pass at 22. The expected sets are nested. A stock should not disappear merely because this single upper ceiling increased.
That expectation depends on the full rule. If the screen also requires “the cheapest two stocks,” applies a changing ranking population or varies another condition, simple nesting may no longer describe the task. Separate those operations from this threshold experiment. The present screen has no capacity truncation or preference ranking.
Missing PE remains unresolved across the grid; it does not become a low PE by replacing null with zero. FFF remains excluded by the fixed growth condition, even when the PE ceiling would admit it. These examples show why a changed numerical threshold need not resolve every nonselected stock.
Execute the predeclared grid
members = [{symbol for symbol, pe, growth in rows
if pe is not None and 0 < pe < cutoff and growth >= .10}
for cutoff in grid]
for left, right in zip(members, members[1:]):
if not left <= right:
raise ValueError("non_monotone_membership")
stable = set.intersection(*members)
union = set.union(*members)
The Python set reference documents subset checks, intersection and union. These operations describe stock identities, not independent observations. Keep a deterministic display order when turning sets into tables so unordered storage does not distract from genuine membership changes.
Download the complete example. Use Python 3.12+, the standard library and synthetic data; run python R526.py. The authoring file is docs/growth/research/round-5/examples/R526.py.
Actual output is one candidate at ceiling 18, two at 20 and four at 22. The member lists are AAA; AAA and BBB; AAA, BBB, CCC and DDD. The script asserts each set, nested inclusion and an unchanged hash of the input rows. It also injects sets containing AAA then BBB and asserts that the nonmonotone check raises an error.
Read the boundary table, including equality
| Strict PE ceiling | Members | Newly admitted versus prior setting |
|---|---|---|
| 18 | AAA | initial member |
| 20 | AAA, BBB | BBB |
| 22 | AAA, BBB, CCC, DDD | CCC, DDD |
BBB at PE 18 does not pass the first setting because the rule is strictly below 18. CCC at PE 20 does not pass the second. These equality cases verify the actual operator. A user who meant “no more than” needs a deliberately changed rule and a new boundary expectation, not a silent correction of the current script.
The stable intersection is AAA. The union is AAA, BBB, CCC and DDD. Boundary candidates are the union minus the stable intersection: BBB, CCC and DDD. Here stability means membership under these particular three settings on this frozen snapshot. It is not stability over time, statistical significance or robustness to unseen market conditions.
For financial cutoffs sensitive to representation, use explicit numeric conventions and unrounded observations. The Python decimal documentation describes decimal representation. The fixture’s integer PE boundaries avoid a floating-point ambiguity; a production screen should still record how supplied decimals and displayed rounding relate to the comparison.
Avoid counting the same stock as several opportunities
The three candidate counts sum to seven, but their union contains four stocks. Seven is the number of stock-setting memberships, not seven distinct research opportunities. AAA appears at all three settings; BBB appears at two. Reporting only the sum would exaggerate the breadth generated by the experiment.
Publish both the count table and the membership transitions. Two settings can have the same count while containing different stocks, which would violate expected nesting in this specific experiment. Counts alone cannot detect that substitution. The injected AAA-to-BBB counterexample deliberately preserves a count of one while changing identity and failing the subset test.
That failure should trigger an input and rule comparison before an economic explanation. Check whether data were refreshed between settings, whether another threshold moved or whether a ranking cap was applied. Do not explain an implementation inconsistency as a stock “becoming sensitive” until the supposedly fixed experiment is actually fixed.
Choose a research scope without a hidden return objective
The researcher can compare one, two and four candidates against available reading capacity. Selecting a workable list size is a legitimate operational choice if the changed requirement still reflects the intended question. Save that decision and retain the full grid so the selected scope does not erase the discarded alternatives.
Do not label the stable set “best” or the boundary set “bad.” Boundary stocks are simply affected by the chosen cutoff range. They may deserve careful source checks, especially when metric rounding or recent revisions place them close to equality. A company far from the threshold can still have poor data or an unsuitable business model.
Preserve a replayable sensitivity package
Deliver the frozen input reference, grid, member sets, counts, stable set, boundary list and monotonicity result. Include the fixed growth condition and missing-PE handling, so readers do not assume every exclusion came from PE. Record the chosen final setting as a separate decision from the experiment output.
Rerun the entire grid after new data, a source correction or a changed rule definition. Compare like-for-like snapshots when explaining why a stock moved. Keep the earlier experiment available instead of updating its inputs in place. This makes cutoff sensitivity a concrete inspection of research workload and membership boundaries while leaving performance evaluation and strategy optimization to separately designed tasks.
Keep research-capacity decisions separate from results
Record the final chosen ceiling, the available research capacity and the reason that ceiling still answers the original request. The experiment can inform that choice without selecting it automatically. If the researcher later has more time, the retained grid can support a different workload decision without rewriting what the earlier screen produced.
Inspect boundary observations for source precision and recent revisions before treating their movement as economically meaningful. A stock can move because the published metric rounded across a strict boundary, while the underlying business has changed very little. Preserve the exact input used and its publication precision so the movement can be reproduced.
When expanding the grid, keep the original settings and explain why new settings were added. Do not replace an inconvenient range after seeing its candidates and still describe the experiment as predeclared. The useful evidence is the complete membership comparison under a stated scope, including repeated stocks and nonselected records, rather than a handpicked threshold that produces an appealing list.
FAQ
Can equal candidate counts prove stable membership?
No. Compare identifiers. The same count can conceal a complete substitution.
Does passing every tested cutoff establish robustness?
Only membership stability across this declared grid and snapshot. It says nothing about future returns or other untested changes.