StockScore Formula Methodology
The formula represents one defined quantitative methodology. Other methodologies may use different inputs, assumptions or weightings and may produce materially different results.
Formula position is relative to the eligible companies and available data at a specific calculation time. A change in position may result from changes to the company's data, market data, the eligible universe or data availability.
StockScore formula results are not valuations, price targets, forecasts, investment recommendations or suitability assessments.
1. Formula Identification
Formula name: StockScore Formula. Current version: v1.0. This is the version in effect from the launch of this published methodology page, 22 September 2026. Version v1.0 introduces formal version labelling and public disclosure of a calculation that was already in use; it does not change any input, weighting or eligibility rule.
2. Eligible Universe
The eligible universe for each calculation is the set of companies that are constituents of the S&P 500 index and have a share price over $5, as returned by the data source's screener filters ("Index: S&P 500" and "Price: Over $5") at the time of that calculation. A company that does not meet both filters on a given calculation date is outside the eligible universe for that date and does not receive a formula position.
3. Inclusion, Exclusion, Missing-Data, Negative/Zero and Outlier Rules
Only companies meeting the eligible-universe filter in Section 2 are included in a given calculation. Companies are not additionally excluded for having incomplete data. Instead, missing values for the two formula inputs are replaced with a fixed placeholder value before ranking:
- A company with no reported P/E ratio is treated as having a P/E of 100, rather than being removed from the universe. This applies whether an individual company's P/E is unreported, or the data source's response is missing the P/E field entirely. 100 is a fixed default, not the least favourable value used anywhere — because P/E has no fixed upper bound, a company with a very high but genuinely reported P/E (well over 100) ranks less favourably on this input than a company with a missing P/E.
- A company with no reported ROA is treated as having an ROA of 0, again rather than being removed from the universe.
Because a substituted default and a genuinely reported value can be numerically identical (a real P/E of exactly 100, or a real ROA of exactly 0%), every formula result carries a separate machine-readable flag (peSubstituted/roaSubstituted) distinguishing the two - shown as "Not reported" on the Formula Results table and company-detail page, and as dedicated "P/E Substituted"/"RoA Substituted" columns in both CSV exports, rather than relying on the number alone.
A negative or zero P/E or ROA value is not treated as missing and is not floored, adjusted or excluded — it is ranked exactly at its reported value, alongside every other company's reported value. A company with negative ROA, for example, ranks below every company with positive ROA, and below any company with a less negative ROA, in that strict order.
No outlier adjustment (winsorising, capping, or exclusion of extreme values) is applied to either input before ranking. An unusually high or low P/E or ROA is compared at its full reported value, exactly like any other value — not capped, floored, or set aside.
Ranking itself is ordinal, not magnitude-weighted: each input is sorted — P/E ascending (lowest first), ROA descending (highest first) — and each company is assigned a position in that order (1st, 2nd, 3rd, and so on), the same way the worked example in Section 7 shows. An ROA of -1% ranks below every higher ROA and above every lower one, in that strict numerical order. A company tied with one or more others on that individual input is not given a separately broken position on it — per Section 5, a tied group each receives the average of the ranks it occupies (e.g. two companies tied for what would be 3rd and 4th both receive 3.5). Only a combined-rank tie — the final sum of a company's P/E-based and ROA-based ranks matching another's, which can happen even when neither individual input was itself tied — is broken, and only by ticker symbol in ascending alphabetical order (Section 5/7). The size of the resulting rank gap between two companies depends on how many other companies in the full eligible universe fall between their reported values, and on how many of those are tied with each other — not on the size of the percentage gap itself. A company with an ROA of -1% could rank one position above a company with an ROA of -2%, or many positions above it, depending entirely on how many other companies' reported ROA falls in between. Nothing here scales, weights, or otherwise reflects how extreme a reported value is beyond its position in that ordering.
4. Data Source, Field Mapping and Currency
Company and market data is sourced from the Finviz screener, filtered to the eligible universe defined in Section 2. Two separate screener views are queried and joined on ticker symbol:
| Displayed field | Source view | Source field | Unit |
|---|---|---|---|
| Price | Overview | Price | USD |
| P/E ratio | Overview | P/E | Ratio (dimensionless) |
| ROA | Financial (joined by ticker) | ROA | Percentage, e.g. a value of 12.5 means 12.5% |
| Sector, country, market-cap group | Overview | Sector, Country, Market Cap | — |
A company absent from the Financial view (so no ROA join match) is treated the same as a company with a missing ROA cell — see Section 3.
Reporting-period disclosure: the Finviz screener views above return a live snapshot with no separate field stating which financial period (e.g. which quarter's filing) a company's P/E or ROA reflects. The only date we can attach to a result is the date we ran the calculation - shown on the Formula Results table and company-detail page as the "Calculated at" timestamp, and in the CSV export as "Screener Retrieval Date" (daily export) or "As Of Date" (historical export). We do not invent a reporting period the source doesn't supply.
Correction/republication disclosure: if a company's Formula Position or Overall Formula Result is later corrected (for example, applying a tie-break rule that was already documented but not yet reflected in that day's live calculation), the original "Calculated at"/"Screener Retrieval Date"/"As Of Date" timestamp is never rewritten to make the corrected result look like it was published at that original time. Instead, a separate "Position Corrected At" value records when the correction was made, only for a company whose result actually changed. This disclosure works differently for a Daily result than for the Historical (trailing average) result, because only the latter is a rolling calculation that a correction can eventually age out of:
- A Daily row's original calculation time is permanent, and the fact that it was ever corrected - once true - is permanent too, but the SPECIFIC correction record shown is not: a second correction to that same date overwrites it, exactly like a correction to a different date overwrites the Historical summary below. A Daily row's "Calculated at" timestamp, once set, is never rewritten. Once its "Position Corrected At" field is ever set, that field is never removed again - the boolean fact "has this specific date's row ever been corrected" is permanent and reliable. But if that same date is corrected a SECOND time (an authorised further republish, distinct from the case below), the "Position Corrected At" VALUE is overwritten with the new correction's own timestamp, exactly as it would be for a different date's correction overtaking the Historical summary (see the fourth bullet below) - the earlier correction's own timestamp for that date is not separately retained anywhere once superseded. This is distinct from saying the row's displayed figures can never move: an authorised same-date republish (for example, correcting a data-source glitch) can re-fetch and revise a displayed input - price, P/E, RoA, name, sector, country or market-cap group - for that same calendar day, recorded as a separate "Data Revised At" value. This is independent of "Position Corrected At", not a substitute for it or a claim about it either way: a single republish can change a displayed input only, the Formula Position/Score only, both together, or neither - "Data Revised At" and "Position Corrected At" are stamped, carried forward, or left absent entirely independently of each other, and a row showing both together is correct, not a contradiction. A Daily result with no "Position Corrected At" value has genuinely never had its Formula Position or Score corrected since its original calculation - this absence-means-never guarantee is unaffected by the above, since the field is only ever absent when no correction has happened at all. The same absence-means-never guarantee does not extend to "Data Revised At": that tracking began when the field was introduced, so a row republished before then could have had a displayed input silently revised with no record of it at all - its absence there means only that no revision is recorded, not that none occurred.
- Whether a correction still affects today's Historical average is a separate question from whether one ever happened. The Historical result is a rolling average of up to the 30 most recent daily observations (Section 5); a correction to one of those observations only affects the CURRENT average while that observation remains inside the window. The visible "Corrected" marker on the Historical Formula Results table and company-detail page is shown only while this is true - once the corrected observation ages out of the window, the marker is removed there, because the average shown no longer reflects it. Its absence therefore means either "never corrected" or "a correction happened but has since aged out of the average" - not necessarily the former, unlike the Daily case above.
- Four distinct things, not one: a dated Daily row's persistent ever-corrected fact, that row's most recently recorded correction timestamp, the Historical row's own single most-recent summary, and a complete event ledger - only the first three exist. Each dated Daily row's fact that that specific calendar day's result was ever corrected, once true, is permanent - correcting adifferent day never touches, overwrites, or erases any other day's own row, and a day's row is never reset back to "never corrected" once it has been. But that same row's most recently recorded correction timestamp is a separate thing from the fact: a SECOND, later correction to that same date overwrites the first correction's timestamp on that date's own row (see the first bullet above) - the fact survives, the specific earlier record does not. The Historical row holds its own separate single summary value: whichever correction happened most recently across any date, which overwrites the record of any earlier correction to a different date. None of the first three is a complete event ledger: there is no single view listing every date, or every correction, a company has ever received - a correction to an earlier date leaves that date's own permanent fact intact and unaffected on its own row, but nothing indexes or enumerates which dates were ever corrected, or how many times; you would need to already know which date to check, and even then would only see that date's own latest correction, never a full count.
- The audit record shows the most recently recorded correction, not a complete history of every correction a company has ever received. A correction is never erased from the underlying data merely because it has aged out of the current Historical average - but if a company's Formula Position is corrected again - whether on a later date, or a second time on that same date - that later correction's timestamp and scan date overwrite the earlier one's record entirely; only the single most recently recorded correction event is ever retrievable for the Historical summary, and only the single most recently recorded correction event for that specific date is ever retrievable on a Daily row that has itself been corrected more than once, whether or not an earlier one also still affects today's average. The historical CSV export's "Position Corrected At" column and the visible "Corrected" marker both describe only this one recorded event - a separate "Correction Reflected In Current Average" column states plainly whether that specific recorded correction still affects today's average ("Yes"), has aged out ("No"), or - for the small number of corrections made before this distinction was tracked - is not determinable ("Unknown"). Neither column claims this is the only correction a company has ever received: a missing "Corrected" marker, or an aged-out "Correction Reflected In Current Average: No", proves only that the recorded correction currently doesn't affect the average - never that no other, earlier correction exists or ever did.
Currency treatment: the P/E ratio and ROA are both dimensionless (a ratio and a percentage respectively) and require no currency conversion — they are identical regardless of what currency the app displays elsewhere. Price is sourced in USD; where the app displays price in a different currency for your account, that is a display-only conversion applied after the formula has already run, and has no effect on P/E, ROA, formula position or formula score.
5. How the Formula Is Calculated
- Every company in the eligible universe is given a P/E-based rank (also labelled the value-factor rank), where a lower P/E ratio receives a numerically lower rank. Companies that report the exact same P/E are not arbitrarily split apart: each one gets the average of the ranks that group would otherwise occupy (for example, three companies tied for the lowest P/E each get rank 2.0, not 1, 2 and 3).
- Every company is also given an ROA-based rank (also labelled the quality-factor rank), where a higher ROA receives a numerically lower rank, using the identical average-rank handling for any ROA tie.
- The P/E-based rank and the ROA-based rank — the exact same two numbers from steps 1 and 2, not a separate calculation — are added together to produce a combined rank for each company.
- Companies are sorted by combined rank, from lowest to highest. Only combined-rank ties — which can arise even when no individual P/E or ROA rank was tied, since two different pairs of ranks can sum to the same total — are broken, and only by ticker symbol in ascending alphabetical order (see Section 7's fictional example for a worked tie of each kind). This ticker tie-break is a distinct, later step: it never changes a company's P/E-based rank or ROA-based rank from steps 1–2, and it is never applied to those individual ranks directly.
- This ordering produces each company's daily Formula Position, running from 1 to N, where N is the number of companies in the eligible universe on that calculation date. A lower position number corresponds to a lower combined rank.
- A Formula Score from 0 to 100 is also shown. This restates the same formula position as a percentile, so that a higher score corresponds to a numerically lower formula position. The Formula Score is purely a display restatement — it plays no part in the calculation and does not change any company's formula position.
- The Historical Formula Result shown for a company (its overall, non-daily position) is a trailing average of that company's daily formula position over its most recent up to 30 actual daily observations - 30 completed daily calculations, not 30 calendar days, and often fewer than 30 for a company still building its history (Section 6). Only this Historical Formula Position is averaged this way; "Latest Daily Formula Result" and the Quality-Factor/Value-Factor Components always reflect the single most recent daily calculation, never an average.
Written as equations, for a company i in a universe of N companies:
pe_rank(i) = average-method rank of pe(i) among all companies, ascending (lower P/E → lower rank; a tied group each gets the average of the ranks it occupies)
roa_rank(i) = average-method rank of roa(i) among all companies, descending (higher ROA → lower rank; same average-rank tie handling)
combined_rank(i) = pe_rank(i) + roa_rank(i)
formula_position(i) = position of company i when all companies are sorted by (combined_rank ascending, ticker ascending) — the ticker term only ever breaks a tie in combined_rank itself
formula_score(i) = round(100 × (N − formula_position(i) + 1) / N)
historical_formula_result(i) = mean of the most recent up to 30 daily formula_position(i) values
The Quality-Factor Component and Value-Factor Component (both shown out of 100) restate pe_rank and roa_rank from steps 1–2 above — the same two numbers already added together to form combined_rank, not a second, separately-computed rank. Restating a rank as a percentile needs no additional tie-break: a tied pair of companies is simply allowed to show the same Component score, since (unlike Formula Position) nothing here requires giving every company a distinct value. This is why a Component score can never determine, or be confused with, Formula Position: two companies can share an identical Value-Factor Component while sitting in different Formula Positions (because their ROA-based rank, which also feeds combined_rank, differs), and two companies can occupy adjacent Formula Positions while showing different Component scores on both factors. See Section 7 for a worked example of each case.
value_factor_component(i) = round(100 × (N − pe_rank(i) + 1) / N)
quality_factor_component(i) = round(100 × (N − roa_rank(i) + 1) / N)
Rounding for both Components is standard round-half-up on the resulting percentage, matching every other 0-100 score on this page. See Section 7's fictional worked example for a full walk-through of these equations, including tied inputs.
A missing P/E or ROA is included in this ranking at its formula-input value (100 for P/E, 0 for ROA - see Section 3), the same substituted value used in the main calculation, and is disclosed via the same peSubstituted/roaSubstituted flag described there.
6. Update Frequency
The formula is recalculated once per day by an automated job that re-fetches data from the source described in Section 4, reapplies the eligible-universe filter, and recomputes the P/E-based rank, ROA-based rank, combined rank, formula position, formula score, and Historical Formula Position (the trailing average over that company's most recent up to 30 actual daily observations - never 30 calendar days, and never a fixed window a newer company's shorter history is padded or rounded up to meet) for every company in that day's eligible universe.
7. Worked Example (Fictional Data)
The companies, tickers, P/E ratios and ROA figures below are entirely fictional and are shown only to illustrate the calculation steps in Section 5. They do not describe any real company.
| Company (fictional) | P/E | ROA | P/E-based rank | ROA-based rank | Combined rank | Formula Position | Value-Factor Component | Quality-Factor Component |
|---|---|---|---|---|---|---|---|---|
| Alpha Corp (ALPC) | 12 | 18% | 1.5 | 2 | 3.5 | 1 | 90 | 80 |
| Epsilon Ltd (EPSL) | 12 | 10% | 1.5 | 3 | 4.5 | 2 | 90 | 60 |
| Gamma Holdings (GAMH) | missing (treated as 100) | 22% | 5 | 1 | 6 | 3 | 20 | 100 |
| Beta Industries (BETI) | 45 | 5% | 4 | 4 | 8 | 4 | 40 | 40 |
| Delta Systems (DLTS) | 20 | missing (treated as 0%) | 3 | 5 | 8 | 5 | 60 | 20 |
Reading the table — three kinds of tie, all in this one fictional universe of five companies:
- Individual-input tie (P/E): Alpha Corp and Epsilon Ltd both report a P/E of 12 - the lowest two in this universe - so instead of arbitrarily giving one of them rank 1 and the other rank 2, they each get the average of those two ranks: 1.5. The identical rule would apply to a tied ROA (not shown here, to keep the table readable) - a group tied for the highest ROA would each get the average of the ranks that group occupies, exactly as for P/E.
- Component scores follow the individual rank, not the final position: because Alpha and Epsilon share the same P/E-based rank (1.5), they also share the same Value-Factor Component (90) - but they do not share a Formula Position. Alpha's higher ROA gives it a numerically lower ROA-based rank (2 vs. 3), so its combined rank is lower (3.5 vs. 4.5), placing it 1st against Epsilon's 2nd. A shared Component score never implies a shared, or even adjacent, Formula Position.
- Combined-rank tie: Beta Industries (BETI) and Delta Systems (DLTS) reach the same combined rank (8) from two different pairs of individual ranks (4+4 and 3+5) - neither company's own P/E-based or ROA-based rank was tied with the other's. Only this final combined-rank tie is broken, and only by ticker symbol in ascending alphabetical order, so BETI (alphabetically before DLTS) receives the lower (numerically first) Formula Position of the two.
8. Formula Changelog
| Version | Date | Change |
|---|---|---|
| v1.0 | 30 September 2026 | Corrects the 29 September entry below, and the two audit-record bullets it describes - no formula/position/score change. That entry said a dated Daily row "permanently retains" whether it was ever corrected, without distinguishing two different things: the PERSISTENT FACT that a given date's row was ever corrected (genuinely permanent, once true) is not the same as the SPECIFIC correction timestamp shown on that row (not permanent - a second, later correction to that same date overwrites it, exactly like a correction to a different date overwrites the Historical row's summary). "Three distinct things" is corrected to four: a dated Daily row's persistent ever-corrected fact, that row's most recently recorded correction timestamp, the Historical row's single most-recent summary, and a complete event ledger - only the first three exist. This also corrects an absence: the prior wording never stated, and should have, that correcting one date never erases, resets, or otherwise affects a different date's own row - that guarantee is unchanged and remains true. See docs/compliance/2026-09-30-round13-remediation-report.md's dated addendum for the full trace. The "Corrected" marker's current-window meaning is unchanged by this correction. |
| v1.0 | 29 September 2026 | Two fixes, no formula/position/score change. (1) The round-11 fail-closed fix checked whether a correction target was still the latest published date only once, before any Daily/Historical rows were actually copied - a genuine concurrent publish (an ordinary scheduled run, or a second correction) landing in that window could still let a stale correction commit. Fixed with a single shared commit step (commit_manifest_publication() in backend/fyre.py, used by both the scheduled daily run and scripts/republish_corrected_positions.py) that re-checks this, atomically, at the actual moment of commit - a concurrent publish now makes the LATER attempt fail cleanly, rather than letting either succeed in a way that could disagree with the other. (2) This section's audit- record wording is sharpened to name three distinct things explicitly: a dated Daily row's own permanent correction fact, the Historical row's single most-recent summary, and a complete event ledger - only the first two exist. No formula, input, weight, eligibility rule, position, or score changed as a result of either fix; the "Corrected" marker's current-window meaning (shown only while the recorded correction still affects today's average) is unchanged. |
| v1.0 | 29 September 2026 | Two fixes, no formula/position/score change. (1) Fail-closed fix in scripts/republish_corrected_positions.py: correcting a published date other than the current latest one wrote a fully correct new Historical bucket under that older date's own manifest row, but the live Historical view resolves its bucket from the LATEST manifest row only - so the correction was invisible to every reader, while "Latest Daily Formula Result" risked being overwritten with a non-latest score. A read-only audit of both environments' real data found no evidence this had already happened - the only corrections present (88 tickers, 24 September 2026, see the entries below) predate this script and were applied same-day, not backdated. The script now refuses any --scan-date that isn't the current latest, before any write, until a genuine atomic multi-manifest-row update exists. (2) Documentation fix: this page previously said the historical CSV's "Position Corrected At" column shows a company's "full history" of corrections. In fact, correcting the same company again on a later date overwrites the earlier correction's own record entirely - only the single most recently recorded correction is ever retrievable. This is an intentional, documented limitation, not a redesign: because a correction can only ever be applied to the current latest date, the earlier corrected date always ages out of the 30-observation window before or alongside the later one, so this never produces a false "not corrected" marker - but a missing or aged-out marker is not proof that no other, earlier correction was ever applied. The Formula Results table, company-detail tooltip, and presentation standard are all reworded to state this precisely. |
| v1.0 | 29 September 2026 | Two fixes, no formula/position/score change. (1) Data-pipeline fix: an authorised same-date republish that changed a company's Daily Formula Position also affects its Historical (trailing average) result for that same day, but the Historical write only ever carried forward an EXISTING "Position Corrected At" value - it never created one when the republish itself was what changed today's contributing observation (a separate correction step, scripts/republish_corrected_positions.py, already stamped this directly - only a same-date fyre.py --allow-republish rerun was affected). The displayed trailing average itself was never wrong; only the audit trail silently missed this specific case. Fixed so a fresh correction is created exactly when today's own observation changes, carried forward unconditionally otherwise, and never erased once the corrected observation ages out of the averaging window. (2) Wording fix: this section, the shared correction-display code, the Formula Results table and company-detail page previously implied "Data Revised At" and "Position Corrected At" were mutually exclusive - a data revision meant no position change, and vice versa. In fact a single republish can change a displayed input, the Formula Position/Score, both, or neither; both markers now show together, correctly, when both happened. The set of fields "Data Revised At" tracks was also reviewed and widened to every displayed input a user can see or filter on (price, P/E, RoA, name, sector, country, market-cap group - previously only the first three plus their substitution flags), and this section no longer claims a missing "Data Revised At" proves a row's inputs were never revised - that tracking only began when the field was introduced, so an older row's absence means only that no revision is recorded, not that none happened. Verified with new tests covering a further correction on an already-corrected position, an aged-out correction's audit trail surviving intact, a failed republish never losing a freshly-created correction, a metadata-only revision (sector), and a single republish that changes both a displayed input and the Formula Position together. |
| v1.0 | 29 September 2026 | Data-pipeline fix, not a documentation correction: an authorised same-date republish that revised a displayed input (price, P/E or RoA) without changing a company's Formula Position or Score left no trace that the row's data had moved since its original calculation - the round-8 fix below already stopped this from being mislabelled a position correction, but recorded no signal of any kind that a revision had happened. Section 4's "immutable"/"never recalculated" wording described a Daily row's calculation timestamp and correction history, which are genuinely permanent, but read as implying its displayed figures could never move at all, which was never quite true for this specific case and is now stated precisely. Fixed by adding a third, independent "Data Revised At" timestamp to backend/fyre.py'spersist_to_aws() - distinct from "Calculated At" (the original calculation, still never rewritten) and "Position Corrected At" (the Formula Position/Score only) - stamped only when a republish changes a displayed input, and passed through the API, Formula Results table, company-detail page and daily CSV export as its own labelled "Revised" marker, never conflated with a "Corrected" one. No formula, input, weight or eligibility rule changed; verified with new tests reproducing an input-only republish, an input-only republish of a previously-corrected row, and a failed republish that must not lose either an existing correction or an existing data revision. |
| v1.0 | 29 September 2026 | Data-pipeline fix, not a documentation correction: Section 4 already said a Daily result's "Calculated at" timestamp is permanent and its correction history is never lost, but backend/fyre.py'spersist_to_aws() did not actually enforce this for a same-date republish (e.g. an --allow-republish rerun, which always targets the current day) - every republished row got a fresh "Calculated at" (the republish time, not the original) and lost any prior correction record entirely, since the write never checked for or read back the previously published generation. Fixed so a republish now preserves each ticker's original "Calculated at" and carries forward any existing correction record, stamping a new one only for a ticker whose position or score genuinely changes in that republish - matching how scripts/republish_corrected_positions.pyalready behaved. No formula, input, weight or eligibility rule changed; this closes a gap between documented and actual behaviour, verified with a new failure-injection test proving a same-date republish preserves a prior correction end-to-end, and that a republish failing partway through never loses one. |
| v1.0 | 29 September 2026 | Documentation correction, no formula/position/score change, two parts. (1) Section 4's correction disclosure said a result with no "Position Corrected At" value "has never been corrected since its original calculation" - true for a Daily result (permanent, immutable), no longer true for a Historical result once the site began suppressing that same visible marker after a correction ages out of the current averaging window (the underlying timestamp is retained and can still appear in the historical CSV export, now alongside a new "Correction Reflected In Current Average" column stating plainly whether it still does). Rewritten as three separate, accurate rules - Daily history is permanent; the Historical marker's absence can mean either "never corrected" or "aged out"; the audit record is always retained and distinguished from a live claim about today's average. (2) Section 5's Historical Formula Result description, and Section 6's update-frequency description, both still said "30-day trailing average" - reworded to state what Section 6's own worked equation already correctly said: a trailing average of up to 30 actual daily observations, not 30 calendar days, often fewer for a company still building its history. No input, weight, eligibility rule, position or score changed as a result of either correction. |
| v1.0 | 29 September 2026 | Documentation correction, no formula/position/score change: the previous entry below (same date) said a tied ROA "is broken the same way any other tie on that input is", contradicting Section 5 - a tie on an individual input (P/E or ROA) is never broken; the tied group each receives the average of the ranks it occupies (e.g. two companies tied for what would be 3rd and 4th both receive 3.5). Only a tie in the final combined rank - which can arise even when neither individual input was itself tied - is broken, and only by ticker symbol, ascending. Section 3 now states this explicitly rather than implying individual-input ties are resolved the same way. No input, weight, eligibility rule, position or score changed as a result of this correction. |
| v1.0 | 29 September 2026 | Documentation correction, no formula/position/score change: Section 3's worked example previously stated that a company with an ROA of -1% "ranks exactly one position above" a company with an ROA of -2% (and likewise above -100%) - mathematically false whenever any other company's reported ROA falls between the two, or is tied with either, which is the ordinary case in a real universe of hundreds of companies. Rewritten to state only what is true: ROA is sorted in descending numerical order (P/E ascending), and the size of the resulting rank gap between two companies depends on the full eligible universe and tie handling, never on the size of the percentage gap itself. Also replaced an imprecise "ordered from best to worst" summary with the actual sort directions for each input. No input, weight, eligibility rule, position or score changed as a result of this correction. |
| v1.0 | 28 September 2026 | Documentation correction, no formula/position/score change: Section 5 and Section 7 described a lower numerical rank or position as "better" or "better-ranked" in several places, and one sentence inverted the relationship entirely (stating a higher Formula Score corresponds to a "higher (better-ranked) formula position", when a higher score in fact corresponds to a numerically lower position). All such phrasing has been replaced with precise, non-evaluative mathematical wording (e.g. "numerically lower rank", "lower combined rank"). Also removed Section 5's worked example naming a real company and stating its live calculation result, which read as a favourable illustration; Section 7's existing fictional worked example already demonstrates the same Component equations, including tied inputs, so no replacement example was needed. No input, weight, eligibility rule, position or score changed as a result of this correction. |
| v1.0 | 25 September 2026 | Documentation correction, no formula/position/score change: Section 5's description of the Quality-Factor and Value-Factor Components was misleading. It previously implied the Components use a separately computed "average rank" that differs from the main calculation's pe_rank/roa_rank. In fact the main calculation's pe_rank and roa_rank already use average-rank tie handling for any individual P/E or ROA tie, and the Components simply restate those exact same two numbers as a percentile - there was never a second, differently-computed rank. The only genuinely separate, additional tie-break step is ticker-ascending ordering, which fires only when the combined rank (pe_rank + roa_rank) itself ties, and never touches pe_rank/roa_rank or the Components. Rewrote the equations, added a worked example showing an individual P/E tie alongside a combined-rank tie, and fixed a cross-reference that pointed to the wrong section. Also corrects an imprecise verbal summary given elsewhere (not on this page) that described the 24 September ordering correction below as leaving "every non-position field byte-identical" - the correct, complete scope, exactly as already stated in the entry below, is: formula position changed for 88 of 503 companies, the displayed 0-100 score changed for 22 of those 88, and the two-observation historical average for each affected ticker shifted by exactly half a position as a result (the mean of its unchanged 23 September observation and its corrected 24 September observation) - pe, roa, name and every other input field were, and remain, unchanged. |
| v1.0 | 24 September 2026 | Correction, not a formula change: the ticker-ascending tie-break described in the 23 September entry below had been committed to the code but, like the ROA-scale fix from the same date, had not yet been exercised by a live daily calculation — today's calculation still reflected an earlier, non-deterministic tie order. Recomputed from the already-published P/E and ROA values and applied to the live 2026-09-24 calculation: 88 of 503 companies (17.5%) had their formula position relabelled by 1 to 3 places, always within a genuinely tied combined-rank group and never across one — for example LOW and RCL, both on combined rank 218, swap from positions 46/45 to the correct 45/46. Combined rank itself is unchanged for all 503 companies; no P/E, ROA, weight or eligibility rule changed. As a side effect of the relabelling, 22 of those 88 companies' displayed 0-100 Overall Formula Result also shifts by exactly 1 point, since that score is a rounded function of position. Verified end-to-end against the rankings API and CSV export with zero remaining ordering discrepancies. |
| v1.0 | 24 September 2026 | Two further corrections, no formula change. (1) A substituted P/E of 100 or ROA of 0 could not previously be told apart from a genuinely reported value of the same number (for example INTC's missing P/E displayed identically to a real P/E of exactly 100) — every formula result now carries a peSubstituted/roaSubstitutedflag, shown on the results table, company-detail page and in dedicated CSV columns, without changing any pe/roa/rank/combined_rank/formula_score value. Regression-tested against missing, genuine-100, negative, zero and very-high-P/E cases, and confirmed all 503 existing formula positions and scores are unchanged. (2) The historical export's "Minimum Observations" column was renamed "Target Observation Window" - it never meant that many observations were required before publishing a result (a 2-of-30 result was already being published correctly), but the old name implied otherwise. |
| v1.0 | 24 September 2026 | Three corrections, no formula change. (1) The 23 September ROA scale correction below had been committed to the code but had not yet been exercised by a live daily calculation — every currently displayed ROA figure has now been recalculated at the correct percentage scale; verified against real source samples for DECK, WAT and CRWD, and confirmed unchanged combined rank/formula position for all 503 companies before and after. (2) The trailing historical average now stores a dated observation per calculation and rebuilds the window from genuinely recovered daily calculations only — no day is ever manufactured, duplicated, or backfilled with a placeholder value; a partial window (fewer than 30 observations) is labelled with its true observation count everywhere it is shown, rather than presented as a complete 30-day average. (3) Corrected this page's prior claim that a missing P/E's fixed default (100) is "the least favourable value used anywhere" — it is not: any company with a genuinely reported P/E above 100 ranks less favourably on this input than a company with a missing P/E. This is a documentation correction only; the calculation itself is unchanged pending a formula-level decision on the intended policy. |
| v1.0 | 23 September 2026 | Correction, not a formula change: ROA was being carried at the wrong scale from source to display (a decimal fraction instead of a percentage), affecting only the displayed ROA figure — P/E-based rank, ROA-based rank, combined rank and formula position were unaffected, since ranking order is unchanged by a constant scaling factor. Tie-breaking on combined rank was also made explicitly deterministic (ticker, ascending) rather than relying on unspecified processing order. No input, weight or eligibility rule changed; historical formula positions are unaffected. |
| v1.0 | 22 September 2026 | Initial published version. No change to underlying calculation; introduces formal version labelling and public disclosure of the methodology. |
Any future change to the formula's inputs, weights, normalisation or eligibility rules will be recorded here with the previous version, the new version, the date, what changed, why, and whether historical results were recalculated. Historical results remain tagged to the formula version that produced them and are never reinterpreted under a later version.