TradingView screening workflow

Support and resistance screeners: explicit levels and confirmation

A support resistance screener needs a numerical level definition before it can produce a useful list. This guide uses the highest high and lowest low of the 20 daily bars before the tested day. It separates closes within 0.5% of a boundary from closes that break it. The Pine example checks three named symbols on completed daily data; it does not interpret every manually drawn line or discover an entire market.

Explore Market Screener

Use a prior range as the level definition

Let t be the completed daily bar being tested. Resistance R is the highest high from t-20 through t-1; support S is the lowest low over the same bars. C is the close at t and P is the close at t-1. This is a prior-window variant of the high-low channel calculation described by TradingView for Donchian Channels. The 20 bars are trading bars, not 20 calendar days. Treat these boundaries as screening references; their existence does not prove that price will reverse there.

  • Exclude day t from the levels. If its own high were included, a close could not exceed the resulting high on ordinary OHLC data.
  • Recompute the range for each tested day. An old extreme can leave the window and move a boundary without a new swing forming.
  • Require positive support and resistance greater than support. Reject missing history and a zero-width range instead of dividing by zero or reporting a false match.
  • A confirmed pivot is a different rule: it requires bars to the right of the pivot before confirmation. This range rule uses only earlier bars and has no pivot-right-bar delay.

Separate near-level states from closing-break events

The tolerance is a percentage of the reference level, not of the current price. Define support distance as 100 × (C - S) / S and resistance distance as 100 × (R - C) / R. A negative distance means the close is beyond that boundary. The 0.5% setting below is an illustrative threshold, not an optimized trading parameter.

  • A wick beyond a level with a close back inside is not a closing break. A close exactly at the level is a proximity match, not a break.
  • The tolerance applies only to proximity. This example uses a strict break with no percentage buffer. If your rule needs a buffer, define it separately and test the changed threshold.
  • The range rolls each day. Consecutive daily closes can each break a newly calculated boundary; this is not a single alert for one permanent line. Narrow ranges can satisfy both proximity rules.
  • Compare P and C with the same R or S for that test. Comparing each close against a different moving boundary can confuse a boundary change with a price crossing.
ClassificationExact rule at tolerance τ = 0.5%Meaning
Near supportS ≤ C ≤ min(R, S × 1.005)Inside the range, within 0.5% above support
Near resistancemax(S, R × 0.995) ≤ C ≤ RInside the range, within 0.5% below resistance
Break upC > R and P ≤ RClose moves above the same resistance used for both comparisons
Break downC < S and P ≥ SClose moves below the same support used for both comparisons
No matchValid data, none of the aboveKeep the row visible so an exclusion can be checked

Check the arithmetic before scanning a list

These hypothetical cases hold S at 100 and R at 110, with a 0.5% tolerance. Near support spans 100 through 100.50. Near resistance spans 109.45 through 110 because 110 × 0.995 = 109.45. They are independent test cases, not consecutive market observations.

  • The script compares unrounded prices with the boundary thresholds. Display rounding must not decide whether a value passes.
  • For an additional overlap test, use S = 100, R = 100.4 and C = 100.2. Both distances are below 0.5%, so the state is Near both.
  • For S = R = 100, or S ≤ 0, the script reports an invalid range. A symbol without enough daily history is also excluded.
Previous close PTest close CDistance / comparisonExpected result
101100.50Above S: 100 × 0.50 / 100 = 0.5%Near support; inclusive boundary
101100.51Above S: 0.51%No match
109109.45Below R: 100 × 0.55 / 110 = 0.5%Near resistance; inclusive boundary
109.8110Below R: 0%; C equals RNear resistance; no break
109.8110.01C > 110 and P ≤ 110Break up
100.299.99C < 100 and P ≥ 100Break down
109.8109.8; intraday high 111Close remains inside; below R ≈ 0.1818%Near resistance; wick alone is no break

Run the three-symbol Pine Script v6 example

Paste the indicator into the TradingView Pine Editor and add it to a standard intraday chart, such as 60 minutes. Set three exchange-qualified symbols in Settings. The table shows the last completed daily bar available through each request. Default symbols are examples only. Blue rows match a proximity or break rule; every row includes its reference levels and observation date.

  • The close uses a one-daily-bar offset. The range uses a two-bar offset because it must end one day before that close. With length 20, the script requires the tested bar plus 20 earlier daily bars.
  • Offset expressions with lookahead_on retrieve confirmed higher-timeframe values without exposing future daily closes on historical intraday bars. This delays the result until the next daily period is available to the running chart.
  • The table is refreshed when the host chart executes. A closed host market can delay updates for another market. The date column is the requested daily bar opening date in UTC, which can differ from the local exchange session label.
  • Invalid symbols return missing data. Carried-forward daily data can remain visible during holidays or feed interruptions, so a populated row is not proof of freshness.
  • This is a chart-table script, not a TradingView Pine Screener configuration. It does not import your watchlist, inspect chart drawings, run an exchange-wide scan, or create an alert.
Three explicit symbol inputs; prior daily range; completed daily close; no orders or alert calls.pine
//@version=6
indicator("Support resistance list: completed daily ranges", overlay = true)
int length = input.int(20, "Prior daily bars", minval = 2, maxval = 252)
float tolerance = input.float(0.5, "Near-level tolerance (%)", minval = 0, maxval = 10, step = 0.1)
string symbol1 = input.symbol("NASDAQ:AAPL", "Symbol 1")
string symbol2 = input.symbol("NASDAQ:MSFT", "Symbol 2")
string symbol3 = input.symbol("NASDAQ:NVDA", "Symbol 3")
if not timeframe.isintraday or timeframe.in_seconds() >= timeframe.in_seconds("1D")
    runtime.error("Use a standard intraday chart, such as 60 minutes.")

scan() =>
    float resistance = ta.highest(high, length)[2]
    float support = ta.lowest(low, length)[2]
    bool ready = not na(high[length + 1]) and not na(low[length + 1])
    [close[1], close[2], resistance, support, time[1], ready]

[c1, p1, r1, s1, t1, ok1] = request.security(symbol1, "1D", scan(), gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_on, ignore_invalid_symbol = true)
[c2, p2, r2, s2, t2, ok2] = request.security(symbol2, "1D", scan(), gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_on, ignore_invalid_symbol = true)
[c3, p3, r3, s3, t3, ok3] = request.security(symbol3, "1D", scan(), gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_on, ignore_invalid_symbol = true)
var table results = table.new(position.top_right, 7, 4, border_width = 1)
showRow(int row, string symbol, float c, float previous, float r, float s, int stamp, bool ready) =>
    bool valid = ready and not na(c) and not na(previous) and not na(stamp) and s > 0 and r > s
    float ds = valid ? 100 * (c - s) / s : na
    float dr = valid ? 100 * (r - c) / r : na
    bool nearS = valid and c >= s and c <= r and c <= (s + s * tolerance / 100)
    bool nearR = valid and c <= r and c >= s and c >= (r - r * tolerance / 100)
    bool breakUp = valid and c > r and previous <= r
    bool breakDown = valid and c < s and previous >= s
    string state = not valid ? "No data / invalid range" : breakUp ? "Break up" : breakDown ? "Break down" : nearS and nearR ? "Near both" : nearS ? "Near support" : nearR ? "Near resistance" : "No match"
    color shade = valid and (breakUp or breakDown or nearS or nearR) ? color.new(color.blue, 70) : color.new(color.gray, 85)
    array<string> cells = array.from(symbol, valid ? str.format_time(stamp, "yyyy-MM-dd", "UTC") : "N/A", valid ? str.tostring(s, "#.########") : "N/A", valid ? str.tostring(r, "#.########") : "N/A", valid ? str.tostring(ds, "#.####") : "N/A", valid ? str.tostring(dr, "#.####") : "N/A", state)
    for col = 0 to 6
        table.cell(results, col, row, array.get(cells, col), bgcolor = shade, text_color = color.white)
if barstate.islast
    array<string> headers = array.from("Symbol", "Daily open UTC", "Support", "Resistance", "Above S %", "Below R %", "State")
    for col = 0 to 6
        table.cell(results, col, 0, array.get(headers, col), bgcolor = color.navy, text_color = color.white)
    showRow(1, symbol1, c1, p1, r1, s1, t1, ok1)
    showRow(2, symbol2, c2, p2, r2, s2, t2, ok2)
    showRow(3, symbol3, c3, p3, r3, s3, t3, ok3)

Keep list size and confirmation delay explicit

The example has three symbol slots and one daily request per slot, with six returned values in each tuple. It uses three request contexts for three distinct symbols and 18 tuple elements. Repeating a symbol duplicates the displayed row rather than expanding coverage. TradingView documents limits of 40 unique request calls for most plans and 64 for Ultimate, plus 127 combined tuple elements; other script limits still apply.

  • Adding symbols is a source-code change here. Count all request contexts and tuple elements before expanding the table. Multiple intervals per symbol consume additional contexts.
  • A daily match is intentionally unavailable while its daily close is still forming. The earliest displayed confirmed result depends on the next daily period and a host-chart execution; this is unsuitable for immediate intraday break detection.
  • Check a passing and failing symbol on standard daily candles. Match exchange, session, price adjustments and bar date, then inspect the 20 preceding highs and lows. Do not compare a synthetic candle close with ordinary OHLC data.
  • Review gaps, liquidity and news separately. A gap can satisfy a closing break without providing an executable fill at the level. A subsequent close can return inside the range.

Use Pineify for supported fields, then apply the custom rule

Pineify Market Screener lets you compare supported technical fields in saved symbol collections. Its public catalog includes Distance from 252-Bar High and Distance from 252-Bar Low. Use those fields to review candidates near longer-window extremes, with the collection set to 1D and any per-symbol overrides checked. These fields are not the prior-20-day rule above and do not establish a confirmed break of that range.

  • Add only symbols present in the selector and check their exchange and market. A collection supports up to 100 symbols and 20 indicator columns. Full Market Screener access starts at Expert.
  • Sort the supported distance columns and inspect the values. The high-distance field is negative below the high, whereas this example reports a positive distance below resistance. Do not transfer the sign or threshold blindly.
  • The active collection refreshes every 60 seconds, but its TradingView Alert snapshots can be older. Check the reported bar and received timestamps before comparing with a chart; a refresh does not guarantee a new exchange observation.
  • For this exact prior-window condition, give Pine Script AI Coding Agent the range length, daily confirmation rule, tolerance, symbols and missing-data behavior. Review its generated source and test both matching and failing cases in TradingView.
  • Keep the screened list and chart review together: symbol, scan time, tested bar, S, R, C, classification and reason for acceptance or rejection. The screen supplies research candidates, not entry instructions.
Where Pineify fits

Pineify Market Screener

Compare supported distance fields across symbol collections. Check the daily interval, field window and snapshot time before reviewing a candidate.

Also useful: Pine Script AI Coding Agent. Specify a prior-range rule and a finite symbol list, then review and validate the generated Pine indicator.

Explore Market Screener

Frequently asked questions

Educational information, not investment advice. Numerical examples are hypothetical. A nearby level or confirmed closing break does not guarantee a reversal, continuation or profitable trade.

Sources and verification

Published by Pineify. Pineify is an independent product and is not affiliated with TradingView. Sources support the technical explanations; examples do not establish trading performance.