Lesson 04. Support and Resistance

Support and Resistance are key price levels where a stock tends to pause or reverse its movement.

  • Support:
    The price level where buying pressure is strong enough to stop the price from falling further.
    → Think of it as a floor where buyers step in.
    Example: A stock keeps bouncing up near $50 — that’s support.
  • Resistance:
    The price level where selling pressure stops the price from rising higher.
    → Think of it as a ceiling where sellers take profits.
    Example: A stock keeps falling back down near $70 — that’s resistance.

When price breaks through one of these levels, it often becomes the opposite:

  • Old resistance can become new support.
  • Old support can become new resistance.

Traders use these zones to plan entries, exits, and stop losses.

The First 30 Minutes Rule

The first 30 minutes of the trading day often create strong support and resistance levels because this period contains a surge of volume and institutional activity, reflecting the market’s initial reaction to overnight news and establishing where major buyers and sellers are willing to transact.

Notice how stocks tend to “ping-pong” off the first 30 minute box?

These opening-range highs and lows represent the earliest and most meaningful price extremes of the session, formed during heightened volatility and heavy order flow; as the day progresses and volatility typically contracts, traders widely reference these well-known levels, reinforcing them psychologically and mechanically as key areas where price frequently pauses, reverses, or breaks with significance.

A good example of Support and Resistance is the First 30 Minutes High/Low Box which can be automatically drawn on your charts by utilizing the following script written in PineScript:

First 30 Minutes High/Low Box

//@version=6
indicator("First 30 Minutes High/Low Box", overlay = true)
range_minutes = input.int(30, "Range length (minutes)", minval = 1, maxval = 120)
extend_today  = input.bool(true, "Extend today's 15m box across day")
fill_transp   = input.int(95, "Box transparency", minval = 0, maxval = 100)
box_color     = color.green

var int   first_bar_index = na
var int   window_end_ts   = na
var float rng_hi          = na
var float rng_lo          = na
var box   rng_box         = na

new_day = ta.change(time("D")) != 0

if (new_day)
    // New day starts: clear old box and start a new 15m window
    if not na(rng_box)
        box.delete(rng_box)
        rng_box := na

    first_bar_index := bar_index
    rng_hi          := high
    rng_lo          := low
    window_end_ts   := time + range_minutes * 60 * 1000

else
    // While still inside the first 15 minutes, keep updating the range
    in_window = not na(window_end_ts) and time <= window_end_ts
    if in_window
        rng_hi := na(rng_hi) ? high : math.max(rng_hi, high)
        rng_lo := na(rng_lo) ? low  : math.min(rng_lo, low)

        if na(rng_box)
            rng_box := box.new(left = first_bar_index, top = rng_hi, right = bar_index, bottom = rng_lo, xloc = xloc.bar_index, border_color = box_color, bgcolor = color.new(box_color, fill_transp))
        else
            box.set_top(rng_box, rng_hi)
            box.set_bottom(rng_box, rng_lo)
            box.set_right(rng_box, bar_index)

    // After the window ends, just extend the box to the right if desired
    if extend_today and not na(rng_box) and not in_window
        box.set_right(rng_box, bar_index)