Library · Pine Script v5 · Library

Support Resistance and Trend

by Electrified-Trading

This Pine Script utility library provides exported helper functions and data structures for calculating market trend directions and key support and resistance boundaries.

View on GitHub

GitHub stars2on the repository
Pine versionv5runs as is
Lines of code416
Settings4inputs
LicenceMPL-2.0
Last update1 year ago7 Jul 2025

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new library, select all of the template text and paste. Press Save and give it a name.
  4. 4Publish or import itA library draws nothing. Publish it from the editor, then import its functions in your own scripts.

Source Code

416 lines of Pine Script v5 from SupportResistanceAndTrend.pine, published under MPL-2.0. Keep the author's credit and licence lines when you reuse it.

SupportResistanceAndTrend.pine
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Electrified (electrifiedtrading)

// @version=5
// @description Contains utilities for finding key levels of support, resistance and direction of trend.
library('SupportResitanceAndTrend', true)
import Electrified/MovingAverages/10 as MA
import Electrified/DataCleaner/5 as Data

////////////////////////////////////////////////////////////////
// @type A high and low value pair.
// @field hi The high value.
// @field lo The low value.
export type Boundary
    float hi
    float lo

////////////////////////////////////////////////////////////////
// @type The state of the trend.
// @field trend The integer representing the trend.
// @field up The value boundary value when the trend is up.
// @field dn The value boundary value when the trend is down.
// @field hitCount The number of times the boundary has been tested but trend is still intact.
// @field warning True if the active boundary has been hit.
// @field reversal True if the trend has confirmed reversal.
export type TrendState
    int trend
    float up
    float dn
    int hitCount
    bool warning
    bool reversal

///////////////////////////////////////////////////
// @function Determines the local trend of a series that and persists the trend if the value is unchanged.
// @param src The source series to derive from.
// @return +1 when the trend is up; -1 when the trend is down; 0 if the trend is not yet established.
export trend(series float src) =>
    var s = 0
    if src > src[1]
        s := +1
    if src < src[1]
        s := -1
    s
///////////////////////////////////////////////////

///////////////////////////////////////////////////
// @function Determines the local trend of each boundary level that and persists the trend if the value is unchanged.
// @param src The source series to derive from.
export trend(series Boundary src) =>
    hi = trend(src.hi)
    lo = trend(src.lo)
    Boundary.new(hi, lo)
///////////////////////////////////////////////////

///////////////////////////////////////////////////
// @function A more flexible version of SuperTrend that allows for supplying the series used and sensitivity adjustment by confirming close bars.
// @param multiple The multiple to apply to the average true range.
// @param h The high values.
// @param l The low values.
// @param atr The average true range values.
// @param closeBars The number of bars to confirm a change in trend.
export superTrendPlus(
  simple float multiple,
  series float h,
  series float l,
  series float atr,
  simple int closeBars = 0) =>
    up = l-(multiple*atr)
    up1 = nz(up[1], up)
    up := l[1] > up1 ? math.max(up, up1) : up
    dn = h+(multiple*atr)
    dn1 = nz(dn[1], dn)
    dn := h[1] < dn1 ? math.min(dn, dn1) : dn

    var lastU = up1
    var lastD = dn1
    var trend = 0
    var confirmation = 0
    var unconfirmed = 0

    // cover gap cases
    if(trend != +1 and l > lastD)
        trend := +1
    else if(trend != -1 and h < lastU)
        trend := -1
    
    // confirmed cases
    else if(trend != +1 and h > lastD)
        unconfirmed += 1
        if(confirmation<closeBars and close[1]>lastD)
            confirmation += 1
        if(confirmation>=closeBars)
            trend := +1       
    else if(trend != -1 and l < lastU)
        unconfirmed += 1
        if(confirmation<closeBars and close[1]<lastU)
            confirmation += 1
        if(confirmation>=closeBars)
            trend := -1

    if(trend[1]!=trend)
        lastU := up1
        lastD := dn1
        confirmation := 0
        unconfirmed := 0
    else
        lastU := trend==+1 ? math.max(lastU, up1) : up1
        lastD := trend==-1 ? math.min(lastD, dn1) : dn1
        // Trend is clearly continuing?  Reset confirmation.
        if(trend==+1 and dn1>dn1[1] or trend==-1 and up1<up1[1])
            confirmation := 0
            unconfirmed := 0

    TrendState.new(trend, lastU, lastD, unconfirmed, unconfirmed[1]==0 and unconfirmed > 0, trend != trend[1])
///////////////////////////////////////////////////

getATR(simple string mode, simple int period, simple float maxDeviation) =>
    trCleaned = maxDeviation==0 ? ta.tr : Data.naOutliers(ta.tr, period, maxDeviation)
    MA.get(mode, period, trCleaned)
////

///////////////////////////////////////////////////
// @function superTrendPlus with simplified parameters.
// @param multiple The multiple to apply to the average true range.
// @param period The number of bars to measure.
// @param mode The type of moving average to use with the true range.
// @param closeBars The number of bars to confirm a change in trend.
export superTrend(
  simple float multiple,
  simple int period,
  simple string mode = 'WMA',
  simple int closeBars = 0,
  simple float maxDeviation = 0) =>
    atr = getATR(mode, period, maxDeviation)
    superTrendPlus(multiple, high, low, atr, closeBars)
///////////////////////////////////////////////////

///////////////////////////////////////////////////
// @function superTrendPlus with default compensation for extreme volatility.
// @param multiple The multiple to apply to the average true range.
// @param period The number of bars to measure.
// @param mode The type of moving average to use with the true range.
// @param closeBars The number of bars to confirm a change in trend.
// @param maxDeviation The optional standard deviation level to use when cleaning the series.  The default is the value of the provided level. 
export superTrendCleaned(
  simple float multiple,
  simple int period,
  simple string mode = 'WMA',
  simple int closeBars = 0,
  simple float maxDeviation = 4) =>
    atr = getATR(mode, period, maxDeviation)
    superTrendPlus(multiple, high, low, atr, closeBars)
///////////////////////////////////////////////////


calcDev(series float source, simple int len, simple float multiple) =>
    ta.wma(source, len) + ta.wma(ta.stdev(source, len * 2), len) * multiple

///////////////////////////////////////////////////
// @function superTrendPlus with default compensation for extreme volatility.
// @param multiple The multiple to apply to the average true range.
// @param period The number of bars to measure.
// @param mode The type of moving average to use with the true range.
// @param closeBars The number of bars to confirm a change in trend.
// @param maxDeviation The optional standard deviation level to use when cleaning the series.  The default is the value of the provided level. 
export superTrendAuto(
  simple int volatilityLength,
  simple float deviationLevel,
  simple int deviationLength,
  simple int confirmBars = 2,
  simple float atrMultiple = 0.5,
  simple float maxAtrDeviation = 2.5) =>
    atr = getATR("WMA", deviationLength, maxAtrDeviation)
    tolerance = atr * atrMultiple

    // Determine the range for the delta length
    upDev = calcDev(math.max(high - low[volatilityLength], 0), deviationLength, deviationLevel)
    dnDev = calcDev(math.max(high[volatilityLength] - low, 0), deviationLength, deviationLevel)

    // Trend
    UP = +1, DOWN = -1
    var trend = 0
    var upper = high
    var lower = low
    var brokenCount = 0
    var wasTouched = false
    warn = false
    reversal = false

    upperWarning = close > upper
    lowerWarning = close < lower
    upperBroken = close[1] - tolerance > upper
    lowerBroken = close[1] + tolerance < lower

    if trend == UP
        // Touching the lower boundary resets the warning condition
        if upperWarning
            brokenCount := 0
            wasTouched := false
        if lowerWarning
            wasTouched := true
            warn := true
    else
        if lowerBroken
            lower := low[1]
        if upperBroken
            brokenCount += 1

    if trend == DOWN
        // Touching the upper boundary resets the warning condition
        if lowerWarning
            brokenCount := 0
            wasTouched := false
        if upperWarning
            wasTouched := true
            warn := true        
    else
        if upperBroken
            upper := high[1]
        if lowerBroken
            warn := true
            brokenCount += 1

    if trend != UP
        // If the low exceeds the threshold then confirmation is not required.
        if brokenCount > confirmBars or low > upper + tolerance 
            trend := UP
            upper := high[1]
            reversal := true

    else if trend != DOWN
        // If the high exceeds the threshold then confirmation is not required.
        if brokenCount > confirmBars or high < lower - tolerance
            trend := DOWN
            lower := low[1]
            reversal := true

    if reversal
        wasTouched := false
        brokenCount := 0

    // Range adjustment
    if low[1] + tolerance < upper - dnDev
        upper := low[1] + dnDev
    if high[1] - tolerance > lower + upDev
        lower := high[1] - upDev

    TrendState.new(trend, lower, upper, brokenCount, warn, reversal)
///////////////////////////////////////////////////

///////////////////////////////////////////////////
// @function Identifies support and resistance levels by when a stochastic RSI reverses.
export stochSR(
  simple int smoothK,
  simple int smoothD,
  simple int lengthRSI,
  simple int lengthStoch,
  series float src = hlc3,
  simple float lowerBand = 20,
  simple float upperBand = 80,
  simple float lowerReversal = 20,
  simple float upperReversal = 80) =>
    rsi1 = ta.rsi(src, lengthRSI)
    stoch = ta.stoch(rsi1, rsi1, rsi1, lengthStoch)
    k = ta.wma(stoch, smoothK)
    d = ta.sma(k, smoothD)
    k_c = ta.change(k)
    d_c = ta.change(d)
    kd = k - d

    var hi = high
    var lo = low
    var phi = high
    var plo = low
    var state = 0

    if(d<lowerBand)
        phi := high
    if(d>upperBand)
        plo := low

    if(high>phi)
        phi := high
    if(low<plo)
        plo := low    

    if(state!=-1 and d<lowerBand)
        state := -1
    else if(state!=+1 and d>upperBand)
        state := +1

    if(hi>phi and state==+1 and k<d and k<lowerReversal)
        hi := phi
    if(lo<plo and state==-1 and k>d and k>upperReversal)
        lo := plo

    if(high>hi)
        hi := high
    if(low<lo)
        lo := low

    Boundary.new(hi, lo)
///////////////////////////////////////////////////

///////////////////////////////////////////////////
// @function Identifies anchored VWAP levels by when a stochastic RSI reverses.
// @returns [active_HL, next_HL]
export stochAVWAP(
  simple int smoothK,
  simple int smoothD,
  simple int lengthRSI,
  simple int lengthStoch,
  series float src = hlc3,
  simple float lowerBand = 20,
  simple float upperBand = 80,
  simple float lowerReversal = 20,
  simple float upperReversal = 80,
  simple bool useHiLow = false) =>
    rsi1 = ta.rsi(src, lengthRSI)
    stoch = ta.stoch(rsi1, rsi1, rsi1, lengthStoch)
    k = ta.wma(stoch, smoothK)
    d = ta.sma(k, smoothD)
    k_c = ta.change(k)
    d_c = ta.change(d)
    kd = k - d

    var hi = high
    var lo = low
    var phi = high
    var plo = low
    var state = 0

    var float hiAVWAP_s = 0
    var float loAVWAP_s = 0
    var float hiAVWAP_v = 0
    var float loAVWAP_v = 0
    var float hiAVWAP_s_next = 0
    var float loAVWAP_s_next = 0
    var float hiAVWAP_v_next = 0
    var float loAVWAP_v_next = 0

    if(d<lowerBand or high>phi)
        phi := high
        hiAVWAP_s_next := 0
        hiAVWAP_v_next := 0
    if(d>upperBand or low<plo)
        plo := low
        loAVWAP_s_next := 0
        loAVWAP_v_next := 0

    if(high>hi)
        hi := high
        hiAVWAP_s := 0
        hiAVWAP_v := 0    
    if(low<lo)
        lo := low
        loAVWAP_s := 0
        loAVWAP_v := 0

    vwapHi = useHiLow ? high : hlc3
    vwapLo = useHiLow ? low : hlc3
        
    hiAVWAP_s += vwapHi * volume
    loAVWAP_s += vwapLo * volume
    hiAVWAP_v += volume
    loAVWAP_v += volume
    hiAVWAP_s_next += vwapHi * volume
    loAVWAP_s_next += vwapLo * volume
    hiAVWAP_v_next += volume
    loAVWAP_v_next += volume


    if(state!=-1 and d<lowerBand)
        state := -1
    else if(state!=+1 and d>upperBand)
        state := +1

    if(hi>phi and state==+1 and k<d and k<lowerReversal)
        hi := phi
        hiAVWAP_s := hiAVWAP_s_next
        hiAVWAP_v := hiAVWAP_v_next
    if(lo<plo and state==-1 and k>d and k>upperReversal)
        lo := plo
        loAVWAP_s := loAVWAP_s_next
        loAVWAP_v := loAVWAP_v_next
    
    avwap = Boundary.new(hiAVWAP_s / hiAVWAP_v, loAVWAP_s / loAVWAP_v)
    avwap_next = Boundary.new(hiAVWAP_s_next / hiAVWAP_v_next, loAVWAP_s_next / loAVWAP_v_next)

    [avwap, avwap_next]
///////////////////////////////////////////////////

// Demo
ATR = "Average True Range", CONFIRM = "Confirmation", DISPLAY = "Display"
WMA = "WMA", EMA = "EMA", SMA = "SMA", VWMA = "VWMA", VAWMA = "VAWMA"

mode = input.string(VAWMA, "Mode", options=[SMA,EMA,WMA,VWMA,VAWMA], group=ATR, tooltip="Selects which averaging function will be used to determine the ATR value.")
atrPeriod = input.int(120, "Period", group=ATR, tooltip="The number of bars to use in calculating the ATR value.")
atrM = input.float(3.0, title="Multiplier", step=0.5, group=ATR, tooltip="The multiplier used when defining the super trend limits.")

closeBars = input.int(2, "Closed Bars", minval = 0, group=CONFIRM, tooltip="The number of closed bars that have to exceed the super-trend value before the trend reversal is confirmed.")


st = superTrend(atrM, atrPeriod, mode=mode, closeBars=closeBars)
plot(st.up)
plot(st.dn)

stc = superTrendCleaned(atrM, atrPeriod, mode=mode, closeBars=closeBars)
plot(stc.up, color=color.green)
plot(stc.dn, color=color.green)

// [trendAuto, upAuto, dnAuto, unconfirmedAuto, warnAuto, reversalAuto] =
//   superTrendAuto(26, 2.5, 1000)
// plot(upAuto, color=color.orange)
// plot(dnAuto, color=color.orange)

Overview

Support Resistance and Trend includes a custom SuperTrend function with configurable bar confirmation requirements to delay trend flips and filter out false breakouts. Custom user-defined types track boundary thresholds, hit counts, and reversal alerts. Because this script is a library, it performs calculations for other scripts and does not draw plots on the chart.

Details

Published by

Electrified-Trading on GitHub

Type

Library, Pine Script v5

Draws

Library (no plots)

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
ModestringVAWMAmode
Periodint120atrPeriod
Multiplierfloat3.0atrM
Closed Barsint2closeBars
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

261 stars

AIActivationFunctionsBipolarSigmoid is a Pine Script library that provides mathematical implementations of the bipolar sigmoid activation function and its derivatives for machine learning algorithms. It calculates bipolar sigmoid values bounded between -1 and

Library v5 AI / machine learning
Updated 4 years ago · None stated GitHub repository of AIActivationFunctionsBipolarSigmoid

KernelFunctions

by artificial-intelligence-edge
75 stars

KernelFunctions is a Pine Script v5 library that exports kernel weight functions for Nadaraya-Watson style estimation. It calculates a Rational Quadratic kernel, a Gaussian kernel based on a radial basis function, and a periodic kernel that models repeating be

Library v5
Updated 2 days ago · MIT GitHub repository of KernelFunctions

Ta

by nersent
29 stars

This Pine Script v5 library exports thin wrappers around built-in technical analysis functions. It covers moving averages, momentum measures such as RSI and CCI, volatility tools including ATR and standard deviation, range extremes, cross detection, and runnin

Library v5
Updated 11 months ago · Custom licence GitHub repository of Ta

Bands

by heyphat
26 stars

This library exports a Band type and functions that build a simple-moving-average basis with upper and lower envelopes from standard deviation. It classifies a source as above, below, or inside those envelopes, measures band width, and scales an imported z-sco

Library v6 Volatility & bandsMoving averages
Updated 2 months ago · AGPL-3.0 GitHub repository of Bands

Mylib

by ferranbt
21 stars

This script serves as a minimal utility library written in Pine Script v6. It provides an exported helper function that calculates the sum of two numeric arguments. As a reusable code library, it produces no visual plots, charts, or trading signals, and it con

Library v6
Updated 7 weeks ago · MPL-2.0 GitHub repository of Mylib

HLevel

by stupenkov
14 stars

HLevel is a Pine Script v5 utility library designed to manage horizontal price levels for cryptocurrency charts. It defines custom types for pivots and levels, along with methods to initialize, add, track, and expire price levels based on pivot high and pivot

Library v5
Updated 3 years ago · None stated GitHub repository of HLevel

More libraries

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers