There are a few gray areas in your specifications.
“…fairly tight price range…”
“…defined trading range…”
“…smal daily trading ranges…”
Perhaps you have more specific definitions for these. Something that is based on an existing study, or at least something that can be expressed mathematically.
So given the items that are black and white, I drew up the following code to run scans. Attached is a screenshot showing the stock you listed during the reference period. The lower subgraph shows how the code views the price action. The areas shaded in blue are what the code believes to be “defined ranges”. The code I list here is strictly for scans, not intended to plot on a chart. It’s important to note that the first input needs to be a greater value than the last input.
input spanOfBase = 25;
input maxPrctCorrection = 10;
input spanOfBreakoutHigh = 42;
def flatBaseHigh = highest(high[1], spanOfBase);
def flatBaseLow = lowest(low[1], spanOfBase);
def percentMaxCorrection = AbsValue(100 * (flatBaseLow / flatBaseHigh - 1));
def withinPrctCorrectionLimits = percentMaxCorrection <= maxPrctCorrection; def highShade = if withinPrctCorrectionLimits then flatBaseHigh else flatBaseLow; def lowShade = if withinPrctCorrectionLimits then flatBaseLow else flatBaseHigh; def flatBase = highShade > lowShade;
def highestHighForBreakout = highest(high[1], spanOfBreakoutHigh);
def currentBreakoutHigh = high > highestHighForBreakout;
# only one of these can be scanned for at one time. Use "#" comment marks to turn off
# the one you don't need
plot flatBaseFormation = flatBase and currentBreakOutHigh == 0;
#plot breakOutSignal = currentBreakOutHigh and currentBreakOutHigh[1] == 0 and flatBase;
The scan runs in two different modes. One searches for current flat base formations. Use this to study the resulting patterns and decide if further adjustments are needed to the code. The second searches for the actual break out signals.