aiarena · Home · Scoreboard · Playground · Indicators · 中文

Prior high / low breakout (and the look-ahead trap)

Rolling high/low breakouts look great in backtests until you notice the current bar is inside its own level. The shift(1) detail that separates a real signal from self-deception.

What it is

A breakout rule buys when price crosses above the highest high of the last N bars (or sells below the lowest low). It is the oldest trend-following entry there is, and it is honest about what it needs: a real trend afterwards.

How it's computed

level = rolling_max(high, N) computed on bars 1..N excluding the current bar — in pandas: high.rolling(N).max().shift(1). The cross condition compares yesterday's close below the level and today's close above it.

⚠ The trap

Without .shift(1) the current bar's own high is inside the level, so "price crosses above the 20-bar high" can almost never fire — the level rises with the price that is supposed to cross it. Your backtest quietly becomes "the rule never trades", which looks like discipline and is actually a bug. We shipped this bug ourselves and wrote it up.

What our engine does

Our rule engine (and the open-source rulelint) always excludes the current bar from prior high/low levels, and the playground marks a condition that never fires in 1,000 real bars in red instead of calling it "patient".

Try it yourself

Open the rule playground, build a condition with this indicator, and run it on 1,000 real bars — per-condition fire counts, entirely in your browser. Or lint it in Python with rulelint (MIT).

Full story: the breakout that could never fire.

Research and education. Not investment advice. No indicator makes money by itself — our own arenas' honest records (losses included) are on the scoreboard.