S&R Zone Signals Indicator

This simple script is designed for structure based traders and trading strategies, although it can be used by anyone who uses price zones and basic candlestick patterns in their trading.

The purpose of this indicator is to generate trading alerts when these patterns occur in order to reduce the screen time required to monitor setups.

How It Works

If price puts in an Engulfing Candle, a Doji Candle, a Hammer Candle or a Shooting Star Candle pattern within the zone you specify, then a trading signal and alert will be generated.

If you leave either zone set to 0 then that zone will not be used, meaning that you can use this to detect both support and resistance signals, or only signals at support, or only signals at resistance.


First resistance zone.

Second resistance zone.

First support zone.

Second support zone.

Draw Signals:
Enable/Disable Visual Signals

How Far To Look Back For Swing High/Lows:
Used for detecting fractal lows for candle patterns.

Doji Size:
This changes the maximum size of detectable doji candles.

Hammer Wick Size:
This changes the minimum size of the wick of detectable hammer/shooting star candles.

Must Engulf Wick:
If enabled, then engulfing candles must engulf the previous wick to be considered valid.

Show Engulfing Candles:
Enable/Disable visual signals for engulfing candles.

Show Doji Candles:
Enable/Disable visual signals for doji candles.

Show Hammer Candles:
Enable/Disable visual signals for hammer and shooting star candles.

Pine Script Basics Course
Pine Script Mastery Course

Source Code

// @version=4
// Created by Matthew J. Slabosz
// www.zenandtheartoftrading.com
study("Zone Signals", shorttitle="Zones", overlay=true)

// Get user inputs
r1 = input(type=input.float, defval=0.0, title="R1")
r2 = input(type=input.float, defval=0.0, title="R2")
s1 = input(type=input.float, defval=0.0, title="S1")
s2 = input(type=input.float, defval=0.0, title="S2")
drawSignals = input(type=input.bool, defval=true, title="Draw Signals?")
lookback = input(7, minval=1, title="How Far To Look Back For Swing High/Lows?")
dojiSize = input(0.5, minval=0, title="Doji Size (in pips):")
hammerWickSize = input(2.5, minval=0.1, title="Hammer Wick Size (X Body):")
engulfWick = input(title="Must Engulf Wick?", type=input.bool, defval=false)
showEC = input(title="Show Engulfing Candles", type=input.bool, defval=true)
showDJ = input(title="Show Doji Candles", type=input.bool, defval=false)
showHM = input(title="Show Hammer Candles", type=input.bool, defval=false)

// Flip resistance values if they are in the wrong order
if r1 < r2
    t = r1
    r1 := r2
    r2 := t

// Flip support values if they are in the wrong order
if s1 < s2
    t = s1
    s1 := s2
    s2 := t

// Check if our basic conditions are met
fractalBuy1 = close[1] < open[1] and close > open[1] and low > low[1] and low[1] < low[2] and 
   low[1] == lowest(low, 4) and open <= close[1]
fractalBuy2 = close[1] < open[1] and close > open[1] and low < low[1] and 
   low == lowest(low, 4) and open <= close[1]
fractalSell1 = close[1] > open[1] and close < open[1] and high > high[1] and 
   high == highest(high, 4) and open >= close[1]
fractalSell2 = close[1] > open[1] and close < open[1] and high < high[1] and high[1] > high[2] and 
   high[1] == highest(high, 4) and open >= close[1]
engulfsSwingHighRule = close <= highest(close, lookback)
engulfsSwingLowRule = close >= lowest(close, lookback)

// Gather data on candlesticks
bodySize = abs(open - close)
topWickSize = abs(high - close)
bottomWickSize = abs(low - close)
bodySizePoints = bodySize / syminfo.mintick
pointsCloseMinusOpen = abs(close - open[1])

// Detect valid engulfing candlestick patterns
bullishEngulfing = fractalBuy1 or fractalBuy2
bearishEngulfing = fractalSell1 or fractalSell2
bullishEcWick = engulfWick ? close >= high[1] : false
bearishEcWick = engulfWick ? close <= low[1] : false

// Detect other patterns (dojis & hammers)
hammer = bottomWickSize >= bodySize * hammerWickSize and topWickSize <= bodySize / 2 and 
   low <= lowest(low, lookback) and 
   (close < open and open[1] >= close or close > open and close[1] <= open) and 
   close <= highest(close, lookback)
star = topWickSize >= bodySize * hammerWickSize and bottomWickSize <= bodySize / 2 and 
   high >= highest(high, lookback) and 
   (close > open and open[1] <= close or close < open and close[1] <= open) and 
   close >= lowest(close, lookback)
doji = bodySize <= dojiSize * 10 * syminfo.mintick
dojiLong = doji and close <= highest(close, lookback) and low <= lowest(low, lookback)
dojiShort = doji and close >= lowest(close, lookback) and high >= highest(high, lookback)

// Draw invisible plot lines required for zone color fill
zr1 = plot(r1 != 0 ? r1 : na, color=color.red, transp=50)
zr2 = plot(r2 != 0 ? r2 : na, color=color.red, transp=50)
zs1 = plot(s1 != 0 ? s1 : na, color=color.green, transp=50)
zs2 = plot(s2 != 0 ? s2 : na, color=color.green, transp=50)

// Fill zones
fill(zr1, zr2, color=color.red, transp=80)
fill(zs1, zs2, color=color.green, transp=80)

// Candle rules for resistance zone
resFlag = r1 > r2 ? high >= r2 and high <= r1 or close >= r2 and close <= r1 : 
   high >= r1 and high <= r2 or close >= r1 and close <= r2

// Determine whether or not we have a valid setup
validLong = (showEC and bullishEngulfing or showDJ and dojiLong or showHM and hammer) and 
   low <= s1 and low >= s2
validShort = (showEC and bearishEngulfing or showDJ and dojiShort or showHM and star) and 
   high <= r1 and high >= r2

// Plot signals
plotshape(validLong, title="Long Entry", location=location.belowbar, color=bullishEcWick ? color.lime : color.green, transp=0, style=shape.triangleup, text="Long")
plotshape(validShort, title="Short Entry", color=bullishEcWick ? color.maroon : color.red, transp=0, style=shape.triangledown, text="Short")

// Send out an alert if this candle meets our conditions
alertcondition(validLong or validShort, title="Zone Alert!", message="Zone alert for {{ticker}}")

Last Updated: 17th August, 2020

Free Premium Charts!