machidden-algonexta-2.pine · 190 lines · 8.2 KB
Not yet verified on the native platform — test it before relying on it.
The original uploaded source.
// ============================================================================
// © algonexta
// This script is for education and research; it does not guarantee results.
// Verify this source in TradingView before use.
// ============================================================================
//@version=6
indicator("MacIce Hidden EMA Indicator", "MacIce", overlay = true, max_labels_count = 500)
// MacIce for TradingView
// 1) EMA60 / EMA240 cross sets the active direction.
// 2) In downturn, every confirmed hidden bearish divergence gets a sell arrow.
// 3) In upturn, every confirmed hidden bullish divergence gets a buy arrow.
// 4) Indicator only. No strategy orders, no trading functions.
//
// Signal timing: a pivot is only known after `pivotRight` more bars have closed.
// The big arrow is drawn on the confirmation bar, which is the bar where the
// alert fires, so the chart history matches what a live user would have seen.
// A small dot marks the pivot bar itself, so the turning point stays visible.
string GROUP_EMA = "EMA Cross"
string GROUP_HIDDEN = "Hidden Divergence"
string GROUP_DISPLAY = "Display"
float source = input.source(close, "Source", group = GROUP_EMA)
int fastEmaPeriod = input.int(60, "Fast EMA", minval = 2, group = GROUP_EMA)
int slowEmaPeriod = input.int(240, "Slow EMA", minval = 5, group = GROUP_EMA)
bool requireEmaSide = input.bool(false, "Require price on EMA side", group = GROUP_EMA)
int pivotLeft = input.int(1, "Pivot left bars", minval = 1, group = GROUP_HIDDEN)
int pivotRight = input.int(1, "Pivot right bars", minval = 1, group = GROUP_HIDDEN)
int macdFast = input.int(12, "MACD fast", minval = 1, group = GROUP_HIDDEN)
int macdSlow = input.int(26, "MACD slow", minval = 2, group = GROUP_HIDDEN)
int macdSignal = input.int(9, "MACD signal", minval = 1, group = GROUP_HIDDEN)
bool resetPivotsOnCross = input.bool(false, "Reset pivot memory on each cross", group = GROUP_HIDDEN)
bool moreSignals = input.bool(true, "More signals / trend pivots", group = GROUP_HIDDEN)
bool showEmaLines = input.bool(false, "Show EMA lines", group = GROUP_DISPLAY)
bool showCrossLabels = input.bool(true, "Show cross labels", group = GROUP_DISPLAY)
bool showPivotMarkers = input.bool(true, "Show pivot dot (where the turn happened)", group = GROUP_DISPLAY)
int signalsToKeep = input.int(20, "Previous signals to show", minval = 20, maxval = 90, group = GROUP_DISPLAY)
int crossLabelsToKeep = input.int(20, "Previous cross labels to show", minval = 1, maxval = 90, group = GROUP_DISPLAY)
float emaFast = ta.ema(source, fastEmaPeriod)
float emaSlow = ta.ema(source, slowEmaPeriod)
float atrValue = ta.atr(14)
bool bullCross = ta.crossover(emaFast, emaSlow)
bool bearCross = ta.crossunder(emaFast, emaSlow)
var int trendDirection = 0
var int trendStartBar = na
if bullCross
trendDirection := 1
trendStartBar := bar_index
else if bearCross
trendDirection := -1
trendStartBar := bar_index
if trendDirection == 0
trendDirection := emaFast > emaSlow ? 1 : emaFast < emaSlow ? -1 : 0
[macdLine, signalLine, histLine] = ta.macd(source, macdFast, macdSlow, macdSignal)
float pivotHigh = ta.pivothigh(high, pivotLeft, pivotRight)
float pivotLow = ta.pivotlow(low, pivotLeft, pivotRight)
bool hasPivotHigh = not na(pivotHigh)
bool hasPivotLow = not na(pivotLow)
int pivotBar = bar_index - pivotRight
var float previousHighPrice = na
var float previousHighMacd = na
var int previousHighBar = na
var float previousLowPrice = na
var float previousLowMacd = na
var int previousLowBar = na
if resetPivotsOnCross and (bullCross or bearCross)
previousHighPrice := na
previousHighMacd := na
previousHighBar := na
previousLowPrice := na
previousLowMacd := na
previousLowBar := na
bool pivotAfterTrendStart = na(trendStartBar) ? true : pivotBar > trendStartBar
bool sellEmaOk = not requireEmaSide or (close[pivotRight] < emaFast[pivotRight] and close[pivotRight] < emaSlow[pivotRight])
bool buyEmaOk = not requireEmaSide or (close[pivotRight] > emaFast[pivotRight] and close[pivotRight] > emaSlow[pivotRight])
bool hiddenBear = false
bool hiddenBull = false
if hasPivotHigh
float highMacd = macdLine[pivotRight]
bool strictBear = not na(previousHighPrice) and pivotHigh < previousHighPrice and highMacd > previousHighMacd
bool softBear = moreSignals and not na(previousHighPrice) and (pivotHigh < previousHighPrice or highMacd > previousHighMacd) and histLine[pivotRight] <= histLine[pivotRight + 1]
bool trendPivotBear = moreSignals and not na(previousHighPrice)
hiddenBear := trendDirection == -1 and pivotAfterTrendStart and sellEmaOk and (strictBear or softBear or trendPivotBear)
previousHighPrice := pivotHigh
previousHighMacd := highMacd
previousHighBar := pivotBar
if hasPivotLow
float lowMacd = macdLine[pivotRight]
bool strictBull = not na(previousLowPrice) and pivotLow > previousLowPrice and lowMacd < previousLowMacd
bool softBull = moreSignals and not na(previousLowPrice) and (pivotLow > previousLowPrice or lowMacd < previousLowMacd) and histLine[pivotRight] >= histLine[pivotRight + 1]
bool trendPivotBull = moreSignals and not na(previousLowPrice)
hiddenBull := trendDirection == 1 and pivotAfterTrendStart and buyEmaOk and (strictBull or softBull or trendPivotBull)
previousLowPrice := pivotLow
previousLowMacd := lowMacd
previousLowBar := pivotBar
plot(showEmaLines ? emaFast : na, "EMA 60", color = color.red, linewidth = 2)
plot(showEmaLines ? emaSlow : na, "EMA 240", color = color.blue, linewidth = 2)
var label[] signalLabels = array.new_label()
var label[] pivotLabels = array.new_label()
var label[] crossLabels = array.new_label()
// Big arrow on the confirmation bar (the current bar), where the alert fires.
addSignalLabel(bool isBuy) =>
float arrowPrice = isBuy ? low - atrValue * 0.25 : high + atrValue * 0.25
label arrowLabel = label.new(
bar_index,
arrowPrice,
isBuy ? "▲" : "▼",
xloc = xloc.bar_index,
yloc = yloc.price,
style = label.style_none,
color = color.new(color.white, 100),
textcolor = isBuy ? color.lime : color.red,
size = size.huge,
tooltip = "Signal confirmed here (" + str.tostring(pivotRight) + " bar(s) after the pivot)")
array.push(signalLabels, arrowLabel)
while array.size(signalLabels) > signalsToKeep
label.delete(array.shift(signalLabels))
// Small dot on the pivot bar itself, so the turning point stays visible.
addPivotMarker(bool isBuy) =>
float dotPrice = isBuy ? low[pivotRight] - atrValue[pivotRight] * 0.25 : high[pivotRight] + atrValue[pivotRight] * 0.25
label dotLabel = label.new(
pivotBar,
dotPrice,
"●",
xloc = xloc.bar_index,
yloc = yloc.price,
style = label.style_none,
color = color.new(color.white, 100),
textcolor = isBuy ? color.new(color.lime, 35) : color.new(color.red, 35),
size = size.tiny,
tooltip = "Pivot bar (known only " + str.tostring(pivotRight) + " bar(s) later)")
array.push(pivotLabels, dotLabel)
while array.size(pivotLabels) > signalsToKeep
label.delete(array.shift(pivotLabels))
if hiddenBear
addSignalLabel(false)
if showPivotMarkers
addPivotMarker(false)
if hiddenBull
addSignalLabel(true)
if showPivotMarkers
addPivotMarker(true)
addCrossLabel(bool isBullCross) =>
float crossPrice = (emaFast + emaSlow) * 0.5
float labelPrice = isBullCross ? crossPrice - atrValue * 0.35 : crossPrice + atrValue * 0.35
label crossLabel = label.new(
bar_index,
labelPrice,
"Cross",
xloc = xloc.bar_index,
yloc = yloc.price,
style = label.style_none,
color = color.new(color.blue, 100),
textcolor = color.rgb(41, 98, 255),
size = size.normal)
array.push(crossLabels, crossLabel)
while array.size(crossLabels) > crossLabelsToKeep
label.delete(array.shift(crossLabels))
if showCrossLabels and bullCross
addCrossLabel(true)
if showCrossLabels and bearCross
addCrossLabel(false)
alertcondition(hiddenBear, "MacIce Sell Hidden", "MacIce sell hidden divergence on {{ticker}} {{interval}}")
alertcondition(hiddenBull, "MacIce Buy Hidden", "MacIce buy hidden divergence on {{ticker}} {{interval}}")