Newsletter
Article Library
Videos
What's New
About Us
Site Map
Search

 

 

The Breakout Bulletin

The following article was originally published in the August 2003 issue of The Breakout Bulletin.
 

Quantifying Consolidation Patterns

In the March 2003 issue of this newsletter I presented a method for identifying chart-based support and resistance levels and included the EasyLanguage code for programming the method. This month, I'm going to do the same thing for consolidation patterns. By consolidation pattern, I mean a trading range where the price bars tend to form a rectangular pattern on the chart. For example, in Figs. 1 and 2, I've identified several consolidation patterns by drawing a white rectangle around them.

 

Consolidation patterns

 

Figure 1. Three consolidation patterns have been identified on this chart of the E-mini S&P.
 
 
Consolidation patterns
 
Figure 2. Two additional consolidation patterns have been identified on this chart.

 

Consolidation patterns can also form other shapes, such as flags and triangles. Usually, a consolidation pattern occurs after a large move. In his book, "7 Chart Patterns That Consistently Make Money," Ed Downs (see reference) cites consolidation patterns as the best tool to predict market direction. There are typically two methods for trading these patterns. You can enter on a breakout from the pattern by buying when the market moves above the upper boundary or selling on a downside breakout below the lower boundary. The second method is to trade within the pattern by selling at the upper boundary and buying at the lower boundary.

 

For the purposes of this article, I'm going to restrict the definition of consolidation patterns to horizontal trading range patterns, such as those shown in Figs. 1 and 2. To quantify the definition, I'm going to say that a consolidation pattern is a sequence of bars on the chart where the "density" of the bars is greater than some threshold. To understand what I mean by "density," imagine drawing a rectangle around the price bars in the consolidation pattern, as I've done in Figs. 1 and 2. The rectangle surrounds the highest high and the lowest low of the bars in the pattern. The more completely the bars fill up the rectangle, the higher the density.

 

 

Densest consolidation pattern

 

 Figure 3. A rectangle bounds a consolidation pattern with the highest possible density.

 

 

The highest possible density for a rectangular consolidation pattern is shown in Fig. 3. In this case, every bar spans the full height of the bounding rectangle. In physics, density is defined as mass per unit volume; the more mass contained within a given space, the higher the density. In our definition, the more bar area within the bounding rectangle, the higher the density. The "bar area" of the pattern can be defined as the sum of the heights of the bars within the bounding rectangle. By bar height, I mean the high minus the low or, to take gaps into account, the true range.

 

The area of the bounding rectangle is the number of bars in the pattern multiplied by the highest high minus the lowest low of the bars in the pattern; i.e.,

 

    Area (bounding rectangle) = N * (Highest High - Lowest Low)

 

where N is the number of bars in the pattern. By this definition, the area of the bounding rectangle is the same as the bar area for the densest pattern, shown in Fig. 3.

 

The density of any pattern of price bars can now be defined as the bar area divided by the area of the bounding rectangle; i.e.,

 

    Density = Sum of true ranges / [N * (Highest High - Lowest Low)].

 

By this definition, the pattern shown in Fig. 3 will have a density of 1. This is the highest possible density. Any other pattern will have a density value less than 1. The more completely the bars fill up the bounding rectangle, the closer the density will be to 1. Also note that since we've normalized the bar area by the area of the bounding rectangle, the density value is independent of the number of bars, so we can compare consolidation patterns with different numbers of bars.

 

Now that we can calculate the density of a consolidation pattern, how do we identify those patterns? The key concept is that we're going to restrict our search for consolidation patterns to the current bar. We want to know if the current bar is part of a consolidation pattern. We could, in principle, extend the search to past price patterns, but since we can't trade in the past, the more important task is to determine the status of the current bar.

 

The approach is as follows: We start by looking at a minimum number of bars, NBMin. We calculate the density of the past NBMin bars. We then add one more bar to the search, and calculate the density of the past NBMin + 1 bars. We keep adding bars to the search, calculating the density of the pattern, until we reach some maximum number of bars, NBMax. For example, we might consider all patterns from four to 20 bars in length. Each pattern begins at the current bar and looks backwards. We want to find the pattern with the greatest density since this is most likely to be a consolidation pattern. Once we find this pattern, we record its density and the number of bars in the pattern. For example, we might find that the last six bars have the highest density.

 

The pattern with the highest density is our candidate consolidation pattern. To decide whether the candidate is an actual consolidation pattern, we have to establish a threshold value for the density. For example, we might decide that any pattern with a density greater than 0.6 is a consolidation pattern. I'll suggest how to come up with the threshold value shortly.  

 

I programmed this method in EasyLanguage using two functions and one indicator. The function CPDensity calculates the density of the consolidation pattern. The function CPLocate calls CPDensity and determines whether the current bar is part of a consolidation pattern. CPLocate returns "true" if the current bar is part of a consolidation pattern and "false" otherwise. CPLocate also returns the density of the pattern, the number of bars in the pattern, and the upper and lower bounds of the pattern through its argument list. Finally, the indicator CPIndicate calls the CPLocate function and plots the upper and lower bounds of the consolidation pattern on the screen if the current bar is part of a consolidation pattern. CPIndicate also writes the results returned by CPLocate to the TradeStation MessageLog.

 

{
 Function: CPDensity ("Consolidation Pattern Density")
 Calculates the "density" of a consolidation/trading range pattern
 over the past NBars bars. The density is defined as the area of bars in
 the pattern divided by the maximum possible area. Area is defined as
 the sum of the height of the bars, where height is given by the
 true range. The max possible area is the area of the rectangle
 that bounds the bars; i.e., the highest high minus the lowest low
 times the number of bars.

 

 Michael R. Bryant
 Breakout Futures
 www.BreakoutFutures.com

 Copyright 2003 Breakout Futures

 August 2003
}
 Input: NBars      (NumericSimple);   { number of bars in pattern }

 

 Var:   CPWidth    (0),     { highest high minus lowest low over last NBars bars }
        NB         (0),     { equal to NBars, provided NBars > 0 }
        SumTR      (0),     { sum of true ranges over NB bars }
        ii         (0);     { loop counter }

 

 { Make sure the input value of NBars is greater than zero }
 NB = MaxList(NBars, 1);

 

 { Calculate width of rectangle bounding consolidatin pattern }
 CPWidth = Highest(H, NB) - Lowest(L, NB);

 

 { Calculate sum of true ranges }
 SumTR = 0;
 For ii = 0 to NB - 1 Begin
     SumTR = SumTR + TrueRange[ii];
 End;

 

 { Return sum of true ranges in pattern divided by max area of pattern }
 CPDensity = SumTR/(CPWidth * NB);

 

{
 Function: CPLocate
 Determine if current bar is part of a consolidation/trading range
 pattern. Return true if it is; false otherwise.

 The pattern is identified as follows:
 1. Patterns of length NBMin to NBMax are scanned using the
    function CPDensity, which calculates the "density" of
    the consolidation pattern. All patterns start at the
    current bar.
 2. The length of the pattern with the highest density is
    recorded.
 3. If the density of the highest density pattern matches or
    exceeds a threshold level, the pattern is considered to be
    a consolidation pattern, and TRUE is returned.

 The function also returns the density, length (in bars),
 and the upper and lower boundaries of the pattern with the highest
 density.

 

 Michael R. Bryant
 Breakout Futures
 www.BreakoutFutures.com

 Copyright 2003 Breakout Futures

 August 2003
}

 Input: DensTH     (NumericSimple),   { Density threshold }
        NBMin      (NumericSimple),   { Min # of bars in pattern }
        NBMax      (NumericSimple),   { Max # of bars in pattern }
        PatDens    (NumericRef),      { Density of pattern }
        NBars      (NumericRef),      { Number of bars in pattern }
        HBound     (NumericRef),      { Upper/high boundary of pattern }
        LBound     (NumericRef);      { Lower boundary of pattern }

 

 Var:   MaxDens    (0),               { max density found }
        NMaxDens   (0),               { length of pattern of max density }
        ibars      (0);               { loop counter }

 

 { Search for pattern with highest density }
 MaxDens = 0.;
 For ibars = NBMin to NBMax Begin     
     PatDens = CPDensity(ibars);
     If PatDens > MaxDens then Begin
        MaxDens = PatDens;
        NMaxDens = ibars;
     End;
 End;

 

 { Record results for densest pattern for return }
 PatDens = MaxDens;
 NBars = NMaxDens;
 HBound = Highest(H, NBars);
 LBound = Lowest(L, NBars);

 

 { Check if densest pattern exceeds threshold }
 If MaxDens >= DensTH then
    CPLocate = True
 Else
    CPLocate = False;

 

{
 Indicator: CPIndicate
 Plot the upper and lower bands of consolidation patterns identified
 by function CPLocate.

 

 Michael R. Bryant
 Breakout Futures
 www.BreakoutFutures.com

 Copyright 2003 Breakout Futures

 August 2003
}

 Input: DensTH     (0.55);   { Density threshold }

 

 Var:   NBMin      (4),      { Min # of bars in pattern }
        NBMax      (30),     { Max # of bars in pattern }
        PatDens    (0),      { Density of pattern }
        NBars      (5),      { Number of bars in pattern }
        HBound     (0),      { Upper/high boundary of pattern }
        LBound     (0),      { Lower boundary of pattern }
        LocTF      (false);  { output of CPLocate function }

 

 LocTF = CPLocate(DensTH, NBMin, NBMax, PatDens, NBars, HBound, LBound);

 

 MessageLog(" Date: ", Date:6:0, " Time: ", time:6:0, " Density: ", PatDens:6:3, " # Bars: ", NBars:3:0);

 

 If LocTF then Begin
    Plot1(HBound, "Upper");
    Plot2(LBound, "Lower");
 End;

 

 

So how well does this method work? Take a second look at Figs. 1 and 2, above. Notice where I identified the consolidation patterns on the charts. Below, in Figs. 4 and 5, are the same charts, showing where the CPIndicate indicator has found consolidation patterns. CPIndicate places red and blue crosses at the upper and lower boundaries of the consolidation pattern it finds -- if any -- on the current bar. I used a density threshold value of 0.6 in this case, with NBMin = 4 and NBMax = 30. For the most part, the consolidation patterns identified by CPIndicate are the same as those I identified by eye.

 

Consolidation patterns identified by CPIndicate

 

Figure 4. Consolidation patterns identified by CPIndicate. Compare to Fig. 1.

 

Consolidation patterns identified by CPIndicate

Figure 5. Consolidation patterns identified by CPIndicate. Compare to Fig. 2.

 

Finding a good value for the density threshold is a kind of calibration process. You want to determine the threshold value that helps the CPLocate function find patterns that you consider to be valid consolidation patterns. One way to do this is to take several charts, mark all the consolidation patterns you can find by hand, then apply the CPIndicate indicator with a guess for the threshold value, which is the only input to the indicator. (By the way, the NBMin and NBMax variables in CPIndicate could just as easily be made inputs rather than variables.). Then look at the chart to see how closely the patterns identified by CPIndicate match the ones you came up with. Adjust the threshold value by trial and error until CPIndicate identifies the consolidation patterns you've chosen as closely as possible.

 

With a little work, the CPLocate function could be incorporated into a trading system. Ed Downs suggests that the market usually continues the trend established prior to the formation of the consolidation pattern. If the market rises then consolidates, for example, it's likely that it will continue to go up after breaking out of the consolidation pattern. This logic could be combined with the CPLocate function to buy breakouts from a consolidation pattern following an up trending move and selling downside breakouts from a consolidation pattern following a down trending move. Alternatively, you could try selling at the top of the consolidation pattern and buying at the bottom of the pattern for a shorter-term trade. If nothing else, hopefully, the approach I've taken in this article illustrates that even seemingly ill-defined trading concepts, like chart patterns, can be quantified and programmed.

 

That's all for now. Good luck with your trading.

 

Reference:

Ed Downs, 7 Chart Patterns That Consistently Make Money, MarketPlace Books, 2000.

 

Mike Bryant

Breakout Futures