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

 

Unlimited Systems

Auto-generate unique

trading strategies for

TradeStation.

 

Position Sizing Tool

Position sizing software for

trading. Trade smarter.

Maximize results.

 

 

The Breakout Bulletin

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

Quantifying Chart-based Support/Resistance Levels

A common distinction in trading is between systematic and discretionary trading methods. Systematic traders use hard and fast rules that are typically computerized in the form of one or more trading systems. Discretionary traders, on the other hand, don't use trading systems. While they have trading rules and methods, they haven't codified those rules into a computerized trading system. I've always found this distinction to be somewhat arbitrary. One of the tenets of good trading is to have well defined methods. Whether you computerize those methods into a trading system or choose to manually implement certain aspects of your approach, you still have something that could reasonably be called a "system." In fact, I'd go as far as to say that most discretionary methods are just trading systems yet to be programmed. A trader may be "discretionary" only because his approach seems too complicated to program. 

 

One aspect of trading that can frustrate attempts at programming is chart patterns. Reading chart patterns, such as triangles and head and shoulder patterns, is said to be more art than science. If you have a trading approach based on chart patterns, you're probably a discretionary trader, if only because it's complicated to program a system to recognize a chart pattern.

 

Several months ago I was studying support and resistance levels for day trading the E-mini S&P. After scanning numerous intraday charts to locate these price levels visually, an algorithm occurred to me for identifying these support and resistance prices. This month, I'll show how this algorithm works and how to program it in TradeStation's EasyLanguage.

 

 

 3-min E-mini S&P 500

Fig. 1 A 3 minute chart of the March E-mini S&P 500 showing several support and resistance levels.

 

Consider Fig. 1. I've drawn several horizontal lines by hand to suggest the kind of short-term support and resistance levels I have in mind. You might look for these price levels if you're trying to capture a few points of profit per trade. For example, you might try to sell short at the resistance level during a downtrend and cover at the support level. Similarly, in a up trend, you might try to buy at the support level and sell at the resistance level.

 

The logic I came up with to systematize the identification of these levels is pretty straight-forward. As each price bar is completed, I look for the most logical location for support and the most logical location for resistance relative to the close of the most recently completed bar. Since we are focusing on intraday data, which, in actual day trading, is evolving in real time, these support/resistance locations may change from bar to bar.

 

To identify the locations of support and resistance relative to the close, I scan all price levels within X points of the close over the last N bars. At each price level, imagine a horizontal line extending back from the current bar over the last N bars. Our goal is find the price level at which the horizontal line best fits the last N bars. I use a least-squares fitting method. At each price bar, determine whether the high or low of the bar is closest to the line and add the square of the difference between that price and the price level of the line to a running sum. This calculation is repeated for each of the N bars closest to the current bar to form the "sum of squares." Ignore price bars that are farther away from the line than Y points in order to avoid skewing the sum by these "outlier" prices. The whole process is repeated for each price level within X points of the current close.

 

The resistance level is then the price above the current bar's high for which the sum of squares is smallest. The support level is the price below the current bar's low for which the sum of squares is smallest.

 

 

Fitting a line to the price bars

Fig. 2. Fitting a line to the price bars.

 

Fig. 2. illustrates the sum-of-squares process for a given price level. The horizontal line is a potential resistance level for the price bar colored green. The prices used in the sum of squares calculation are circled in red. Notice that one of the bars does not have a red circle on either its high or low. This is because the closest price on the bar is farther than Y points from the horizontal line. The sum of squares for this horizontal price level is the sum of the squares of the distances between the circled prices and the horizontal line.

 

I programmed the calculation of the support and resistance levels into an EasyLanguage function called SupRes2. The EasyLanguage code is shown below.

 

{
  Function: SupRes2 ("Support/Resistance")
  Locate the nearest price levels of support and resistance. 

 

  Returns: Average of support and resistance levels; Also, the
  support and resistance levels are returned through the argument
  list.

 

  Michael R. Bryant
  Breakout Futures
  www.BreakoutFutures.com

  Copyright 2003 Breakout Futures

  Feb 24, 2003
}
  Input: NBars     (NumericSimple),  { # bars to lookback in search }
         PriceRnge (NumericSimple),  { # points to examine above/below close }
         PFilter   (NumericSimple),  { Include high/low within PFilter points }
         MinPoints (NumericSimple),  { min # points for a fit }
         SupPrice  (NumericRef),     { located support price }
         ResPrice  (NumericRef);     { located resistance price }
        
  Var:  iPrice     (0),     { price at current level }
        DtoLow     (0),     { distance from line to low }
        DtoHigh    (0),     { distance from line to high }
        Sum        (0),     { sum of weights }
        NormSum    (0),     { normalized sum }
        MinSum     (999999),{ max sum of weights }
        NPoints    (0),     { # points in sum }
        SupportP   (0),     { best support price }
        ResistP    (0),     { best resistance price }
        NPInc      (0),     { number of price increments above/below close }
        istart     (0),     { first increment to start at }
        ip         (0),     { loop counter of price increments }
        ib         (0);     { loop counter for bars }

 

  NPInc = PriceRnge/(MinMove/PriceScale);
  istart = IntPortion(NPInc/3);

 

  { Search for resistance; loop over prices above close }
  MinSum = 999999;
  ResistP = MaxList(High, ResPrice);
  For ip = istart to NPInc Begin
     iPrice = Close + ip * (MinMove/PriceScale);
      Sum = 0;
      NPoints = 0;

 

      { Loop over bars }
      For ib = 1 to NBars Begin
    
          { Add up sum of squares of distances to price line }
          DtoLow = AbsValue(L[ib] - iPrice);
          DtoHigh = AbsValue(H[ib] - iPrice);
          If DtoLow <= DtoHigh and DtoLow <= PFilter then Begin
             NPoints = NPoints + 1;
             Sum = Sum + Square(DtoLow);
          end
          else If DtoHigh < DtoLow and DtoHigh <= PFilter then Begin
             NPoints = NPoints + 1;
             Sum = Sum + Square(DtoHigh);
          end;
          
    end; { loop ib }

 

    { Record iPrice if sum is lowest so far }

    If NPoints >= MinPoints then Begin
       NormSum = SquareRoot(Sum/NPoints);
       If NormSum < MinSum then Begin
          MinSum = NormSum;
          ResistP = iPrice;
       end;
    end;
  end; { loop ip }

 

  ResistP = MaxList(High, ResistP);   { make sure resistance >= high }

 

  { Search for support; loop over prices below close }
  MinSum = 999999;
  SupportP = MinList(Low, SupPrice);
  For ip = istart to NPInc Begin
     iPrice = Close - ip * (MinMove/PriceScale);
      Sum = 0;
      NPoints = 0;

 

      { Loop over bars }
      For ib = 1 to NBars Begin
    
          { Add up sum of squares of distances to price line }
          DtoLow = AbsValue(L[ib] - iPrice);
          DtoHigh = AbsValue(H[ib] - iPrice);
          If DtoLow <= DtoHigh and DtoLow <= PFilter then Begin
             NPoints = NPoints + 1;
             Sum = Sum + Square(DtoLow);
          end
          else If DtoHigh < DtoLow and DtoHigh <= PFilter then Begin
             NPoints = NPoints + 1;
             Sum = Sum + Square(DtoHigh);
          end;
          
    end; { loop ib }

 

    { Record iPrice if sum is lowest so far }
    If NPoints >= MinPoints then Begin
       NormSum = SquareRoot(Sum/NPoints);
       If NormSum < MinSum then Begin
          MinSum = NormSum;
          SupportP = iPrice;
       end;
    end;
  end; { loop ip }

 

  SupportP = MinList(Low, SupportP);   { make sure support <= Low }

 

  SupPrice = SupportP;
  ResPrice = ResistP;

 

  SupRes2 = (SupportP + ResistP)/2.;

 

I also created an indicator based on the SupRes2 function to plot the support and resistance levels. The code for the indicator is shown below.

 

{
  Indicator: SupRes Indicator-2
  Plot the support and resistance given by the SupRes2 function.

 

  Michael R. Bryant
  Breakout Futures
  www.BreakoutFutures.com

  Copyright 2003 Breakout Futures

  Feb 24, 2003
}

 Inputs: NBars     (30),             { # bars to lookback in search }
         PriceRnge (3),              { # points to examine above/below close }
         PFilter   (1.0),            { points this close to line }
         MinPoints (4);              { need at least this many points in fit }

 

 Var:    SupPrice  (C),              { located support price }
         ResPrice  (C);              { located resistance price }

 

 { Call SupRes function to find nearest support/resistance }
 Value1 = SupRes2(NBars, PriceRnge, PFilter, MinPoints, SupPrice, ResPrice);

 Plot1(SupPrice, "Support");
 Plot2(ResPrice, "Resistance");

 

In Fig. 3, I show how the indicator works for the same price chart shown in Fig. 1. I used the following input parameter values: 30, 2.25, 0.75, 4. The support prices are in green and the resistance levels in red. During downtrending markets, the support levels tend to stay close to the price bar lows because none of the nearby price bars have prices lower than the most recent bar's low. Similarly, in uptrending markets, the resistance levels stay near the highs. The SupRes2 function could be employed in a trading system in a number of different ways, such as (1) to identify the trend based on whether support and resistance levels are rising or falling, and (2) to trigger entries and/or exits at the identified support and resistance levels.

 

 

SupRes Indicator on 3-min E-mini S&P

Fig. 3. SupRes Indicator plotted on a 3 minute chart of E-mini S&P data.

 

 

The SupRes2 function illustrates how a visual task like identifying a support or resistance level on a price chart can be systematized. I'll leave it to you to incorporate these levels into a trading system.

 

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

 

Mike Bryant

Breakout Futures