Parameter Plateau Map - Moving Average Crossover RobustnessEvery backtest has a best setting. The question almost nobody asks is whether the settings next to it were any good — and that question is the whole difference between an edge and a coincidence.
WHAT IT DOES
It sweeps a grid of fast/slow moving average pairs, scores all thirty valid combinations on the same data, and draws the result as a heatmap. What you are looking for is not the brightest cell. It is the shape around it.
A broad, coherent region → the result survives changing the parameters.
A single bright cell → you found noise and gave it a name.
THE PLATEAU SCORE
The heatmap makes the shape visible; this puts a number on it. It compares the best cell to its four immediate neighbours, both measured against the grid's own mean:
Plateau = (mean of neighbours − grid mean) ÷ (best − grid mean)
Near 1.00, the neighbourhood is nearly as good as the peak, so the peak is a ridge you can actually stand on. Near 0.00, the peak stands alone above an otherwise ordinary grid, and selecting it is curve fitting.
Measuring against the grid's own mean rather than a fixed 50% is deliberate. In a strongly directional window every cell shifts together, and a peak-versus-50% ratio would either explode or collapse on that shift alone. The shape of the surface is the question here, not its height. Height gets its own row.
HOW EACH CELL IS SCORED
Directional hit rate. On every bar in the window a cell votes long when its fast mean is above its slow mean, and the vote counts as correct if price moved that way over the next N bars. 50% is a coin flip.
Means come from a running cumulative sum, so a 233-length mean costs exactly what a 5-length mean costs. That is what keeps a thirty-cell sweep cheap enough to recompute live rather than making you wait.
READING THE VERDICT PANEL
Best pair — the winning fast/slow combination and its hit rate.
Best vs chance — how far that winner sits above or below 50%. This is the level question, kept deliberately separate from the shape question, because they have different answers surprisingly often.
Plateau — the shape. This is the headline.
Grid mean — where the whole surface sits. If this is far from 50%, the window had a strong directional character and every cell inherited it.
Best to worst — the spread across the grid, in percentage points.
Reading — PLATEAU, RIDGE, or SPIKE, so the number does not need interpreting mid-session.
Sample — bar count and, next to it, the roughly independent sample size. Overlapping forward windows mean 250 bars at a 10-bar horizon is closer to 25 independent observations than 250. That second number is the one that should govern how much you trust any of this.
WHAT IT SHOWS RIGHT NOW
On BTCUSD 1h at the time of writing: Plateau 0.86 — a smooth, well-behaved surface with no isolated spike — while Best vs chance reads −3.2 pp and the grid mean sits at 38%. Every one of the thirty settings scored below a coin flip, and they did so coherently rather than randomly. ETHUSD 1h looks much the same, best pair 49.2%, grid mean 40.4%.
That combination is worth sitting with. The parameter surface is not noisy at all. It is simply, consistently, unprofitable over this window — which is a far more useful thing to learn than which of thirty losing settings lost least.
HONEST LIMITS
A hit rate is not a P&L. It ignores position size, cost, slippage, and the size of the moves it is counting. A 55% hit rate that is right on small moves and wrong on large ones loses money.
The effective sample is small. Overlapping windows are correlated, so treat the independent figure in the Sample row as the real one, and treat a few percentage points of difference between cells as noise.
This measures one specific and rather crude strategy family. A flat or losing surface says moving average crossovers did not work here over this window. It does not say nothing works.
Widening the step ladder until the peak looks impressive will collapse the Plateau score, which is precisely what it is there for.
NO REPAINT
There is no request.security call anywhere in this script, so the higher-timeframe lookahead problem does not arise. Every cell is scored on bars that had already closed, the forward return grading a vote is always taken from bars after that vote and before the present, and only confirmed bars enter the sample.
Open source under MPL 2.0. Read it, fork it, tell me where I am wrong.
Indicator


