21 — Structural Analysis

Support & Resistance#

LevelsHeuristic1 min read
◆ The PatternThe floor and ceiling of price — where memory lives

Support is a price level where buying concentrates (floor). Resistance is where selling concentrates (ceiling). These levels have "memory" — broken support becomes resistance, and broken resistance becomes support. This polarity principle is fundamental to all chart reading.

More touches = stronger level · Broken support → resistance (and vice versa)
S&R levels are zones, not exact prices — think of them as areas where orders cluster, not precise lines.
// Support & Resistance — price memory
Key insight: Round numbers ($50, $100) and previous highs/lows create natural S&R levels because traders and algorithms place orders there.
Pattern bridge: Price memory at specific levels is anchoring bias made visible. In ML, activation clamping (ReLU at 0, sigmoid at 0/1) creates the same floor and ceiling.
Worked example

The price turns up from 100 three times (days 4, 12 and 20). Grouping the swing lows to the nearest point gives one level with three touches: support at 100. A close 1% below it, under 99, would count as a break; day 24 closes at 106, so it holds.

The example data

The turning points the daily closes run through, in straight lines between them; high and low are half a point either side of each bar.

DayClose
0105
4100
8108
12100
16110
20100
24106
Where it misleads
  • Levels are zones, not lines: how close counts as a touch is a parameter, and changing it changes the levels you find.
  • Every test also uses up the buyers waiting there, so heavily tested levels often break.
  • Round numbers and old highs work partly because many traders watch them, a self-fulfilling effect that can stop at any time.
In code
def swings(s, n=3):                     # a swing high (low) is the extreme of the 2n+1 bars around it
    w = s.rolling(2 * n + 1, center=True)
    return s[s == w.max()], s[s == w.min()]
c = df['close']
highs, lows = swings(c)
touches = lows.round(0).value_counts()               # swing lows grouped to the nearest point
level = touches.idxmax()
support = level if touches.max() >= 2 else None
broken = c.iloc[-1] < level * 0.99                    # a close 1% under it
Python, in your browser — edit the code and run it again

Assumes import numpy as np, import pandas as pd, and a DataFrame df with columns open, high, low and close for the data above.

Sources
  • C. L. Osler, “Support for Resistance: Technical Analysis and Intraday Exchange Rates”, Federal Reserve Bank of New York Economic Policy Review 6(2), 2000
  • Technical Analysis of the Financial Markets, J. J. Murphy, New York Institute of Finance, 1999

Last reviewed October 2026 · How this site checks its content · Report a mistake

Check yourself

1. Why might support and resistance levels work at all?

Show answer

C. Osler (2000) found published support and resistance levels helped predict intraday trend interruptions in currency markets.

2. Price breaks below support, then closes back above it the next day. What is this called?

Show answer

A. Requiring a close, or a percentage beyond the level, filters some false breaks at the cost of later entries.

3. What is the trap in drawing levels on a past chart?

Show answer

B. Define the levels by a rule (e.g. the last swing low) and test that rule on data it did not see.

Linked from 4
← Previous
Evening Star
Open in the full reader, with the topic sidebar