Bears and Bulls.pine
Copy
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © claygrace74
//@version=6
indicator(title="Bears and Bulls", shorttitle="B&B", overlay=true, max_labels_count=500)
// ==================== RSI Filter Settings ====================
var rsi_group = "RSI Filter Settings"
rsisrc = input.source(close, "RSI Source", group=rsi_group)
rsilen = input.int(14, "RSI Length", minval=1, group=rsi_group)
rsiob = input.int(60, "RSI Overbought Level", minval=50, maxval=100, group=rsi_group)
rsios = input.int(50, "RSI Oversold Level", minval=0, maxval=50, group=rsi_group)
i_useRSI = input.bool(true, "Filter Patterns by RSI", group=rsi_group)
// ==================== Pattern Categories ====================
var cat_group = "Pattern Categories"
i_showSingle = input.bool(true, "Single-Candle Patterns", group=cat_group)
i_showDouble = input.bool(true, "Double-Candle Patterns", group=cat_group)
i_showTriple = input.bool(true, "Triple-Candle Patterns", group=cat_group)
i_showMulti = input.bool(true, "Multi-Candle Patterns (4-5 bars)", group=cat_group)
// ==================== Volume Confirmation ====================
var vol_group = "Volume Confirmation"
i_useVol = input.bool(false, "Require Volume Spike", group=vol_group)
volMult = input.float(1.5, "Volume Spike Multiplier", minval=1.0, step=0.1, group=vol_group)
volLookback = input.int(20, "Volume Average Lookback", minval=5, group=vol_group)
// ==================== Display Settings ====================
var disp_group = "Display Settings"
i_showLabels = input.bool(true, "Show Pattern Name Labels", group=disp_group)
bullHighClr = input.color(#04F909, "Bull High Reliability", group=disp_group)
bullMedClr = input.color(color.new(#04F909, 30), "Bull Medium Reliability", group=disp_group)
bullLowClr = input.color(color.new(#04F909, 60), "Bull Low Reliability", group=disp_group)
bearHighClr = input.color(#F90404, "Bear High Reliability", group=disp_group)
bearMedClr = input.color(color.new(#F90404, 30), "Bear Medium Reliability", group=disp_group)
bearLowClr = input.color(color.new(#F90404, 60), "Bear Low Reliability", group=disp_group)
// ==================================================================================
// Core Calculations
// ==================================================================================
body = close - open
candleRange = high - low
abody = math.abs(body)
ratio = candleRange > 0 ? abody / candleRange : 0
longcandle = ratio > 0.6
bodytop = math.max(open, close)
bodybottom = math.min(open, close)
shadowtop = high - bodytop
shadowbottom = bodybottom - low
// RSI
rsival = ta.rsi(rsisrc, rsilen)
isrsiob = rsival >= rsiob
isrsios = rsival <= rsios
// Volume
volAvg = ta.sma(volume, volLookback)
volSpike = volume > volAvg * volMult
volOk = not i_useVol or volSpike
// RSI gate helpers
bullRSI = not i_useRSI or isrsios or isrsios[1]
bearRSI = not i_useRSI or isrsiob or isrsiob[1]
// ==================================================================================
// Bearish Patterns
// ==================================================================================
// --- Single candle (bear) ---
shooting_star = body[1] > 0 and longcandle[1] and high > high[1] and shadowtop > 2 * abody and shadowbottom < 0.3 * abody
shooting_star_doji = close[1] > open[1] and math.abs(close[1] - open[1]) / (high[1] - low[1]) >= 0.7 and math.abs(close - open) / candleRange < 0.1 and close[1] < close and close[1] < open and (high - math.max(close, open)) > (3 * math.abs(close - open)) and (math.min(close, open) - low) > (3 * math.abs(close - open))
the_hanging_man = close < open and 0.3 > math.abs(close - open) / candleRange and math.abs(close - open) / candleRange >= 0.1 and (math.min(close, open) - low) >= (2 * math.abs(close - open)) and (high - math.max(close, open)) > (0.25 * math.abs(close - open))
gravestone_doji_top = body[1] > 0 and longcandle[1] and high > high[1] and shadowtop > 3 * abody and shadowbottom < shadowtop / 3
dragonfly_doji_top = body[1] > 0 and longcandle[1] and high > high[1] and shadowbottom > 3 * abody and shadowtop < shadowbottom / 3
// --- Double candle (bear) ---
evening_star = close[2] > open[2] and math.abs(close[2] - open[2]) / (high[2] - low[2]) >= 0.7 and 0.3 > math.abs(close[1] - open[1]) / (high[1] - low[1]) and math.abs(close[1] - open[1]) / (high[1] - low[1]) >= 0.1 and close < open and math.abs(close - open) / candleRange >= 0.7 and close[2] < close[1] and close[2] < open[1] and close[1] > open and open[1] > open and close < close[2]
evening_star_doji = close[2] > open[2] and math.abs(close[2] - open[2]) / (high[2] - low[2]) >= 0.7 and math.abs(close[1] - open[1]) / (high[1] - low[1]) < 0.1 and close < open and math.abs(close - open) / candleRange >= 0.7 and close[2] < close[1] and close[2] < open[1] and close[1] > open and open[1] > open and close < close[2] and (high[1] - math.max(close[1], open[1])) > (3 * math.abs(close[1] - open[1])) and (math.min(close[1], open[1]) - low[1]) > (3 * math.abs(close[1] - open[1]))
dark_cloud_cover = close[1] > open[1] and math.abs(close[1] - open[1]) / (high[1] - low[1]) >= 0.7 and close < open and math.abs(close - open) / candleRange >= 0.7 and open >= close[1] and close > open[1] and close < ((open[1] + close[1]) / 2)
bearish_engulfing = close[1] > open[1] and 0.3 > math.abs(close[1] - open[1]) / (high[1] - low[1]) and math.abs(close[1] - open[1]) / (high[1] - low[1]) >= 0.1 and close < open and math.abs(close - open) / candleRange >= 0.7 and high[1] < open and low[1] > close
bearish_engulfing_doji = math.abs(close[1] - open[1]) / (high[1] - low[1]) < 0.1 and close > open and math.abs(close - open) / candleRange >= 0.7 and high[1] < close and low[1] > open and (high[1] - math.max(close[1], open[1])) > (3 * math.abs(close[1] - open[1])) and (math.min(close[1], open[1]) - low[1]) <= math.abs(close[1] - open[1])
bearish_harami = body[1] > 0 and body < 0 and longcandle[1] and bodybottom > bodybottom[1] and bodytop < bodytop[1]
bearish_harami_cross = body[1] > 0 and longcandle[1] and bodybottom > bodybottom[1] and bodytop < bodytop[1] and ratio < 0.3 and candleRange < 0.3 * candleRange[1]
last_engulfing_top = body[1] < 0 and body > 0 and bodybottom < bodybottom[1] and bodytop > bodytop[1] and longcandle
descending_hawk = body[1] > 0 and body > 0 and longcandle[1] and bodybottom > bodybottom[1] and bodytop < bodytop[1]
two_crows = body[2] > 0 and body[1] < 0 and body < 0 and longcandle[2] and open[1] > close[2] and close[1] > close[2] and open < bodytop[1] and open > bodybottom[1] and close < bodytop[2] and close > bodybottom[2]
// --- Triple candle (bear) ---
three_inside_down = body[2] > 0 and body[1] < 0 and body < 0 and bearish_harami[1] and close < close[1]
three_outside_down = body[2] > 0 and body[1] < 0 and body < 0 and bearish_engulfing[1] and close < close[1]
three_black_crows = body[2] < 0 and body[1] < 0 and body < 0 and longcandle[2] and longcandle[1] and longcandle and low[1] < low[2] and low < low[1] and close[1] < close[2] and close < close[1] and open[1] < open[2] and open[1] > close[2] and open < open[1] and open > close[1]
upside_gap_two_crows = body[2] > 0 and body[1] < 0 and body < 0 and longcandle[2] and open[1] > close[2] and bodytop > bodytop[1] and bodybottom < bodybottom[1] and close > close[2]
abandoned_baby_top = body[2] > 0 and body < 0 and longcandle[2] and ratio[1] < 0.3 and low[1] > high[2] and low[1] > high
advance_block = body[2] > 0 and body[1] > 0 and body > 0 and high[2] < high[1] and high[1] < high and open[1] > bodybottom[2] and open[1] < bodytop[2] and open > bodybottom[1] and open < bodytop[1] and abody[1] < abody[2] and abody < abody[1]
// --- Multi candle (bear) ---
falling_three_methods = body[4] < 0 and body[3] > 0 and body[1] > 0 and body < 0 and longcandle[4] and longcandle and close[2] > close[3] and close[1] > close[2] and low[2] > low[3] and low[1] > low[2] and high[1] < high[4] and open < close[1] and close < low[4] and close < low[3] and close < low[2] and close < low[1]
bearish_three_line_strike = body[3] < 0 and body[2] < 0 and body[1] < 0 and body > 0 and longcandle[3] and longcandle[2] and longcandle[1] and close[2] < close[3] and close[1] < close[2] and open < close[1] and close > open[3]
bearish_breakaway = body[4] > 0 and body[3] > 0 and body < 0 and open[3] > close[4] and close[2] > close[3] and close[1] > close[2] and longcandle and close > close[4] and close < open[3]
// ==================================================================================
// Bullish Patterns
// ==================================================================================
// --- Single candle (bull) ---
hammer = body[1] < 0 and longcandle[1] and low < low[1] and shadowbottom > 2 * abody and shadowtop < 0.3 * abody
inverted_hammer = body[1] < 0 and longcandle[1] and low < low[1] and shadowtop > 2 * abody and shadowbottom < 0.3 * abody
dragonfly_doji_bottom = body[1] < 0 and longcandle[1] and low < low[1] and shadowbottom > 3 * abody and shadowtop < shadowbottom / 3
// --- Double candle (bull) ---
morning_star = close[2] < open[2] and math.abs(close[2] - open[2]) / (high[2] - low[2]) >= 0.7 and 0.3 > math.abs(close[1] - open[1]) / (high[1] - low[1]) and math.abs(close[1] - open[1]) / (high[1] - low[1]) >= 0.1 and close > open and math.abs(close - open) / candleRange >= 0.7 and close[2] > close[1] and close[2] > open[1] and close[1] < open and open[1] < open and close > close[2]
morning_star_doji = close[2] < open[2] and math.abs(close[2] - open[2]) / (high[2] - low[2]) >= 0.7 and math.abs(close[1] - open[1]) / (high[1] - low[1]) < 0.1 and close > open and math.abs(close - open) / candleRange >= 0.7 and close[2] > close[1] and close[2] > open[1] and close[1] < open and open[1] < open and close > close[2] and (high[1] - math.max(close[1], open[1])) > (3 * math.abs(close[1] - open[1])) and (math.min(close[1], open[1]) - low[1]) > (3 * math.abs(close[1] - open[1]))
piercing_line = close[1] < open[1] and math.abs(close[1] - open[1]) / (high[1] - low[1]) >= 0.7 and close > open and math.abs(close - open) / candleRange >= 0.7 and open <= close[1] and close < open[1] and close < ((open[1] + close[1]) / 2)
bullish_harami = close[1] < open[1] and math.abs(close[1] - open[1]) / (high[1] - low[1]) >= 0.7 and 0.3 > math.abs(close - open) / candleRange and math.abs(close - open) / candleRange >= 0.1 and high < open[1] and low > close[1]
bullish_engulfing = body[1] < 0 and body > 0 and bodybottom < bodybottom[1] and bodytop > bodytop[1] and longcandle
bullish_engulfing_doji = math.abs(close[1] - open[1]) / (high[1] - low[1]) < 0.1 and close > open and math.abs(close - open) / candleRange >= 0.7 and high[1] < close and low[1] > open and (high[1] - math.max(close[1], open[1])) > (3 * math.abs(close[1] - open[1])) and (math.min(close[1], open[1]) - low[1]) <= math.abs(close[1] - open[1])
bullish_harami_cross = body[1] < 0 and longcandle[1] and bodybottom > bodybottom[1] and bodytop < bodytop[1] and ratio < 0.3 and candleRange < 0.3 * candleRange[1]
last_engulfing_bottom = body[1] > 0 and body < 0 and bodybottom < bodybottom[1] and bodytop > bodytop[1] and longcandle
homing_pigeon = body[1] < 0 and body < 0 and longcandle[1] and bodybottom > bodybottom[1] and bodytop < bodytop[1]
// --- Triple candle (bull) ---
three_white_soldiers = body[2] > 0 and body[1] > 0 and body > 0 and high[1] > high[2] and high > high[1] and close[1] > close[2] and close > close[1] and open[1] > open[2] and open[1] < close[2] and open > open[1] and open < close[1]
three_inside_up = body[2] < 0 and body[1] > 0 and body > 0 and bullish_harami[1] and close > close[1]
three_outside_up = body[2] < 0 and body[1] > 0 and body > 0 and bullish_engulfing[1] and close > close[1]
three_stars_in_south = body[2] < 0 and body[1] < 0 and body < 0 and shadowtop[2] < candleRange[2] / 4 and shadowbottom[2] > abody[2] / 2 and low[1] > low[2] and high[1] < high[2] and abody[1] < abody[2] and shadowtop[1] < candleRange[1] / 4 and shadowbottom[1] > abody[1] / 2 and low > low[1] and high < high[1] and abody < abody[1] and shadowtop < candleRange / 4 and shadowbottom < candleRange / 4
abandoned_baby_bottom = body[2] < 0 and body > 0 and longcandle[2] and ratio[1] < 0.3 and high[1] < low[2] and high[1] < low
// --- Multi candle (bull) ---
rising_three_methods = body[4] > 0 and body[3] < 0 and body[1] < 0 and body > 0 and longcandle[4] and longcandle and close[2] < close[3] and close[1] < close[2] and high[2] < high[3] and high[1] < high[2] and low[1] > low[4] and open > close[1] and close > high[4] and close > high[3] and close > high[2] and close > high[1]
bullish_mat_hold = body[4] > 0 and body[3] < 0 and body[1] < 0 and body > 0 and longcandle[4] and close[3] > close[4] and close[2] < close[3] and close[1] < close[2] and high[2] < high[3] and high[1] < high[2] and low[1] > low[4] and open > close[1] and close > high[4] and close > high[3] and close > high[2] and close > high[1]
bullish_three_line_strike = body[3] > 0 and body[2] > 0 and body[1] > 0 and body < 0 and longcandle[3] and longcandle[2] and longcandle[1] and close[2] > close[3] and close[1] > close[2] and open > close[1] and close < open[3]
bullish_breakaway = body[4] < 0 and body[3] < 0 and body > 0 and open[3] < close[4] and close[2] < close[3] and close[1] < close[2] and longcandle and close < close[4] and close > open[3]
concealing_baby_swallow = body[3] < 0 and body[2] < 0 and body[1] < 0 and body < 0 and ratio[3] > 0.8 and ratio[2] > 0.8 and ratio > 0.8 and open[1] < close[2] and high[1] > close[2] and shadowtop[1] > 0.6 * (abody[1] + shadowbottom[1]) and bodybottom < bodybottom[1] and bodytop > high[1]
// ==================================================================================
// Aggregate Signals by Reliability Tier
// ==================================================================================
// Bull aggregates
highRelBull = (bullRSI and volOk) and (i_showTriple and (three_white_soldiers or morning_star or morning_star_doji or three_outside_up or abandoned_baby_bottom) or i_showDouble and bullish_engulfing)
medRelBull = (bullRSI and volOk) and (i_showDouble and (piercing_line or bullish_harami or bullish_harami_cross or bullish_engulfing_doji or last_engulfing_bottom or homing_pigeon) or i_showTriple and (three_inside_up or three_stars_in_south) or i_showMulti and (rising_three_methods or bullish_mat_hold or bullish_three_line_strike or bullish_breakaway))
lowRelBull = (bullRSI and volOk) and i_showSingle and (hammer or inverted_hammer or dragonfly_doji_bottom) or (bullRSI and volOk) and i_showMulti and concealing_baby_swallow
// Bear aggregates
highRelBear = (bearRSI and volOk) and (i_showTriple and (three_black_crows or evening_star or evening_star_doji or three_outside_down or abandoned_baby_top) or i_showDouble and bearish_engulfing)
medRelBear = (bearRSI and volOk) and (i_showDouble and (dark_cloud_cover or bearish_harami or bearish_harami_cross or bearish_engulfing_doji or last_engulfing_top or descending_hawk or two_crows) or i_showTriple and (three_inside_down or upside_gap_two_crows or advance_block) or i_showMulti and (falling_three_methods or bearish_three_line_strike or bearish_breakaway))
lowRelBear = (bearRSI and volOk) and i_showSingle and (shooting_star or shooting_star_doji or the_hanging_man or gravestone_doji_top or dragonfly_doji_top)
anyBull = highRelBull or medRelBull or lowRelBull
anyBear = highRelBear or medRelBear or lowRelBear
// ==================================================================================
// Build Pattern Name Strings (series — for label.new)
// ==================================================================================
f_bullName() =>
string n = ""
// High reliability
if three_white_soldiers
n := "3 White Soldiers"
else if morning_star
n := "Morning Star"
else if morning_star_doji
n := "Morning Star Doji"
else if bullish_engulfing
n := "Bullish Engulfing"
else if three_outside_up
n := "3 Outside Up"
else if abandoned_baby_bottom
n := "Abandoned Baby"
// Medium reliability
else if piercing_line
n := "Piercing Line"
else if bullish_harami
n := "Bullish Harami"
else if bullish_harami_cross
n := "Harami Cross"
else if bullish_engulfing_doji
n := "Engulfing Doji"
else if rising_three_methods
n := "Rising 3 Methods"
else if bullish_mat_hold
n := "Mat Hold"
else if bullish_three_line_strike
n := "3 Line Strike"
else if three_inside_up
n := "3 Inside Up"
else if bullish_breakaway
n := "Breakaway"
else if three_stars_in_south
n := "3 Stars South"
else if last_engulfing_bottom
n := "Last Engulf"
else if homing_pigeon
n := "Homing Pigeon"
// Low reliability
else if hammer
n := "Hammer"
else if inverted_hammer
n := "Inv Hammer"
else if dragonfly_doji_bottom
n := "Dragonfly Doji"
else if concealing_baby_swallow
n := "Baby Swallow"
n
f_bearName() =>
string n = ""
// High reliability
if three_black_crows
n := "3 Black Crows"
else if evening_star
n := "Evening Star"
else if evening_star_doji
n := "Evening Star Doji"
else if bearish_engulfing
n := "Bearish Engulfing"
else if three_outside_down
n := "3 Outside Down"
else if abandoned_baby_top
n := "Abandoned Baby"
// Medium reliability
else if dark_cloud_cover
n := "Dark Cloud Cover"
else if bearish_harami
n := "Bearish Harami"
else if bearish_harami_cross
n := "Harami Cross"
else if bearish_engulfing_doji
n := "Engulfing Doji"
else if falling_three_methods
n := "Falling 3 Methods"
else if bearish_three_line_strike
n := "3 Line Strike"
else if three_inside_down
n := "3 Inside Down"
else if last_engulfing_top
n := "Last Engulf"
else if bearish_breakaway
n := "Breakaway"
else if descending_hawk
n := "Desc Hawk"
else if upside_gap_two_crows
n := "Gap 2 Crows"
else if advance_block
n := "Advance Block"
else if two_crows
n := "Two Crows"
// Low reliability
else if shooting_star
n := "Shooting Star"
else if shooting_star_doji
n := "Shooting Star Doji"
else if the_hanging_man
n := "Hanging Man"
else if gravestone_doji_top
n := "Gravestone Doji"
else if dragonfly_doji_top
n := "Dragonfly Doji"
n
bullName = f_bullName()
bearName = f_bearName()
// ==================================================================================
// Plot Signals — 6 plotshape calls + labels for pattern names
// ==================================================================================
// Bull shapes by tier
plotshape(highRelBull, style=shape.triangleup, location=location.belowbar, color=bullHighClr, size=size.small, title="High Rel Bull")
plotshape(medRelBull, style=shape.triangleup, location=location.belowbar, color=bullMedClr, size=size.tiny, title="Med Rel Bull")
plotshape(lowRelBull, style=shape.triangleup, location=location.belowbar, color=bullLowClr, size=size.tiny, title="Low Rel Bull")
// Bear shapes by tier
plotshape(highRelBear, style=shape.triangledown, location=location.abovebar, color=bearHighClr, size=size.small, title="High Rel Bear")
plotshape(medRelBear, style=shape.triangledown, location=location.abovebar, color=bearMedClr, size=size.tiny, title="Med Rel Bear")
plotshape(lowRelBear, style=shape.triangledown, location=location.abovebar, color=bearLowClr, size=size.tiny, title="Low Rel Bear")
// Pattern name labels (dynamic text via label.new)
if i_showLabels and anyBull
lbl_color = highRelBull ? bullHighClr : medRelBull ? bullMedClr : bullLowClr
label.new(bar_index, low, bullName, style=label.style_none, textcolor=lbl_color, size=size.small)
if i_showLabels and anyBear
lbl_color = highRelBear ? bearHighClr : medRelBear ? bearMedClr : bearLowClr
label.new(bar_index, high, bearName, style=label.style_none, textcolor=lbl_color, size=size.small)
// ==================================================================================
// Alert Conditions
// ==================================================================================
alertcondition(anyBull, "Any Bullish Pattern", "Bullish candlestick pattern detected (RSI-filtered)")
alertcondition(anyBear, "Any Bearish Pattern", "Bearish candlestick pattern detected (RSI-filtered)")
alertcondition(anyBull and volSpike, "Volume-Confirmed Bullish", "Bullish pattern with volume spike confirmation")
alertcondition(anyBear and volSpike, "Volume-Confirmed Bearish", "Bearish pattern with volume spike confirmation")
alertcondition(highRelBull, "High-Reliability Bullish", "Strong bullish pattern (3WS, MStar, Engulfing, 3OU)")
alertcondition(highRelBear, "High-Reliability Bearish", "Strong bearish pattern (3BC, EStar, Engulfing, 3OD)")
Show all 296 lines