Revenue Forecasts: method notes
Walk of Grit · Kareem Powell · built 2026-10-30. Paper trading only. This is not investment advice.
All numbers on the Revenue Forecasts page come from one published data file, revenue_forecasting.json. Each company is a sub-tab under that page, for example ServiceNow (NOW), and reads the same data.
In plain terms: Revenue Whisperer missed actual revenue by 0.79% on average in back-tests
Revenue Whisperer forecasts next-quarter revenue for ten software companies and estimates what each company's shares could be worth in 12 months.
- Forecast: Forecasts next-quarter revenue for ten software companies, plus a 12-month share-price estimate for each.
- Back-test: Rebuilt past quarters using only the information available at the time. Revenue Whisperer's main approach missed actual revenue by 0.79% on average, against 2.37% for company guidance taken at face value and 2.48% for weighted peer comparisons.
- Method: Starts from each company's guidance midpoint and adds the amount it usually came in above guidance over the prior four quarters, because companies tend to do so by a fairly steady amount.
- Practice Trades: Places practice trades with no real money to test whether the forecasts would have made money.
Terms used below, in one line each:
- MAPE (average miss): how far a forecast landed from the real number, as a percentage, averaged over many quarters. Lower is better.
- Guidance + usual amount above guidance: the company's own revenue forecast, plus the amount by which revenue has usually come in above that forecast.
- Consensus: the average forecast from Wall Street analysts.
- Model value and upside: our estimate of what a share could be worth in 12 months, and how far that is above or below today's price.
- 80% band (expected range): a range we expect the real number to land in 8 times out of 10.
- Back-test: replaying past quarters in order, using only what was known before each one.
- Paper trade: a practice trade with no real money.
The technical detail follows.
1. Universe and data (every number has a source)
| Item | Source |
|---|---|
| Tickers | CRM, NOW, ADBE, SNOW, DDOG, CRWD, HUBS, WDAY, MDB, ZS. All are tradable and fractionable on Alpaca /v2/assets. |
| Daily prices | Alpaca Market Data v2 /v2/stocks/bars (SIP, adjustment=all) |
| Quarterly revenue (actual) | SEC EDGAR companyfacts XBRL: RevenueFromContractWithCustomerExcludingAssessedTax, then …IncludingAssessedTax (CRWD), then Revenues. Only 80–100-day durations are used. Q4 = FY − (Q1+Q2+Q3). |
| Management guidance | Next-quarter revenue range in each 8-K Item 2.02 earnings press release (Ex. 99.1) on EDGAR. The URL and the quoted sentence are stored per release. Segment guidance (NOW subscription, SNOW product, WDAY subscription) is converted to total using the total/segment ratio reported in the same release. |
| Diluted shares | XBRL WeightedAverageNumberOfDilutedSharesOutstanding, latest quarter |
| NRR (comps feature) | Only used where the 10-Q discloses it: SNOW 126%, DDOG 120%, MDB 122% (net ARR expansion). The source quotes are in the JSON. |
| Street consensus | stockanalysis.com forecast pages. This is a reference only and is not used in the model or the back-test. |
| News | Alpaca News API (Benzinga) and Google News RSS headlines |
No figures were typed in by hand. If a source is missing, the field is null.
2. Revenue models
Let R_t be quarterly revenue and h the forecast horizon.
(a) Management guidance. G_t = midpoint of the next-quarter range.
(b) Guidance + usual amount above guidance. SaaS management guides conservatively, so the guidance midpoint is scaled by the company's own average amount above guidance over its prior four quarters. Only amounts known at the forecast date are used.
G*_t = G_t · (1 + b̄), b̄ = mean_{last 4}(R_actual / G − 1)
(c) Weighted market comps. Each peer j gets a similarity weight to the target i. The weight uses log TTM revenue (scale), YoY growth, and NRR when both companies disclose it. Each dimension is z-scaled by its cross-sectional standard deviation, and NRR uses a 5-point bandwidth:
w_j = exp(−½·[(Δsize/σ_size)² + (Δgrowth/σ_g)² + (ΔNRR/5)²]), ĝ = Σ w_j·g_j / Σ w_j, C_t = R_{t−3}·(1 + ĝ)
The forecast applies the weighted peer YoY growth to the target's same quarter last year. Only peer data released before the forecast date is used.
(d) Holt damped trend. SaaS revenue is seasonal, so Holt is run on YoY log growth g_t = ln(R_t / R_{t−4}) over the last 12 observations:
ℓ_t = α·g_t + (1−α)(ℓ_{t−1} + φ·b_{t−1})
b_t = β·(ℓ_t − ℓ_{t−1}) + (1−β)·φ·b_{t−1}
ĝ_{t+h} = ℓ_t + (φ + φ² + … + φ^h)·b_t, R̂_{t+h} = R_{t+h−4}·exp(ĝ_{t+h})
The parameters (α ∈ 0.1…0.9, β ∈ {.05, .1, .2, .3}, φ ∈ {.8, …, .98}) are grid-searched on one-step SSE. Damping (φ < 1) flattens the growth trend over time. This fits mature SaaS, where growth decelerates as companies scale.
(e) Blend and the smoothed prediction line.
B_t = 0.50·G*_t + 0.25·C_t + 0.25·H_t (if comps are unavailable, G*_t takes the comps weight)
The forward line takes B for the next quarter. For quarters +2 to +4, it uses the Holt path rescaled so it passes through B: R̂_{t+k} = H_{t+k}·(B_{t+1}/H_{t+1}). This produces the smoothed dashed line on the page.
(f) Prediction intervals. σ is the sample standard deviation of the back-test log errors ln(R/B) for each company. The interval at horizon k is
R̂·exp(±z·σ·√k), z = 1.2816 (80%), 1.96 (95%).
3. "Positive Override" sentiment and SEO framing
"Positive override" comes from Kareem's post Navigating Tough Times (Tarantino via Billy Oppenheimer). It means overriding the first negative reaction to a setback and reframing it as an opportunity, "not by being overly optimistic". The score encodes that idea directly. It also draws on two lines from Kareem's other writing: "valuation reflected economic reality — not our hopes or dreams", and the warning against false confidence.
| Lexicon | Weight | Examples |
|---|---|---|
| POS | +1.0 | came in above, raise, accelerating, record, momentum |
| NEG | −1.0 | miss, cut, plunge, slowdown, headwinds, worst |
| OVERRIDE (reframing a setback) | +1.5 | rebound, turnaround, recover, overdone, buying opportunity, lessons, despite, back on track |
| GRIT (durable execution) | +1.25 | durable, discipline, consistent, execution, free cash flow, long-term |
| HYPE (false confidence) | −0.5 | soar, skyrocket, no-brainer, bubble, must-buy, "next Nvidia" |
These rules adjust the raw score:
- Override mechanic: if a story contains both negative terms and override terms, the negative weight is halved. The setback is acknowledged, then reframed.
- Hype penalty: if hype terms appear in a positive story, the positive score is halved.
- Article score: s = tanh(raw/3) ∈ (−1, 1).
SEO framing features (from the headline):
- Keyword prominence: 1.0 if the company is named in the first 10 characters, 0.6 if it appears later, 0.3 if it isn't named or the article is a multi-ticker roundup.
- Question or uncertainty framing ("Is…?", "Why…"): weight ×0.8.
- Superlative count.
- Override/negative ratio.
Aggregate:
S = Σ w·s / Σ w, w = 0.5^(age/7 days) · prominence · question factor
Duplicate titles are removed.
Centering. News tone is structurally positive, so the model only reacts to unusual tone: S_c = S − (mean of all earlier back-test windows). The back-test windows run from release −21 days to release +1 day, and the mean is only applied once there are 5 or more windows. The live model score uses the same recipe (Alpaca news, 21 days). The broader 30-day score on the page, which includes Google News, is for display only.
Revenue tilt: B = B_nosent·(1 + κ·S_c) with κ = 0.02, a maximum tilt of ±2%.
Caveat: the historical windows all sit around earnings releases, so the baseline (≈0.137) is earnings-heavy. Today's off-cycle news therefore centers slightly negative, though the effect on revenue is at most a few tenths of a percent. In the back-test, raw sentiment correlated with revenue surprise at only about 0.16. Sentiment is a framing signal for the stock, not a revenue driver, which is why κ is small.
3b. X post sentiment (added Oct 31, 2026)
Revenue Whisperer also reads public X posts about each company. It never reads private or account data.
- Data: Pulled public posts through X API search (cashtag or company name, English only, no reposts, up to 25 of the most relevant posts per search call). Used three calls per company for the live window, up to 75 posts before removing duplicates, and collected 593 live posts across 10 companies from Oct 24 to Oct 30 or 31, 2026 (each company's dates are in the table below). Used one call per back-test window, up to 25 posts each, and collected 3,086 back-test posts from two windows covering the 30 days before each of the 80 back-test forecast dates, never after the date.
- Post score: Scored each post with VADER (Hutto & Gilbert, 2014), a sentiment model built for social media, plus a short list of finance terms VADER lacks (came in above, miss, upgrade, downgrade, bullish, bearish, plunge, layoffs and similar). Each post gets a compound score c from −1 to 1; posts with c ≥ 0.05 count as positive and posts with c ≤ −0.05 as negative.
- Engagement weight: Weighted each post by w = 1 + ln(1 + likes + reposts), so widely shared posts count more and posts with no engagement still count. Calculated the positive and negative shares on each tab with these weights (the sum of w over positive or negative posts divided by the sum of w over all posts), not as raw post counts. Dropped duplicate posts and spam posts that list 5 or more cashtags.
- Negative-weighted net: Combined post scores into N = Σ w·(c⁺ − λ·c⁻) / Σ w, where λ is the weight on negative tone. Research on financial text (Tetlock, 2007; Loughran & McDonald, 2011) finds negative words carry more information, so λ values from 1 to 3 were tested. The earlier back-test quarters picked λ = 1.0, because heavier negative weights raised the average miss.
- Positive–negative correlation: Measured ρ, the correlation between VADER positive and negative intensity, across Eastern-time days (5 or more days with 3 or more posts) and across individual posts otherwise. When both rise together, the chatter is contested rather than one-sided, so the signal shrinks: X = (1 − s·max(0, ρ))·N, with s = 1.0.
- Centering and blend: Centered X on the mean of all earlier back-test windows (point in time, 5 or more windows needed), then blended it with the centered news tone: S = 0.9·S_news + 0.1·X_c. The revenue tilt is B = B_nosent·(1 + κ·S) with κ = 0.02, still capped at ±2%.
Back-test: Ran point in time on 80 company-quarters, 74 of them with an X baseline. Chose the parameters on the first 4 of 8 quarters for each company and checked them on the last 4.
| Average miss (MAPE) | No sentiment | News tone | News tone + X |
|---|---|---|---|
| Earlier 40 quarters (used to choose parameters) | 1.106% | 1.134% | 1.133% |
| Later 40 quarters (held out) | 1.055% | 1.029% | 1.032% |
| All 80 quarters | 1.081% | 1.082% | 1.082% |
Result: The earlier quarters favored a 50% X weight, but that weight raised the held-out miss to 1.048%. X sentiment pointed the right way in only 37 of the 74 quarters with an X reading (50%), meaning its sign matched whether actual revenue came in above the news-only forecast, so it did not improve accuracy. Revenue Whisperer keeps X sentiment at a 10% weight, where it changes forecasts by a few hundredths of a percent.
Live X readings (Oct 24 to Oct 30 or 31, 2026; positive and negative shares are weighted by likes and reposts):
| Ticker | Window | Posts | Positive | Negative | ρ (pos vs neg) | Tilt, news only | Tilt, news + X |
|---|---|---|---|---|---|---|---|
| CRM | Oct 24–Oct 30 | 73 | 71% | 16% | -0.16 | -0.17% | -0.14% |
| NOW | Oct 24–Oct 31 | 55 | 44% | 24% | -0.41 | -0.14% | -0.14% |
| ADBE | Oct 24–Oct 31 | 65 | 39% | 24% | +0.02 | -0.22% | -0.23% |
| SNOW | Oct 24–Oct 31 | 73 | 42% | 28% | -0.35 | -0.15% | -0.16% |
| DDOG | Oct 24–Oct 30 | 55 | 65% | 20% | -0.48 | +0.26% | +0.25% |
| CRWD | Oct 24–Oct 30 | 57 | 47% | 20% | -0.68 | -0.24% | -0.23% |
| HUBS | Oct 24–Oct 31 | 69 | 55% | 29% | +0.29 | -0.31% | -0.30% |
| WDAY | Oct 24–Oct 30 | 40 | 45% | 11% | -0.47 | -0.31% | -0.28% |
| MDB | Oct 24–Oct 30 | 70 | 60% | 20% | -0.17 | -0.09% | -0.08% |
| ZS | Oct 24–Oct 30 | 36 | 70% | 8% | +0.31 | -0.23% | -0.21% |
Limits: The X API returns at most 25 posts per search call (three calls per company live, one per back-test window), so each window is a relevance-ranked sample, not every post. Bots and promotional accounts remain after filtering, and VADER misreads some sarcasm and finance slang.
4. Price model ("predicted price line")
- Fair value: Fair_t = median P/S over the trailing 252 trading days × TTM revenue known at t (point-in-time, using release dates) ÷ diluted shares.
- 12-month path: median P/S × forward TTM revenue from the forecast path. The band uses the P/S interquartile range.
- Paper-trade score: z(model upside) + 0.5·z(centered sentiment). Names with score > 0 are bought with notional $2,500 + $2,500·score/max score. Limits are $5,000 per name and $40,000 in total.
5. Back-test (one-step-ahead, last 8 quarters per company, point-in-time)
Pooled MAPE, 10 companies × 8 quarters:
| Method | MAPE |
|---|---|
| Management guidance (raw midpoint) | 2.37% |
| Guidance + usual amount above guidance | 0.79% |
| Weighted comps | 2.48% |
| Holt damped trend | 1.75% |
| Blend (no sentiment) | 1.08% |
| Blend + news tone | 1.08% |
| Blend + news tone + X posts (current) | 1.08% |
MAPE by company (%):
| Ticker | Guide | Guide adj. | Comps | Holt | Blend no-sent | Blend |
|---|---|---|---|---|---|---|
| CRM | 0.55 | 0.43 | 2.61 | 1.48 | 0.88 | 0.89 |
| NOW | 0.97 | 0.85 | 1.69 | 1.57 | 1.05 | 1.16 |
| ADBE | 1.52 | 0.47 | 1.81 | 0.57 | 0.45 | 0.50 |
| SNOW | 4.01 | 1.19 | 4.18 | 1.69 | 1.53 | 1.59 |
| DDOG | 4.08 | 0.56 | 3.58 | 1.00 | 1.34 | 1.20 |
| CRWD | 1.68 | 0.90 | 0.92 | 1.77 | 0.81 | 0.84 |
| HUBS | 2.69 | 0.67 | 2.92 | 2.09 | 1.15 | 1.14 |
| WDAY | 0.69 | 0.76 | 3.90 | 0.91 | 1.04 | 0.93 |
| MDB | 5.30 | 1.27 | 2.20 | 4.65 | 1.74 | 1.66 |
| ZS | 2.22 | 0.79 | 0.97 | 1.81 | 0.80 | 0.89 |
6. Recommendation: internal forecasts vs weighted market comps
Revenue Whisperer anchors next-quarter SaaS revenue on the company's own guidance, adjusted for how far results usually came in above it. That approach had a 0.79% MAPE, against 2.48% for weighted comps and 2.37% for raw guidance, because management sees backlog, RPO and billings that outsiders can't. Use weighted comps (scale, growth and NRR similarity) and damped-trend Holt as an independent check, and as the main tool beyond the guided horizon or for private companies, where guidance doesn't exist. A 50/25/25 blend gives up a little accuracy (1.08%) in exchange for robustness when a company changes its guidance style. Keep sentiment and SEO framing as a small tilt and a trading signal, not a revenue input, because it added no accuracy (1.08% → 1.08%).
7. Limitations
- Sample Size: 8 quarters × 10 large-cap names.
- Guidance Parsing: Regex-based. Workday's releases from 2023-11 and 2024-02 were not parsed.
- Consensus Data: Comes from a third-party site.
- Valuation Multiples: P/S multiples are mean-reverting only over long horizons.
- Paper Fills: No slippage modeled. NOW's position is sized partly because of a single-day drop of about 27% on 2026-10-29.