The pipeline: 785 to 57
The first pass disqualifies and orders. It does not value.
Claim tested
That a first-pass screen should rank companies by the gap between price and estimated value.
Result
Rejected. On this dataset that ranking is arithmetically equivalent to sorting by earnings yield, while looking like analysis.
Output
57 names: 38 AIM, 19 FTSE SmallCap. 41 operating companies, 16 financials.
The model I built and threw away
The obvious design was to estimate a low, central and high value per company from the screener data and rank by the discount to price. I tried it. It does not work, and the reason is arithmetic rather than a matter of taste.
The source file has 89 columns and no absolute financial-statement figures other than market capitalisation and revenue. Every valuation field is a ratio with price already inside it. Absolutes can be recovered legitimately — earnings equal market cap divided by P/E — and that recovery is price-independent. But the value estimate is then recovered earnings multiplied by a multiple I choose:
gap = value / price − 1 = (chosen multiple ÷ market multiple) − 1
Within a sector, that is a monotone transform of 1/PE. The value estimate adds no information whatsoever over sorting by earnings yield, while presenting itself as considered analysis. It is the composite score the specification forbids and the false precision it forbids, arriving together and holding hands.
The empirical run confirmed it. Only 178 of 410 companies were scoreable at all. Eleven of the top twenty by apparent discount carried a distress or manipulation flag. The extreme tail was also where the data errors concentrated, including a Beneish M-score of +31.8 and an Altman Z of 192.8 — not so much outliers as evidence that something has gone wrong upstream. Sector anchors rested on medians of six or seven companies.
Ranking by extremity on this data ranks by probability of data error at least as much as by cheapness.
The universe, and the triage
The raw universe was the full AIM list (597 companies) and the FTSE SmallCap constituents (188), as at 13 August 2026. Everything after that is reproducible from the published files.
Tradability first. Before any analytical work, every name was checked against my own broker for a tradable contract, then for three months of daily bars to compute average volume. A hard gate deliberately placed at the front: a mispricing in a company I cannot buy is a curiosity, not an opportunity. 41 companies failed it.
| Bucket | Count | Meaning |
|---|---|---|
| Pass | 275 | Clean on every availability criterion |
| Hold | 196 | Excluded only by the SETSqx off-book volume gap described in section 05 |
| Excluded | 314 | Fund or trust with no meaningful market cap (78), not tradable (41), market cap above £500m (35), dissolved or closed at Companies House (8), confirmed volume below the floor (the remainder) |
The Hold bucket is the part I would point at. The lazy version of this pipeline has two buckets and silently loses 196 companies to a limitation in one data feed. Cross-referencing recovered 135 of them, giving a screening universe of 410.
Five gates
Applied in order, all deterministic, all reproducible from screener_candidates_410.csv.
| # | Gate | Removed | Left | Why |
|---|---|---|---|---|
| 0 | Input | — | 410 | Tradable, matched to fundamentals data |
| 1 | Drop resource sector | 117 | 293 | Value in an explorer sits in reserves, licences and financing optionality, none of which is in this dataset. 91 of the 117 were loss-making, 59 had no revenue at all |
| 2 | Positive trailing earnings | 138 | 155 | Without positive earnings the earnings frame does not apply. A scope decision, not a verdict on the companies |
| 3 | Piotroski F-score ≥ 6 | 63 | 92 | A fundamental-momentum floor applied before any reading time is spent |
| 4 | Solvency, frame-appropriate | 15 | 77 | Altman Z ≥ 1.8 for operating companies, net gearing ≤ 150% for financials |
| 5 | ADV ≥ 1,000 shares | 20 | 57 | Removes names with no observable tradeable volume |
Gates apply in order — the flags are cumulative in the source data, so drag the slider to step through the funnel one gate at a time. Counts recompute live from the 410-company screening universe (pipeline_full_785.csv).
| Symbol ⇕ | Company ⇕ | List ⇕ | Type ⇕ | Value ⇕ | Quality ⇕ |
|---|---|---|---|---|---|
| Loading… | |||||
The correction I had to make
An earlier version of this gate produced 49 names. It was wrong. It applied the Altman Z-score to the 67 financial companies, where Z is undefined and generates artefacts. That value of 192.8 mentioned earlier belongs to a bank. Killing companies on a metric that does not apply to them is an accident, not a screen, and eight names failed for no reason at all.
A metric may only gate a company where the metric is defined for that company's frame.
Known defects, stated rather than discovered later
At least three resource explorers are misclassified in the source data and leaked through. Flagged in the workbook rather than silently deleted. The resource cut is approximately 117, not exactly.
Capitalising a single trailing figure is the classic small-cap error. Rebuilding multi-year history from primary filings is the entire purpose of the next stage.
Share count trend and director dealings are absent from the data and have to be added by hand.
Include SETSqx companies that may well be tradable in practice. They sit on an excluded sheet rather than being deleted.
Most are probably legitimate features of financing or asset-light models, but none should be used before establishing which.
With their exclusion reasons, so a revised gate can be re-run against the full 410. Nothing is deleted from this process, only labelled.
Four dimensions, never added together
Within the 57, four percentile ranks are computed and displayed side by side: value, quality, solvency and alignment. Direction is applied so that 100 is always favourable. Each score is the median of its available components, so a company is not penalised for a missing metric, and component coverage is reported next to it — a dimension backed by one input is a much weaker statement than one backed by five. They are never combined into a single figure. That was the point of writing it down beforehand.