Skip to content
Dog on a Leash
Setups2 min read

The gap-down filter earned its keep

The single cheapest line in the screen is the one that throws out overnight gaps. Last week it excluded four names and every one of them kept going.

Published

Of all the filters in the screen, the one that does the most work per line of code is also the least clever:

gapped = df["overnight_return"].abs().rolling(5).max().gt(0.15)
screen = screen[~gapped]

Throw out anything whose extreme z-score was manufactured by a single session’s gap. That is it.

Why it works

A stock that ground down 18% over six weeks and a stock that fell 18% in one overnight gap have identical z-scores and completely different distributions of what happens next.

The grinder is a candidate. Nothing changed in what is known about the company; the price drifted away from an anchor that stayed put. That is the setup.

The gapper is a company where something is now known that was not known before. The market repriced it in one move, deliberately, on new information. The mean has moved — your rolling 50-day window simply has not caught up yet, and it will not for weeks. The enormous z-score is an artifact of measuring a new distribution with an old ruler.

Last week

Four names cleared every other filter and were excluded by this one. All four continued lower over the following sessions. That is a small sample and I would not draw a conclusion from one week — but it is the shape the filter is designed around, and it is worth logging when the design behaves as designed.

The more useful number is the cost. The filter also excludes genuine overreactions: real cases where the market panicked overnight and the price came back. Those are given up. That is the price of avoiding the structural repricings, which take a year to recover from if they ever do.

I take that trade every time, because the two errors are not symmetric. Missing a bounce costs opportunity. Buying a structural repricing because it looked statistically stretched costs capital, and it costs it in the size that makes a year hard to recover from.

Tuning it

Three parameters worth thinking about rather than copying:

  • The threshold (15%). Should scale with the universe. For large-cap names it is too loose; for small-cap biotech, far too tight.
  • The window (5 days). Long enough that a gap two sessions ago still disqualifies the name, short enough that a gap from last quarter does not.
  • Direction. I filter on absolute overnight return, not just down-gaps. A violent up-gap distorts the standard deviation in the denominator just as badly.

The general principle

The best filters in a screen are not the ones that find opportunities. They are the ones that remove the situations where the underlying assumption is false.

This screen assumes there is a stable mean to revert to. Every filter in it exists to test that assumption in a different way, cheaply, before any money is at risk.

Nothing here is investment advice. Every parameter above is a starting point to be tested against your own universe and horizon.

This post is research and opinion for educational purposes only. It is not investment advice and not a recommendation to buy or sell any security. Full disclaimer.