Qtick
Sign in

Earnings personality

How QTick calculates the 2 metrics in this group — the real method named, then translated: what it tells you, how it is computed, and where it breaks down. None of these is a trigger to act.

Beat-again probability

How it's calculated

We take this stock's trailing beat rate over its prior up-to-8 earnings events (only when at least 4 prior events exist — otherwise no bucket) and assign it to one of four buckets: <=0.25, 0.25-0.5, 0.5-0.75, >0.75 (left-open, right-closed; the first bucket includes 0). We then query earnings_beat_base_rates for that bucket and read p_beat — the realized fraction of all historical announcement EVENTS (one observation per event, non-overlapping) in that same bucket that actually beat. That fraction is pBeatNext. The table validates itself out-of-time: it fits cell rates on events through T-12m, scores them on the last 12m (brier_model vs brier_climatology), and stores a verdict. If the verdict is not "persistent_skill" — or the bucket is empty or unavailable — the service serves the pooled climatology rate instead, with an honest flag, never a manufactured signal.

How it affects judgement

Strengthens a pre-earnings thesis when pBeatNext sits above the pooled base rate and cohort_multiple (cell rate / pooled rate, populated only on the persistent-skill path) is meaningfully above 1.0; weakens it when pBeatNext sits below the pooled rate. Neither alone is actionable — pair it with consensus_bias (does the street sandbag?) and reaction_asymmetry (does a beat even move the stock up?) before forming a view. When the flag reads "no persistent skill in beat persistence — pooled base rate", the bucket conditioning adds nothing statistically, so read it as climatology, not an edge.

What the current value signifies

pBeatNext is the realized historical beat frequency for this stock's bucket (or the pooled rate when no bucket-level skill is detected). A higher value means names in this trailing-beat-rate bucket historically beat more often; a lower value, less often. The exact pooled and per-bucket numbers are computed live from earnings_beat_base_rates and are not hard-coded — read the live value (and its flag/cohort_n) to know which regime you are in: a cell rate with verdict "persistent_skill", or the pooled climatology fallback.

Range

A probability in [0.0, 1.0]. By construction no cell can exceed 1.0 or fall below 0.0 (it is a fraction of events that beat). The specific pooled rate and per-bucket spread are NOT hard-coded — they are recomputed from the earnings_beat_base_rates window each run — so any concrete band would be illustrative, not code-true; cite actual figures only from a live DB read. Cells with too little history publish NULL (n=0) so consumers flag rather than imply.

The catch

The spine is survivor-tilted: a yfinance capture of (mostly) currently-listed names, large-cap-skewed (measured 2026-06: ~70% of megas vs ~5% of pennies have history). Delisted companies that missed repeatedly are absent, so the rates are conditioned on "still listed today" and run modestly optimistic versus a true full-universe base rate. The window is whatever the intel_earnings_events spine covers (exposed as window.start / window.end), not a fixed start year.

Sells the news

How it's calculated

For every past earnings beat (EPS actual > estimate), we record the stock's price reaction that day. `avg_reaction_beat_pct` is the mean of those reactions. The flag `sells_the_news=True` fires only when three gates all clear: at least 4 beats are on record, the mean reaction is below -0.5%, and a one-sample t-statistic (mean / (sd/sqrt(n))) is <= -1. A bare negative sign never qualifies. Two edge cases sit alongside the main path: if the recorded beat reactions show zero variance (sd = 0, every beat sold off the same), the flag fires on the material mean alone without computing a t; and if the dispersion (sd) was never recorded for a row, the result is null, not False.

How it affects judgement

A confirmed "sells the news" pattern means the market has historically priced in the beat before the announcement, so even good numbers produce selling pressure. That weakens a thesis that leans on a clean earnings catalyst; the reaction history becomes evidence the catalyst may already be in the price. No pattern (False or None) neither confirms nor negates a catalyst view.

What the current value signifies

True = the stock has a statistically supported habit of declining on beats (mean beat-day return below -0.5%, t <= -1 over >=4 events; or zero-variance beats that all sold off). False = enough beats on record but no such pattern. Null = fewer than 4 measured beats, or the dispersion (sd) was never recorded for the row, so the result is undetermined, not a clean bill of health.

Range

Boolean with a null state: True / False / null (undetermined). The underlying `avgReactionBeatPct` is a percentage. Typical stocks cluster near 0%; outliers reach roughly -5% to +5% on earnings days. The t-threshold is fixed at -1, a modest bar chosen deliberately given thin n.

The catch

The universe skews toward currently-listed, large-cap names (roughly 70% mega-cap vs ~5% pennies per the coverage note); delisted companies are absent, so the base rates carry a survivorship tilt. Thin beat histories (n=4-6) make the t-statistic noisy, so the flag can trip on a short streak that later reverts.

See these metrics live on a stock dossier

QTick shows cited data and code-computed models for self-directed research. Nothing here is a recommendation, solicitation, or investment advice. Where a metric’s live data pipeline is under review, its method is described but its current value is withheld rather than shown as reliable.