The Confirmed Contrarian - a Benchmark Reversion System |
Ok guys, im excited about this one. Honestly this might just be the best indicator I've created to date (might not be saying a whole lot but ya
The Confirmed Contrarian is a simple, visual trade execution framework designed to help you:
- Buy fundamentally strong stocks when they’re stretched to the downside
- Fade overheated runners when they’ve statistically overextended
- Stay out of chop when no real edge is present
It uses Z-score-based mean reversion logic, paired with RSI, relative volume, and your choice of benchmark ETF (SPY, QQQ, etc.).

The system calculates:
- Cumulative Relative Strength: Measures your stock vs an ETF (like QQQ)
- Z-Score: Tracks how far the stock has drifted from the normal relative relationship
- Rolling Bands: Based on standard deviation (like Bollinger logic but for relative performance)
- RSI: Confirms overbought/oversold context
- Relative Volume: Confirms that the market is actually stepping in
When these conditions align, you get:
- Buy arrows on strong reversion setups (Z < -1.5, RSI < 40, high relative volume)
- Sell arrows when the stock is statistically extended (Z > +1.5, RSI > 60, high volume)
- Contextual labels to give you the Z-score, RSI, volume strength, and entry confidence at a glance

Label | Meaning |
---|---|
RelStrength Z | Tells you how far from "normal" the move is |
RSI | Classic overbought/oversold zone reference |
Volume Confirms | Confirms if action is backed by buyers/sellers |
Buy/Sell Setup Confirmed | Only lights up when all signals align |
Z Sentiment Zone | Interprets Z-score into plain language like: |
“Fade or Take Profits”, “Watch for Bottoming”, “Get Ready for Bounce” | |
Accumulation / Distribution | Shows if the market is likely rotating out or in at extremes |

- Already do research and believe in the stock
- Just want a clean, non-chasey entry system
- Prefer volume-backed mean reversion over prediction
- Want something visual, simple, and execution-focused
Check this out:

The Case Study: The highlighted bubble on the chart represents a local bottom for ENPH. If you look at the slope line on volume it shows that volume was slowing down after the sell of. Continue down to the indicator and you will see that the price was extremely down relative to the benchmark, which I chose as SMH since it is a solar ETF. You currently, as of 5/4/2025 have a similar setup on ENPH right now so keep your eyes on it and see how it responds.
Code:
declare lower;
# === Inputs ===
input marketETF = {default "SPY", "QQQ", "DIA", "IWM", "TAN", "XLK", "XLF", "SMH"};
input lookback = 20;
input thresholdMult = 1.5;
input rsiLength = 14;
input rsiOversold = 40;
input rsiOverbought = 60;
input volLength = 20;
input relVolHigh = 1.5;
input relVolLow = 0.8;
input showLabels = yes;
input showArrows = yes;
input showThresholds = yes;
input useVolumeFilter = no;
input volumeMultiplier = 1.2;
input useTrendFilter = no;
input trendLength = 21;
# === Fetch ETF Close ===
def etfClose =
if marketETF == marketETF."SPY" then close("SPY")
else if marketETF == marketETF."QQQ" then close("QQQ")
else if marketETF == marketETF."DIA" then close("DIA")
else if marketETF == marketETF."IWM" then close("IWM")
else if marketETF == marketETF."TAN" then close("TAN")
else if marketETF == marketETF."XLK" then close("XLK")
else if marketETF == marketETF."XLF" then close("XLF")
else if marketETF == marketETF."SMH" then close("SMH")
else Double.NaN;
def safeETF = if !IsNaN(etfClose) and etfClose != 0 then etfClose else close;
# === Relative Return Logic ===
def stockReturn = close / close[1] - 1;
def etfReturn = safeETF / safeETF[1] - 1;
def relReturn = stockReturn - etfReturn;
def cumStrength = Sum(relReturn, lookback);
plot CumRelStrength = cumStrength;
CumRelStrength.AssignValueColor(if cumStrength > 0 then Color.GREEN else if cumStrength < 0 then Color.RED else Color.GRAY);
CumRelStrength.SetLineWeight(2);
# === Rolling Bands (Standard Deviation-Based) ===
def stdev = StDev(cumStrength, lookback);
plot UpperThresh = if showThresholds then thresholdMult * stdev else Double.NaN;
plot LowerThresh = if showThresholds then -thresholdMult * stdev else Double.NaN;
UpperThresh.SetDefaultColor(Color.LIGHT_GREEN);
LowerThresh.SetDefaultColor(Color.PINK);
UpperThresh.SetStyle(Curve.LONG_DASH);
LowerThresh.SetStyle(Curve.LONG_DASH);
plot ZeroLine = 0;
ZeroLine.SetDefaultColor(Color.LIGHT_GRAY);
# === Z-Score ===
def mean = Average(cumStrength, lookback);
def zScore = if stdev != 0 then (cumStrength - mean) / stdev else 0;
# === RSI and Relative Volume ===
def rsi = RSI(length = rsiLength);
def avgVol = Average(volume, volLength);
def relVol = if avgVol != 0 then volume / avgVol else 0;
# === Optional Filters ===
def volFilter = if useVolumeFilter then volume > avgVol * volumeMultiplier else 1;
def trend = ExpAverage(close, trendLength);
def slope = trend - trend[1];
def trendFilter = if useTrendFilter then slope > 0 else 1;
def showSignal = volFilter and trendFilter;
# === Reversion Buy/Sell Logic ===
def buySignal = zScore < -1.5 and rsi < rsiOversold and relVol > relVolHigh;
def sellSignal = zScore > 1.5 and rsi > rsiOverbought and relVol > relVolHigh;
# === Arrows ===
plot UpArrow = if showArrows and showSignal and buySignal then cumStrength else Double.NaN;
UpArrow.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
UpArrow.SetDefaultColor(Color.GREEN);
UpArrow.SetLineWeight(3);
plot DownArrow = if showArrows and showSignal and sellSignal then cumStrength else Double.NaN;
DownArrow.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
DownArrow.SetDefaultColor(Color.RED);
DownArrow.SetLineWeight(3);
# === Labels ===
AddLabel(showLabels,
"RelStrength Z: " + Round(zScore, 2),
if zScore < -1.5 then Color.GREEN else if zScore > 1.5 then Color.RED else Color.GRAY
);
AddLabel(showLabels,
"RSI: " + Round(rsi, 1),
if rsi < rsiOversold then Color.GREEN else if rsi > rsiOverbought then Color.RED else Color.GRAY
);
AddLabel(showLabels,
if relVol > relVolHigh then "Volume Confirms"
else if relVol < relVolLow then "Volume Weak"
else "Neutral Volume",
if relVol > relVolHigh then Color.GREEN else if relVol < relVolLow then Color.ORANGE else Color.GRAY
);
AddLabel(showLabels,
if buySignal then "Buy Setup Confirmed"
else if sellSignal then "Sell Setup Confirmed"
else "No Setup",
if buySignal then Color.CYAN else if sellSignal then Color.PINK else Color.DARK_GRAY
);
AddLabel(showLabels,
if zScore > 2 then "Fade or Take Profits"
else if zScore > 1.5 then "Watch for Buyer Exhaustion"
else if zScore > 0.5 then "Trail Stop"
else if zScore > -0.5 then "Neutral"
else if zScore > -1.5 then "Watch for Bottoming"
else if zScore > -2 then "Watch for Seller Exhaustion"
else "Get Ready for Bounce",
if zScore > 2 then Color.RED
else if zScore > 1.5 then Color.ORANGE
else if zScore > 0.5 then Color.YELLOW
else if zScore > -0.5 then Color.GRAY
else if zScore > -1.5 then Color.LIGHT_GREEN
else if zScore > -2 then Color.GREEN
else Color.DARK_GREEN
);
AddLabel(showLabels and (zScore > 1.5 or zScore < -1.5),
if zScore > 1.5 then "Distribution"
else "Accumulation",
if zScore > 1.5 then Color.RED else Color.GREEN
);
Last edited by a moderator: