I measured 8,000+ forward returns on my own trading signals. Most of what I believed was wrong — and the part that survived, I nearly deleted as a bug.

MRdata · research note 01 · July 2026

Nothing here is financial advice. It's a measurement log from one system, one market, one seven-week window. All figures independently re-verified against the data lake as of 5 July 2026.


For the past two months I've been running an automated pipeline over a ~184-ticker ASX small-cap watchlist. Every morning it scrapes announcements from two independent sources, pulls a year of OHLCV per ticker, and — the part I care most about — scrapes broker-level net flow across five broker-group panels: resource-specialist brokers, investment banks, market makers, retail brokers, and wealth/advisers. A deterministic classifier turns each day's tape into a signal tier per ticker, an LLM layer writes the narrative (it never overrides the label), and every signal gets stamped with +1/+5/+10/+20-session forward returns as they mature.

That last part is the point of this note. Signals are cheap. I now have 8,244 outcome rows, which means I can stop having opinions and start counting. So I backtested the things I believed about my own system.

Method, briefly

  • Window: 15 May – early July 2026. All stats exclude day 0 (14 May), which ran legacy classifier code.
  • Point-in-time discipline everywhere: momentum, baselines, and filters only use data available on the signal date.
  • Episode dedupe where noted: one entry per ticker per 14 days (a ticker firing ten days straight is one bet, not ten).
  • Baseline matters: over this window the watchlist itself was falling — universe median forward return was −2.6% at 5 sessions and −8.3% at 20 (n=6,140 / 3,455). Every claim below is relative to that, not to zero.

Belief 1: my flagship signal has an edge. (No.)

The classifier's top tier — call it STAR: institutional cross-group buying plus a genuine price-sensitive catalyst — fired on 66 tickers in the window. First-fire forward returns: 33% win rate, median −2.7% at 5 sessions. The universe baseline: 33% win, −2.6%. Statistically indistinguishable from throwing darts at my own watchlist.

The winners were real (best first-fires: +42%, +25%, +20%, +13% at 5d). They were fully paid for by the losers (−23%, −21%, −17%). Ratio magnitude at fire time didn't predict which was which.

Belief 2: the classifier separates good flow from bad. (Half yes — the bottom of the ladder works.)

The tier ordering is real, just not where I wanted it. The rejection tiers underperform hard and consistently: market-maker-only flow ran a −10.4% median at 5 sessions; retail-only flow −4.5%, decaying to −14% at 20. And the cruelest cell in the dataset: retail buying an oversold name while institutions stand aside — 6% win rate at 20 sessions, median −17% (n=31). The classifier reliably identifies what not to touch. That's a genuine, measurable result — it's just the unglamorous half of the system.

Belief 3: low RSI + high volume marks the turn. (Only under one condition — keep reading.)

My strongest prior: oversold stock, volume arrives — coiled spring. First pass said no, emphatically:

Cut (5-session forward) Episodes Win% Median
Watchlist baseline 33% −2.6%
RSI<40 + volume ≥2× average 83 28% −5.5%
… + drilling/activity news in the prior 14d 11 22% −11.8%

Volume at the lows, especially right after news, was distribution with an audience. The down-day version was the single worst pattern I found: spike on a red day ran a 9.5% win rate at 20 sessions.

I nearly closed the case there. Then I checked my own dashboard and it disagreed with me.

The bug that wasn't: how I accused my own site and lost

My public site has a pattern-conditioner page. It showed one cell — resource specialists AND investment banks both net-buying, RSI<40, volume ≥2× — at 83% win, median +21.5%. My backtest of "the same thing" said 45%, −1.1%. Same winners in both, but the page was excluding five qualifying rows, every one a double-digit loser. I wrote up the "survivorship bug," drafted the fix order, and got ready to publish the mea culpa.

The dashboard was right. I was wrong.

The page's pattern has a condition my reproduction didn't: no price-sensitive announcement in the prior 7 days. Every "dropped" row failed it — a trading halt, a high-grade assay, a reinstatement, a maiden target. All news-driven volume. The filter is point-in-time legitimate (you know on the day whether there was recent news), so it's not look-ahead — it's a design decision I'd forgotten my own exporter made, and it turns out to be the entire ballgame:

Same pattern (Res+banks ≥$5k same day, vol≥2×, ret 5d) n Win% Median
RSI<40, quiet (no PS news prior 7d) 6 83% +21.5%
RSI<40, quiet filter removed 10 50% +1.9%
ANY RSI, quiet 18 61% +5.0%
ANY RSI, not quiet 32 50% +1.6%

Which also reconciles Belief 3's wreckage: my "with drilling news" cut was conditioning on recent news — the exact opposite of quiet — and those names bled −11.8%. Both results are one finding viewed from opposite sides: volume at the lows after news is distribution; volume at the lows before news is accumulation. The tape only means something when you know whether the market has already been told the story.

Two lessons, and the second one stings more. First: the discriminating variable in a flow pattern may not be the flow. Second: I was fully prepared to believe my pipeline was silently wrong — I'd found real bugs before — and much less prepared for the possibility that the pipeline remembered my own design better than I did. Adversarial self-review cuts both ways.

One more cell I'm watching, not claiming

Institutions who had been net sellers flipping to net buyers: 58% win, median +5.1% at 5 sessions, +5.2% at 10. Twelve episodes — too few to claim, and it's the cell most exposed to a known labelling flaw (counterparty absorption of large exits reads as "buying"), which is my next fix. It earns its way in clean or not at all.

What happens next

The quiet-accumulation cell is n=6 and I found it by toggling filters until something shone — the textbook way to fool yourself. So it gets the only treatment that means anything: pre-registration. From today I'm tracking, out of sample, the exact definition the site already implements: resource specialists AND investment banks both net-buying ≥$5k on the same day, volume ≥2× average, no price-sensitive announcement in the prior 7 days — with the RSI<40 subset reported alongside. The running tally goes on the site either way. If it dies in public, that's the content.

Also queued: the exit-churn relabel and a substantial-holder exit/becoming split — the two flaws most likely to be polluting the flip-buyer cell above.


I'm building this solo — scraping, classifier, forward-return measurement, the site. If you're building something similar (LLM-assisted market-data pipelines, any exchange), I'd like to compare notes: mrdatadec@gmail.com.

One email per market day. Zero when nothing happened.

Just the letter. No promotion, unsubscribe anytime.