PROTECTED SOURCE SCRIPT
Yaso- Structural Signals: Buy/Sell (Clean v5)

//version=5
indicator("Structural Signals: Buy/Sell (Clean v5)", overlay=true)
//===================== Inputs =====================
grpCtx = "Context (Structure)"
lenDon = input.int(20, "Donchian Lookback (S/R proxy)", minval=5, group=grpCtx)
ema20On = input.bool(true, "Show EMA 20", group=grpCtx)
ema50On = input.bool(true, "Show EMA 50", group=grpCtx)
ema200On = input.bool(true, "Show EMA 200", group=grpCtx)
grpVol = "Volume Confirmation"
volLen = input.int(20, "Volume SMA Length", minval=2, group=grpVol)
volMult = input.float(1.5, "Volume Spike × SMA", minval=1.0, step=0.1, group=grpVol)
grpCand = "Candlestick Reversal (at Structure)"
useHammer = input.bool(true, "BUY: Hammer/Bottoming Tail near Support", group=grpCand)
useStar = input.bool(true, "SELL: Shooting Star/Topping Tail near Resistance", group=grpCand)
srNearPct = input.float(0.004, "‘Near’ S/R tolerance (0.004=0.4%)", step=0.001, minval=0.0, group=grpCand)
grpBreak = "Breakouts / Breakdowns"
useBO = input.bool(true, "BUY: Breakout above Resistance (Donchian High)", group=grpBreak)
useBD = input.bool(true, "SELL: Breakdown below Support (Donchian Low)", group=grpBreak)
grpPats = "Double Tops / Bottoms (pivots)"
useDB = input.bool(true, "BUY: Double Bottom / Higher Low", group=grpPats)
useDT = input.bool(true, "SELL: Double Top / Lower High", group=grpPats)
pvLeft = input.int(3, "Pivot Left Bars", minval=2, group=grpPats)
pvRight = input.int(3, "Pivot Right Bars", minval=2, group=grpPats)
matchTolPct = input.float(0.0075, "Price Match Tolerance (0.75%)", step=0.0005, minval=0.0, group=grpPats)
grpXover = "Trend Filters (Crosses)"
useGolden = input.bool(true, "BUY: Golden Cross (EMA50 > EMA200)", group=grpXover)
useDeath = input.bool(true, "SELL: Death Cross (EMA50 < EMA200)", group=grpXover)
grpGap = "Gap Fills (Daily preferred)"
useGapUpRev = input.bool(true, "SELL: Gap-Up Fill & Reversal (close < prior close)", group=grpGap)
useGapDnRev = input.bool(true, "BUY: Gap-Down Fill & Reversal (close > prior close)", group=grpGap)
minGapPct = input.float(0.01, "Min Gap % (1% = 0.01)", minval=0.0, step=0.001, group=grpGap)
grpAgg = "Alert Controls"
aggregateAlerts = input.bool(true, "Enable Aggregate BUY/SELL Alerts", group=grpAgg)
//===================== Context =====================
ema20 = ta.ema(close, 20)
ema50 = ta.ema(close, 50)
ema200 = ta.ema(close, 200)
donHi = ta.highest(high, lenDon)
donLo = ta.lowest(low, lenDon)
plot(ema20On ? ema20 : na, "EMA 20", color=color.new(color.teal, 0), linewidth=2)
plot(ema50On ? ema50 : na, "EMA 50", color=color.new(color.orange, 0), linewidth=2)
plot(ema200On ? ema200 : na, "EMA 200", color=color.new(color.blue, 0), linewidth=2)
plot(donHi, "Donchian High", color=color.new(color.red, 40))
plot(donLo, "Donchian Low", color=color.new(color.green,40))
volSMA = ta.sma(volume, volLen)
volSpike = volume > volSMA * volMult
//===================== Helpers =====================
near(val, ref, pct) =>
// true if |val - ref| / ref <= pct (with nz guard)
math.abs(val - ref) / nz(ref, val) <= pct
lowerWick() =>
(open < close ? open : close) - low
upperWick() =>
high - (open > close ? open : close)
bodySize() =>
math.abs(close - open)
isHammer() =>
lw = lowerWick()
uw = upperWick()
bd = bodySize()
lw >= bd * 2 and uw <= bd * 0.6 and close > open
isShootingStar() =>
lw = lowerWick()
uw = upperWick()
bd = bodySize()
uw >= bd * 2 and lw <= bd * 0.6 and close < open
nearSupport = near(low, donLo, srNearPct) or near(low, ema200, srNearPct)
nearResist = near(high, donHi, srNearPct) or near(high, ema200, srNearPct)
//===================== Signals =====================
// Breakouts / Breakdowns
buyBreakout = useBO and ta.crossover(close, donHi[1]) and (volSpike or close > donHi[1])
sellBreakdown = useBD and ta.crossunder(close, donLo[1]) and (volSpike or close < donLo[1])
// Pivots → Double Bottom / Top
pL = ta.pivotlow(low, pvLeft, pvRight)
pH = ta.pivothigh(high, pvLeft, pvRight)
lastLow = ta.valuewhen(pL, low[pvRight], 0)
prevLow = ta.valuewhen(pL, low[pvRight], 1)
lastHigh = ta.valuewhen(pH, high[pvRight], 0)
prevHigh = ta.valuewhen(pH, high[pvRight], 1)
priceMatch(a, b, tol) =>
not na(a) and not na(b) and math.abs(a - b) / b <= tol
doubleBottom = useDB and priceMatch(lastLow, prevLow, matchTolPct) and nz(lastLow) > nz(prevLow)
doubleTop = useDT and priceMatch(lastHigh, prevHigh, matchTolPct) and nz(lastHigh) < nz(prevHigh)
// Crosses (trend)
goldenCross = useGolden and ta.crossover(ema50, ema200)
deathCross = useDeath and ta.crossunder(ema50, ema200)
// Gap fill reversals (daily)
isDaily = timeframe.isdaily
gapUp = isDaily and open > close[1] * (1 + minGapPct)
gapDown = isDaily and open < close[1] * (1 - minGapPct)
gapUpFillRev = useGapUpRev and gapUp and high >= close[1] and close < close[1]
gapDnFillRev = useGapDnRev and gapDown and low <= close[1] and close > close[1]
// Candles at structure
hammerAtSupport = useHammer and isHammer() and nearSupport
starAtResist = useStar and isShootingStar() and nearResist
// Aggregate booleans (no arrays, no loops)
anyBuy = hammerAtSupport or buyBreakout or doubleBottom or goldenCross or gapDnFillRev
anySell = starAtResist or sellBreakdown or doubleTop or deathCross or gapUpFillRev
//===================== Plots =====================
plotshape(hammerAtSupport, title="BUY: Hammer @ Support", style=shape.triangleup, color=color.new(color.lime, 0), size=size.tiny, location=location.belowbar, text="Hammers")
plotshape(buyBreakout, title="BUY: Breakout", style=shape.triangleup, color=color.new(color.green, 0), size=size.tiny, location=location.belowbar, text="BO")
plotshape(doubleBottom, title="BUY: Double Bottom", style=shape.triangleup, color=color.new(color.teal, 0), size=size.tiny, location=location.belowbar, text="DB")
plotshape(goldenCross, title="BUY: Golden Cross", style=shape.triangleup, color=color.new(color.aqua, 0), size=size.tiny, location=location.belowbar, text="GC")
plotshape(gapDnFillRev, title="BUY: Gap-Down Reversal",style=shape.triangleup, color=color.new(color.fuchsia,0), size=size.tiny, location=location.belowbar, text="GapDnREV")
plotshape(starAtResist, title="SELL: Star @ Resistance",style=shape.triangledown, color=color.new(color.red, 0), size=size.tiny, location=location.abovebar, text="Starr")
plotshape(sellBreakdown, title="SELL: Breakdown", style=shape.triangledown, color=color.new(color.maroon, 0), size=size.tiny, location=location.abovebar, text="BD")
plotshape(doubleTop, title="SELL: Double Top", style=shape.triangledown, color=color.new(color.orange, 0), size=size.tiny, location=location.abovebar, text="DT")
plotshape(deathCross, title="SELL: Death Cross", style=shape.triangledown, color=color.new(color.purple, 0), size=size.tiny, location=location.abovebar, text="DC")
plotshape(gapUpFillRev, title="SELL: Gap-Up Reversal", style=shape.triangledown, color=color.new(color.yellow, 0), size=size.tiny, location=location.abovebar, text="GapUpREV")
plotshape(aggregateAlerts and anyBuy, title="BUY (Aggregate)", style=shape.labelup, color=color.new(color.green, 70), textcolor=color.black, text="BUY", location=location.belowbar, size=size.tiny)
plotshape(aggregateAlerts and anySell, title="SELL (Aggregate)", style=shape.labeldown, color=color.new(color.red, 70), textcolor=color.black, text="SELL", location=location.abovebar, size=size.tiny)
//===================== Alerts =====================
alertcondition(hammerAtSupport, "BUY: Hammer @ Support", "Hammer/Bottoming Tail at support on {{ticker}} {{interval}}")
alertcondition(buyBreakout, "BUY: Breakout", "Breakout above Donchian High on {{ticker}} {{interval}}")
alertcondition(doubleBottom, "BUY: Double Bottom", "Double Bottom/Higher Low on {{ticker}} {{interval}}")
alertcondition(goldenCross, "BUY: Golden Cross", "EMA50 crosses above EMA200 on {{ticker}} {{interval}}")
alertcondition(gapDnFillRev, "BUY: Gap-Down Reversal","Gap-down filled & reversed on {{ticker}} {{interval}}")
alertcondition(starAtResist, "SELL: Star @ Resistance","Shooting Star/Topping Tail at resistance on {{ticker}} {{interval}}")
alertcondition(sellBreakdown, "SELL: Breakdown", "Breakdown below Donchian Low on {{ticker}} {{interval}}")
alertcondition(doubleTop, "SELL: Double Top", "Double Top/Lower High on {{ticker}} {{interval}}")
alertcondition(deathCross, "SELL: Death Cross", "EMA50 crosses below EMA200 on {{ticker}} {{interval}}")
alertcondition(gapUpFillRev, "SELL: Gap-Up Reversal", "Gap-up filled & reversed on {{ticker}} {{interval}}")
// Aggregate
alertcondition(aggregateAlerts and anyBuy, "BUY: Aggregate", "Structural BUY signal on {{ticker}} {{interval}}")
alertcondition(aggregateAlerts and anySell, "SELL: Aggregate", "Structural SELL signal on {{ticker}} {{interval}}")
indicator("Structural Signals: Buy/Sell (Clean v5)", overlay=true)
//===================== Inputs =====================
grpCtx = "Context (Structure)"
lenDon = input.int(20, "Donchian Lookback (S/R proxy)", minval=5, group=grpCtx)
ema20On = input.bool(true, "Show EMA 20", group=grpCtx)
ema50On = input.bool(true, "Show EMA 50", group=grpCtx)
ema200On = input.bool(true, "Show EMA 200", group=grpCtx)
grpVol = "Volume Confirmation"
volLen = input.int(20, "Volume SMA Length", minval=2, group=grpVol)
volMult = input.float(1.5, "Volume Spike × SMA", minval=1.0, step=0.1, group=grpVol)
grpCand = "Candlestick Reversal (at Structure)"
useHammer = input.bool(true, "BUY: Hammer/Bottoming Tail near Support", group=grpCand)
useStar = input.bool(true, "SELL: Shooting Star/Topping Tail near Resistance", group=grpCand)
srNearPct = input.float(0.004, "‘Near’ S/R tolerance (0.004=0.4%)", step=0.001, minval=0.0, group=grpCand)
grpBreak = "Breakouts / Breakdowns"
useBO = input.bool(true, "BUY: Breakout above Resistance (Donchian High)", group=grpBreak)
useBD = input.bool(true, "SELL: Breakdown below Support (Donchian Low)", group=grpBreak)
grpPats = "Double Tops / Bottoms (pivots)"
useDB = input.bool(true, "BUY: Double Bottom / Higher Low", group=grpPats)
useDT = input.bool(true, "SELL: Double Top / Lower High", group=grpPats)
pvLeft = input.int(3, "Pivot Left Bars", minval=2, group=grpPats)
pvRight = input.int(3, "Pivot Right Bars", minval=2, group=grpPats)
matchTolPct = input.float(0.0075, "Price Match Tolerance (0.75%)", step=0.0005, minval=0.0, group=grpPats)
grpXover = "Trend Filters (Crosses)"
useGolden = input.bool(true, "BUY: Golden Cross (EMA50 > EMA200)", group=grpXover)
useDeath = input.bool(true, "SELL: Death Cross (EMA50 < EMA200)", group=grpXover)
grpGap = "Gap Fills (Daily preferred)"
useGapUpRev = input.bool(true, "SELL: Gap-Up Fill & Reversal (close < prior close)", group=grpGap)
useGapDnRev = input.bool(true, "BUY: Gap-Down Fill & Reversal (close > prior close)", group=grpGap)
minGapPct = input.float(0.01, "Min Gap % (1% = 0.01)", minval=0.0, step=0.001, group=grpGap)
grpAgg = "Alert Controls"
aggregateAlerts = input.bool(true, "Enable Aggregate BUY/SELL Alerts", group=grpAgg)
//===================== Context =====================
ema20 = ta.ema(close, 20)
ema50 = ta.ema(close, 50)
ema200 = ta.ema(close, 200)
donHi = ta.highest(high, lenDon)
donLo = ta.lowest(low, lenDon)
plot(ema20On ? ema20 : na, "EMA 20", color=color.new(color.teal, 0), linewidth=2)
plot(ema50On ? ema50 : na, "EMA 50", color=color.new(color.orange, 0), linewidth=2)
plot(ema200On ? ema200 : na, "EMA 200", color=color.new(color.blue, 0), linewidth=2)
plot(donHi, "Donchian High", color=color.new(color.red, 40))
plot(donLo, "Donchian Low", color=color.new(color.green,40))
volSMA = ta.sma(volume, volLen)
volSpike = volume > volSMA * volMult
//===================== Helpers =====================
near(val, ref, pct) =>
// true if |val - ref| / ref <= pct (with nz guard)
math.abs(val - ref) / nz(ref, val) <= pct
lowerWick() =>
(open < close ? open : close) - low
upperWick() =>
high - (open > close ? open : close)
bodySize() =>
math.abs(close - open)
isHammer() =>
lw = lowerWick()
uw = upperWick()
bd = bodySize()
lw >= bd * 2 and uw <= bd * 0.6 and close > open
isShootingStar() =>
lw = lowerWick()
uw = upperWick()
bd = bodySize()
uw >= bd * 2 and lw <= bd * 0.6 and close < open
nearSupport = near(low, donLo, srNearPct) or near(low, ema200, srNearPct)
nearResist = near(high, donHi, srNearPct) or near(high, ema200, srNearPct)
//===================== Signals =====================
// Breakouts / Breakdowns
buyBreakout = useBO and ta.crossover(close, donHi[1]) and (volSpike or close > donHi[1])
sellBreakdown = useBD and ta.crossunder(close, donLo[1]) and (volSpike or close < donLo[1])
// Pivots → Double Bottom / Top
pL = ta.pivotlow(low, pvLeft, pvRight)
pH = ta.pivothigh(high, pvLeft, pvRight)
lastLow = ta.valuewhen(pL, low[pvRight], 0)
prevLow = ta.valuewhen(pL, low[pvRight], 1)
lastHigh = ta.valuewhen(pH, high[pvRight], 0)
prevHigh = ta.valuewhen(pH, high[pvRight], 1)
priceMatch(a, b, tol) =>
not na(a) and not na(b) and math.abs(a - b) / b <= tol
doubleBottom = useDB and priceMatch(lastLow, prevLow, matchTolPct) and nz(lastLow) > nz(prevLow)
doubleTop = useDT and priceMatch(lastHigh, prevHigh, matchTolPct) and nz(lastHigh) < nz(prevHigh)
// Crosses (trend)
goldenCross = useGolden and ta.crossover(ema50, ema200)
deathCross = useDeath and ta.crossunder(ema50, ema200)
// Gap fill reversals (daily)
isDaily = timeframe.isdaily
gapUp = isDaily and open > close[1] * (1 + minGapPct)
gapDown = isDaily and open < close[1] * (1 - minGapPct)
gapUpFillRev = useGapUpRev and gapUp and high >= close[1] and close < close[1]
gapDnFillRev = useGapDnRev and gapDown and low <= close[1] and close > close[1]
// Candles at structure
hammerAtSupport = useHammer and isHammer() and nearSupport
starAtResist = useStar and isShootingStar() and nearResist
// Aggregate booleans (no arrays, no loops)
anyBuy = hammerAtSupport or buyBreakout or doubleBottom or goldenCross or gapDnFillRev
anySell = starAtResist or sellBreakdown or doubleTop or deathCross or gapUpFillRev
//===================== Plots =====================
plotshape(hammerAtSupport, title="BUY: Hammer @ Support", style=shape.triangleup, color=color.new(color.lime, 0), size=size.tiny, location=location.belowbar, text="Hammers")
plotshape(buyBreakout, title="BUY: Breakout", style=shape.triangleup, color=color.new(color.green, 0), size=size.tiny, location=location.belowbar, text="BO")
plotshape(doubleBottom, title="BUY: Double Bottom", style=shape.triangleup, color=color.new(color.teal, 0), size=size.tiny, location=location.belowbar, text="DB")
plotshape(goldenCross, title="BUY: Golden Cross", style=shape.triangleup, color=color.new(color.aqua, 0), size=size.tiny, location=location.belowbar, text="GC")
plotshape(gapDnFillRev, title="BUY: Gap-Down Reversal",style=shape.triangleup, color=color.new(color.fuchsia,0), size=size.tiny, location=location.belowbar, text="GapDnREV")
plotshape(starAtResist, title="SELL: Star @ Resistance",style=shape.triangledown, color=color.new(color.red, 0), size=size.tiny, location=location.abovebar, text="Starr")
plotshape(sellBreakdown, title="SELL: Breakdown", style=shape.triangledown, color=color.new(color.maroon, 0), size=size.tiny, location=location.abovebar, text="BD")
plotshape(doubleTop, title="SELL: Double Top", style=shape.triangledown, color=color.new(color.orange, 0), size=size.tiny, location=location.abovebar, text="DT")
plotshape(deathCross, title="SELL: Death Cross", style=shape.triangledown, color=color.new(color.purple, 0), size=size.tiny, location=location.abovebar, text="DC")
plotshape(gapUpFillRev, title="SELL: Gap-Up Reversal", style=shape.triangledown, color=color.new(color.yellow, 0), size=size.tiny, location=location.abovebar, text="GapUpREV")
plotshape(aggregateAlerts and anyBuy, title="BUY (Aggregate)", style=shape.labelup, color=color.new(color.green, 70), textcolor=color.black, text="BUY", location=location.belowbar, size=size.tiny)
plotshape(aggregateAlerts and anySell, title="SELL (Aggregate)", style=shape.labeldown, color=color.new(color.red, 70), textcolor=color.black, text="SELL", location=location.abovebar, size=size.tiny)
//===================== Alerts =====================
alertcondition(hammerAtSupport, "BUY: Hammer @ Support", "Hammer/Bottoming Tail at support on {{ticker}} {{interval}}")
alertcondition(buyBreakout, "BUY: Breakout", "Breakout above Donchian High on {{ticker}} {{interval}}")
alertcondition(doubleBottom, "BUY: Double Bottom", "Double Bottom/Higher Low on {{ticker}} {{interval}}")
alertcondition(goldenCross, "BUY: Golden Cross", "EMA50 crosses above EMA200 on {{ticker}} {{interval}}")
alertcondition(gapDnFillRev, "BUY: Gap-Down Reversal","Gap-down filled & reversed on {{ticker}} {{interval}}")
alertcondition(starAtResist, "SELL: Star @ Resistance","Shooting Star/Topping Tail at resistance on {{ticker}} {{interval}}")
alertcondition(sellBreakdown, "SELL: Breakdown", "Breakdown below Donchian Low on {{ticker}} {{interval}}")
alertcondition(doubleTop, "SELL: Double Top", "Double Top/Lower High on {{ticker}} {{interval}}")
alertcondition(deathCross, "SELL: Death Cross", "EMA50 crosses below EMA200 on {{ticker}} {{interval}}")
alertcondition(gapUpFillRev, "SELL: Gap-Up Reversal", "Gap-up filled & reversed on {{ticker}} {{interval}}")
// Aggregate
alertcondition(aggregateAlerts and anyBuy, "BUY: Aggregate", "Structural BUY signal on {{ticker}} {{interval}}")
alertcondition(aggregateAlerts and anySell, "SELL: Aggregate", "Structural SELL signal on {{ticker}} {{interval}}")
نص برمجي محمي
تم نشر هذا النص البرمجي كمصدر مغلق. ومع ذلك، يمكنك استخدامه بحرية ودون أي قيود - تعرف على المزيد هنا.
إخلاء المسؤولية
لا يُقصد بالمعلومات والمنشورات أن تكون، أو تشكل، أي نصيحة مالية أو استثمارية أو تجارية أو أنواع أخرى من النصائح أو التوصيات المقدمة أو المعتمدة من TradingView. اقرأ المزيد في شروط الاستخدام.
نص برمجي محمي
تم نشر هذا النص البرمجي كمصدر مغلق. ومع ذلك، يمكنك استخدامه بحرية ودون أي قيود - تعرف على المزيد هنا.
إخلاء المسؤولية
لا يُقصد بالمعلومات والمنشورات أن تكون، أو تشكل، أي نصيحة مالية أو استثمارية أو تجارية أو أنواع أخرى من النصائح أو التوصيات المقدمة أو المعتمدة من TradingView. اقرأ المزيد في شروط الاستخدام.