The recipe in one line
The Bull Rankings score is:
Score = average of seven grade-points + signed synergy and risk adjustments
Seven graded signals, each scored A through F, get converted to points (A=100, A-=92, B+=85, B=80, ..., F=20), averaged, and then nudged up or down by a small set of explicit signed adjustments. The final number is rounded to the nearest integer and clamped between 20 and 110.
That's it. No machine learning, no black-box weighting, no analyst input. Every step is auditable from the row card: click any ticker on the rankings page and the score breakdown shows you the grades, the adjustments, and the math.
The seven signals
Each contributes ~14.3% of the base composite. Five surface on every row card; two live in the breakdown tooltip but feed the score equally.
Primary (shown on the row card):
- FCF (free cash flow) — How much cash the business produces after capex. See: Understanding free cash flow.
- Rev (revenue growth) — TTM YoY top-line growth. See: Understanding revenue growth.
- D/E (debt-to-equity) — Total balance-sheet leverage. See: Understanding debt-to-equity.
- P/E or P/S (valuation multiple) — P/E for profitable names, P/S for speculative pre-profit names. See: P/E vs P/S: when to use which.
- PEG (growth-adjusted P/E) — The Lynch ratio. See: Understanding the PEG ratio.
Supplemental (in the breakdown tooltip):
- FCF Yield — FCF divided by market cap. See: Understanding free cash flow yield.
- ROE (return on equity) — Capital efficiency. See: Understanding return on equity.
How a grade becomes a number
The conversion is a fixed table:
| Grade | Points |
|---|---|
| A | 100 |
| A- | 92 |
| B+ | 85 |
| B | 80 |
| B- | 72 |
| C+ | 68 |
| C | 60 |
| C- | 52 |
| D+ | 48 |
| D | 40 |
| F | 20 |
The base composite is the simple arithmetic average across all seven. A name graded straight Bs in everything scores (80 × 7) / 7 = 80. A name with three As and four Bs scores ~88. A name with one D among six Bs drops to ~74. No grade dominates by design — the model is deliberately humbled against any single signal.
The synergy and risk adjustments
After the base composite, the model applies signed nudges for setups that historically reward or punish more than the seven signals alone capture:
- GARP synergy bonus (+3 to +6). Awarded when a name combines a PEG under 1.5, P/E under 25, AND revenue growth above 10%. That intersection is statistically rare and historically the best-performing risk/reward setup.
- Compounder bonus (+2 to +5). Awarded for sustained high ROE (>20%) combined with low leverage (D/E < 0.5) and positive revenue growth. The classic Buffett "wide-moat compounder" profile.
- Hypergrowth premium (+2 to +4). For names growing revenue >30% YoY with sound balance sheets. Captures the pre-megacap stage where growth investing actually works.
- Extreme leverage penalty (−3 to −6). Applied when D/E exceeds 2.0 in a sector where 0.5 is typical. Double-counts deliberately — high leverage is a survival-of-the-business signal that deserves an extra penalty beyond what the D/E grade alone applies.
- Cash-burn penalty (−2 to −5). For non-speculative names with consistently negative FCF — a growth company plowing back cash is fine in the speculative bucket, but a "value" name burning cash is the worst kind of value trap.
- DCF cross-check nudge (±2). We compute a coarse three-horizon DCF on every name. If the DCF implies the stock is materially undervalued AND our composite agrees, the score gets a small upward nudge. If they disagree, no adjustment — keeps the model from double-counting either signal.
- Accruals warning (−1 to −3). A simple quality-of-earnings check: if reported earnings are materially higher than operating cash flow over multiple periods, accruals are doing too much of the work. Triggers a small downward nudge — earnings that don't convert to cash tend to revert.
The final score is the base composite plus all triggered adjustments. The breakdown tooltip on the row card shows every adjustment that fired, so you can see exactly why a name landed at 95 vs 88.
Sector-aware exceptions
A few sectors require special handling because the standard grade card doesn't apply:
- Banks, insurers: FCF, D/E, and PEG all break down (operating cash flow obscured by loans/deposits, structural leverage, sparse forward-EPS coverage). These get marked explicitly as n/a and replaced with neutral grades so they don't drag the score.
- REITs: Same FCF / D/E issues as financials. We use FFO-style metrics where available.
- Mining (gold, silver, copper): Highly cyclical earnings make PEG erratic at cycle extremes. We override the default C-on-null PEG grade to B for these sectors so a structural data gap doesn't penalize a real business.
Why one score and not three?
We could have published a separate "growth score," "value score," and "quality score" and let the reader weight them. The reason we don't: weighting is what makes a model opinionated. By committing to a single composite — and being explicit about the seven inputs and the adjustments — we force ourselves to make the trade-offs visible rather than punt them to the reader.
The bucket split (growth / value / spec) is where the per-name editorial choice lives. Within a bucket, the score is the answer to "is this a better-or-worse member of this bucket than this other one?" It doesn't claim to be comparable across buckets — a value bucket #1 with score 95 and a growth bucket #1 with score 92 are scoring different setups. The number is internally consistent within a bucket and roughly directional across them.
Bottom line
Every score is one average plus a handful of explicit adjustments, every input is auditable, and every grade is reproducible from the underlying financial statements. That's the entire pitch: the rankings page should be a reasonable starting point for someone who wants to do their own work, not a black box that asks you to trust it. Click any pick and watch the math.