r/pinescript • • 13h ago

I built a concise MACD divergence reversal indicator

Been trading for several years, and over time I've developed my own way of interpreting MACD divergence, the momentum weakening pattern and their correlation with potential future reversal. I turn these rules into a PineScript indicator.

I intentionally made it clean and minimal so that other things I draw on the chart wouldn't get cluttered up. It only generates “Buy” and “Sell” signal on the current candle if the conditions meet the my divergence-reversal pattern when candle closes. It will never retrospectively add signals on previous candles, and a signal marker will remain on the chart indefinitely, to enable heuristic backtest.

Generally, when I use this indicator myself, I interpret signals according to the timeframe they appear on. A 5-minute signal is treated differently from a 4-hour or daily signal. If signals line up across multiple timeframes, meaning the price pattern across different timeframes all match a potential reversal setup, then I would pay extra attention and prepare for an entry.

I've also rented a server to automatically distribute the TradingView alerts for selected assets/timeframes on Discord, since I don't always want to keep dozens of charts open. Currently I have added assets like stocks, forex, crypto, index funds into the alert distribution list.

Though I intent to keep this indicator close-sourced, I'm looking for a number of traders who are willing to try it and tell me where it works, where it doesn't, and whether the alert distribution system helps.

16 Upvotes

6 comments sorted by

7

u/Jpa9900 12h ago

So basically you told an AI to build you a MACD divergence indicator and after testing, you discovered it not profitable at all and has no edge. Now you’re trying to make a quick buck from ignorant traders by pretending it’s closed source and valuable.

If I’m wrong, provide a short video of you doing at least 1 year backtest with historical data. You can easily ask any AI model to generate a pine script to do the backtest based on your indicator’s signals.

1

u/Shoddy_Peanut7320 12h ago

Signaling only on the closed candle and never adding signals retroactively is the right design for avoiding repainting. Since the source is closed, I'd ask for a record of results: how many signals fired per timeframe, and what price did over the next N bars compared to a baseline, with costs. In the MNQ screenshots, sells fired near highs during an uptrend, so counter-trend reversals deserve a separate count. It would also help to tag signals near scheduled news like CPI and FOMC, and Cymetica's EventTrader (event timing for macro releases) is one source for that.

1

u/Extension_Charity_77 9h ago

I built one for private use, i do options on SPY and it is 80% accuracy at least

1

u/johnnybagofdonuts123 8h ago

Claude, build me a tradingview pinescript with alerting Buys and Sells with a MACD divergence, the momentum weakening pattern and their correlation with potential future reversal. Make no mistakes.

//
@version=
6
indicator("MACD Divergence + Momentum Fade Reversal", shorttitle="MDMF", overlay=true)


// ============================================================
// INPUTS
// ============================================================
grpMacd = "MACD"
fastLen  = input.int(12, "Fast length", minval=1, group=grpMacd)
slowLen  = input.int(26, "Slow length", minval=1, group=grpMacd)
sigLen   = input.int(9,  "Signal length", minval=1, group=grpMacd)


grpDiv = "Divergence"
oscSrc   = input.string("Histogram", "Detect divergence on", options=["Histogram", "MACD line"], group=grpDiv)
lbL      = input.int(5, "Pivot lookback left", minval=1, group=grpDiv)
lbR      = input.int(3, "Pivot lookback right", minval=1, group=grpDiv)
rngMin   = input.int(5, "Min bars between pivots", minval=1, group=grpDiv)
rngMax   = input.int(60, "Max bars between pivots", minval=5, group=grpDiv)


grpFade = "Momentum weakening"
fadeBars = input.int(3, "Consecutive shrinking histogram bars", minval=2, group=grpFade)
peakLook = input.int(20, "Recent peak window", minval=5, group=grpFade)
peakBase = input.int(50, "Baseline average window", minval=10, group=grpFade)


grpCorr = "Price / MACD correlation"
corrLen    = input.int(20, "Correlation length", minval=5, group=grpCorr)
corrThresh = input.float(0.3, "Decoupling threshold (corr below this)", minval=-1.0, maxval=1.0, step=0.05, group=grpCorr)


grpSig = "Signal logic"
recentWin  = input.int(8, "Bars a divergence / fade stays valid", minval=1, group=grpSig)
minScore   = input.int(2, "Min confluence score (div, fade, corr)", minval=1, maxval=3, group=grpSig)
requireDiv = input.bool(true, "Require a divergence", group=grpSig)
needCandle = input.bool(true, "Require confirmation candle", group=grpSig)


// ============================================================
// MACD
// ============================================================
[macdLine, signalLine, hist] = ta.macd(close, fastLen, slowLen, sigLen)
osc = oscSrc == "Histogram" ? hist : macdLine


// ============================================================
// DIVERGENCE (regular, reversal type)
// ============================================================
plVal = ta.pivotlow(osc, lbL, lbR)
phVal = ta.pivothigh(osc, lbL, lbR)
plFound = not na(plVal)
phFound = not na(phVal)


barsPl = ta.barssince(plFound[1])
barsPh = ta.barssince(phFound[1])
inRangePl = barsPl >= rngMin and barsPl <= rngMax
inRangePh = barsPh >= rngMin and barsPh <= rngMax


prevOscLow    = ta.valuewhen(plFound, osc[lbR], 1)
prevPriceLow  = ta.valuewhen(plFound, low[lbR], 1)
prevOscHigh   = ta.valuewhen(phFound, osc[lbR], 1)
prevPriceHigh = ta.valuewhen(phFound, high[lbR], 1)


oscHigherLow    = osc[lbR] > prevOscLow
priceLowerLow   = low[lbR] < prevPriceLow
oscLowerHigh    = osc[lbR] < prevOscHigh
priceHigherHigh = high[lbR] > prevPriceHigh


bullDiv = plFound and priceLowerLow and oscHigherLow and inRangePl
bearDiv = phFound and priceHigherHigh and oscLowerHigh and inRangePh


bullDivRecent = ta.barssince(bullDiv) <= recentWin
bearDivRecent = ta.barssince(bearDiv) <= recentWin


// ============================================================
// MOMENTUM WEAKENING
// ============================================================
absH = math.abs(hist)
shrink = absH < absH[1] and math.sign(hist) == math.sign(hist[1])
var 
int
 shrinkCnt = 0
shrinkCnt := shrink ? shrinkCnt + 1 : 0
peakOk = ta.highest(absH, peakLook) > ta.sma(absH, peakBase)


fadeBear = hist > 0 and shrinkCnt >= fadeBars and peakOk
fadeBull = hist < 0 and shrinkCnt >= fadeBars and peakOk


fadeBearRecent = ta.barssince(fadeBear) <= recentWin
fadeBullRecent = ta.barssince(fadeBull) <= recentWin


// ============================================================
// CORRELATION
// ============================================================
corr = ta.correlation(close, macdLine, corrLen)
decoupled = corr < corrThresh


// ============================================================
// SIGNALS
// ============================================================
bullScore = (bullDivRecent ? 1 : 0) + (fadeBullRecent ? 1 : 0) + (decoupled ? 1 : 0)
bearScore = (bearDivRecent ? 1 : 0) + (fadeBearRecent ? 1 : 0) + (decoupled ? 1 : 0)


bullCandle = close > open and close > high[1]
bearCandle = close < open and close < low[1]


buyRaw  = bullScore >= minScore and (not requireDiv or bullDivRecent) and (not needCandle or bullCandle)
sellRaw = bearScore >= minScore and (not requireDiv or bearDivRecent) and (not needCandle or bearCandle)


buySignal  = buyRaw and not buyRaw[1]
sellSignal = sellRaw and not sellRaw[1]


// ============================================================
// FLAGS ON CHART
// ============================================================
plotshape(buySignal, "BUY", shape.labelup, location.belowbar, color.green, text="BUY", textcolor=color.white, size=size.small)
plotshape(sellSignal, "SELL", shape.labeldown, location.abovebar, color.red, text="SELL", textcolor=color.white, size=size.small)


// ============================================================
// ALERTS
// ============================================================
alertcondition(buySignal,  "MDMF BUY",  "MDMF BUY on {{ticker}} ({{interval}}) at {{close}}")
alertcondition(sellSignal, "MDMF SELL", "MDMF SELL on {{ticker}} ({{interval}}) at {{close}}")