Uptrick Liquid Reversal Bands for ThinkorSwim was converted from this original source.
https://www.tradingview.com/script/NkOJyPWb-Uptrick-Liquid-Reversal-Bands/
Liquid Reversal Bands is an overlay indicator designed to help traders identify dynamic support and resistance zones, detect mean-reversion opportunities, and read price position within a volatility-aware envelope. Rather than using fixed standard deviation bands around a single moving average, this system builds its band width from multiple volatility components simultaneously, creating a more adaptive and stable envelope that responds to changing market conditions without overreacting to short-term noise. The candle coloring, fair value line, and band fills all carry live visual information, making it possible to assess market state and recent signal context at a glance without needing additional tools on the chart.
Lower indicator:
https://www.tradingview.com/script/NkOJyPWb-Uptrick-Liquid-Reversal-Bands/
Liquid Reversal Bands is an overlay indicator designed to help traders identify dynamic support and resistance zones, detect mean-reversion opportunities, and read price position within a volatility-aware envelope. Rather than using fixed standard deviation bands around a single moving average, this system builds its band width from multiple volatility components simultaneously, creating a more adaptive and stable envelope that responds to changing market conditions without overreacting to short-term noise. The candle coloring, fair value line, and band fills all carry live visual information, making it possible to assess market state and recent signal context at a glance without needing additional tools on the chart.
Code:
#// Uptrick_Liquid_Reversal_Bands
#// Original concept from https://www.tradingview.com/script/NkOJyPWb-Uptrick-Liquid-Reversal-Bands/
#// Converted and modified by Chewie 7/11/2026
declare upper;
#=== Inputs ===
input colorbar = no;
input enableSignals = yes;
input showOuterBands = yes;
input src = close;
input fairLen = 50;
input zLen = 100;
input smoothLen = 18;
input upperMult0 = 2.0;
input upperMult = 2.4;
input lowerMult = 2.4;
input outerUpperMult = 1.45;
input outerLowerMult = 1.45;
input cooldownBars = 0;
input candleMode = {default ReversalHeat, LatestSignal};
input lineSlopeLen = 5;
input lineSlopeSensitivity = 1.25;
#=== Fixed palette (matches original hex colors) ===
def bullR = 92; def bullG = 240; def bullB = 215;
def bearR = 179; def bearG = 42; def bearB = 195;
#=== ALMA (Arnaud Legoux Moving Average) for Fair Value ===
def almaOffset = 0.85;
def almaSigma = 6.0;
def m = almaOffset * (fairLen - 1);
def s = fairLen / almaSigma;
def wSum = fold wi = 0 to fairLen with ws = 0 do
ws + Exp(-1 * Power(wi - m, 2) / (2 * Power(s, 2)));
def wPriceSum = fold pi = 0 to fairLen with wps = 0 do
wps + GetValue(src, fairLen - 1 - pi) * Exp(-1 * Power(pi - m, 2) / (2 * Power(s, 2)));
def almaFair = wPriceSum / wSum;
#=== Liquid Fair Value ===
def emaFair = ExpAverage(src, fairLen);
def fairRaw = emaFair * 0.55 + almaFair * 0.45;
def fairSmoothLen = Max(1, Floor(smoothLen / 2.0));
def fair = ExpAverage(fairRaw, fairSmoothLen);
#=== Liquid Band Width ===
def dev = src - fair;
def devStdev = StandardDeviation(dev, zLen);
def atrValue = WildersAverage(TrueRange(high, close, low), 14);
def absDev = ExpAverage(AbsValue(dev), zLen);
def rangeEnergy = ExpAverage(high - low, smoothLen);
def baseWidth = devStdev * 0.60 + atrValue * 0.25 + absDev * 0.10 + rangeEnergy * 0.05;
def width = ExpAverage(baseWidth, smoothLen);
def upperBand1 = fair + width * upperMult;
def lowerBand1 = fair - width * lowerMult;
def outerUpperBand1 = fair + width * upperMult * outerUpperMult;
def outerLowerBand1 = fair - width * lowerMult * outerLowerMult;
def upperbanda = (upperband1 - fair) /2 + fair;
def lowerbanda = fair - (upperband1 - fair) /2;
#=== Fair Value Line Slope Coloring ===
def fairSlopeRaw = fair - fair[1];
def fairSlopeAvg = ExpAverage(AbsValue(fairSlopeRaw), lineSlopeLen);
def fairSlopeNorm = if fairSlopeAvg != 0 then fairSlopeRaw / fairSlopeAvg else 0;
def fairSlopeSmooth = ExpAverage(fairSlopeNorm, lineSlopeLen);
def lineRatioRaw = 0.5 + fairSlopeSmooth / (2 * lineSlopeSensitivity);
def lineRatio = Min(1, Max(0, lineRatioRaw));
def lineR = bearR + (bullR - bearR) * lineRatio;
def lineG = bearG + (bullG - bearG) * lineRatio;
def lineB = bearB + (bullB - bearB) * lineRatio;
#=== Band / Fair Value Plots ===
plot upperBand0 = fair + width * upperMult0;
plot lowerBand0 = fair - width * upperMult0;
plot UpperBand = upperBand1;
plot LowerBand = lowerBand1;
plot UpperBandi = upperBanda;
plot LowerBandi = lowerBanda;
plot FairValue = fair;
plot UM = (upperbandi-fair)/2 + fair;
plot LM = (upperbandi-fair)/2 + lowerbandi;
UM.SetDefaultColor(Color.GRAY);
LM.SetDefaultColor(Color.GRAY);
UpperBand0.SetDefaultColor(Color.red);
LowerBand0.SetDefaultColor(Color.green);
UpperBand.SetDefaultColor(Color.red);
LowerBand.SetDefaultColor(Color.green);
UpperBand.SetLineWeight(1);
LowerBand.SetLineWeight(1);
UpperBandi.SetDefaultColor(Color.GRAY);
LowerBandi.SetDefaultColor(Color.GRAY);
FairValue.AssignValueColor(CreateColor(lineR, lineG, lineB));
FairValue.SetLineWeight(4);
plot OuterUpperBand = if showOuterBands then outerUpperBand1 else Double.NaN;
plot OuterLowerBand = if showOuterBands then outerLowerBand1 else Double.NaN;
OuterUpperBand.SetDefaultColor(color.magenta); #CreateColor(bearR, bearG, bearB));
OuterLowerBand.SetDefaultColor(color.cyan); #CreateColor(bullR, bullG, bullB));
#=== Reversal Signals ===
def rawBuy = close[1] <= lowerBand1[1] and close > lowerBand1;
def rawSell = close[1] >= upperBand1[1] and close < upperBand1;
# self-referential cooldown counter (bars since last accepted signal)
def barsSinceSignal = CompoundValue(1,
if enableSignals and (rawBuy or rawSell) and (barsSinceSignal[1] >= cooldownBars)
then 0
else barsSinceSignal[1] + 1,
9999);
def barsOk = barsSinceSignal[1] >= cooldownBars;
def finalBuy = enableSignals and rawBuy and barsOk;
def finalSell = enableSignals and rawSell and barsOk;
def lastSignalState = CompoundValue(1,
if finalBuy then 1 else if finalSell then -1 else lastSignalState[1],
0);
#=== Candle Coloring ===
def bandRange = upperBand1 - lowerBand1;
def ratioRaw = if bandRange != 0 then (src - lowerBand1) / bandRange else 0.5;
def ratioClamped = Min(1, Max(0, if IsNaN(ratioRaw) then 0.5 else ratioRaw));
def heatR = bullR + (bearR - bullR) * ratioClamped;
def heatG = bullG + (bearG - bullG) * ratioClamped;
def heatB = bullB + (bearB - bullB) * ratioClamped;
def candleR = if candleMode == candleMode.LatestSignal
then (if lastSignalState == 1 then bullR else if lastSignalState == -1 then bearR else heatR)
else heatR;
def candleG = if candleMode == candleMode.LatestSignal
then (if lastSignalState == 1 then bullG else if lastSignalState == -1 then bearG else heatG)
else heatG;
def candleB = if candleMode == candleMode.LatestSignal
then (if lastSignalState == 1 then bullB else if lastSignalState == -1 then bearB else heatB)
else heatB;
AssignPriceColor(if colorbar then CreateColor(candleR, candleG, candleB) else color.current);
#=== Fills ===
AddCloud(UpperBand, UpperBandi, CreateColor(129, 20, 135), CreateColor(129, 20, 135));
AddCloud(LowerBandi, LowerBand, CreateColor(70, 180, 155), CreateColor(70, 180, 155));
AddCloud(OuterUpperBand, UpperBand, CreateColor(bearR, bearG, bearB), CreateColor(bearR, bearG, bearB));
AddCloud(LowerBand, OuterLowerBand, CreateColor(bullR, bullG, bullB), CreateColor(bullR, bullG, bullB));
AddCloud(UpperBand, UpperBand0, CreateColor(150, 40, 155), CreateColor(150, 40, 155));
AddCloud(LowerBand0, LowerBand, CreateColor(90, 200, 175), CreateColor(90, 200, 175));
#=== Buy / Sell Signal Arrows ===
plot BuySignal = if finalBuy then low - ATR(60) / 2 else Double.NaN;
BuySignal.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
BuySignal.SetDefaultColor(color.green); #CreateColor(bullR, bullG, bullB));
BuySignal.SetLineWeight(3);
plot SellSignal = if finalSell then high + ATR(60) / 2 else Double.NaN;
SellSignal.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
SellSignal.SetDefaultColor(color.red); #CreateColor(bearR, bearG, bearB));
SellSignal.SetLineWeight(3);
Lower indicator:
Code:
#// Uptrick_Liquid_Reversal_Oscillator
#// Based on Uptrick_Liquid_Reversal_Bands by Chewie 7/11/2026
#// Oscillator conversion by Chewie 7/28/2026
declare lower;
#=== Inputs ===
input enableSignals = yes;
input showOuterBands = yes;
input src = close;
input fairLen = 50;
input zLen = 100;
input smoothLen = 18;
input upperMult0 = 2.0;
input upperMult = 2.4;
input lowerMult = 2.4;
input outerUpperMult = 1.45;
input outerLowerMult = 1.45;
input cooldownBars = 0;
input lineSlopeLen = 5;
input lineSlopeSensitivity = 1.25;
#=== Fixed palette ===
def bullR = 92; def bullG = 240; def bullB = 215;
def bearR = 179; def bearG = 42; def bearB = 195;
#=== ALMA for Fair Value ===
def almaOffset = 0.85;
def almaSigma = 6.0;
def m = almaOffset * (fairLen - 1);
def s = fairLen / almaSigma;
def wSum = fold wi = 0 to fairLen with ws = 0 do
ws + Exp(-1 * Power(wi - m, 2) / (2 * Power(s, 2)));
def wPriceSum = fold pi = 0 to fairLen with wps = 0 do
wps + GetValue(src, fairLen - 1 - pi) * Exp(-1 * Power(pi - m, 2) / (2 * Power(s, 2)));
def almaFair = wPriceSum / wSum;
#=== Liquid Fair Value ===
def emaFair = ExpAverage(src, fairLen);
def fairRaw = emaFair * 0.55 + almaFair * 0.45;
def fairSmoothLen = Max(1, Floor(smoothLen / 2.0));
def fair = ExpAverage(fairRaw, fairSmoothLen);
#=== Liquid Band Width ===
def dev = src - fair;
def devStdev = StandardDeviation(dev, zLen);
def atrValue = WildersAverage(TrueRange(high, close, low), 14);
def absDev = ExpAverage(AbsValue(dev), zLen);
def rangeEnergy = ExpAverage(high - low, smoothLen);
def baseWidth = devStdev * 0.60 + atrValue * 0.25 + absDev * 0.10 + rangeEnergy * 0.05;
def width = ExpAverage(baseWidth, smoothLen);
#=== Oscillator: ===
def osc = if width != 0 then (src - fair) / width else 0;
#=== Horizontal Band Lines ===
plot ZeroLine = 0;
ZeroLine.SetLineWeight(2);
# Inner half-bands (upperbanda/lowerbanda midpoints)
plot UpperBandI_H = upperMult / 2;
plot LowerBandI_H = -(upperMult / 2);
UpperBandI_H.SetDefaultColor(Color.light_gray);
LowerBandI_H.SetDefaultColor(Color.light_gray);
# Mid inner
plot UM_H = upperMult / 4;
plot LM_H = -(upperMult / 4);
UM_H.SetDefaultColor(Color.GRAY);
LM_H.SetDefaultColor(Color.GRAY);
# Band0 lines (upperMult0)
plot UpperBand0_H = upperMult0;
plot LowerBand0_H = -upperMult0;
UpperBand0_H.SetDefaultColor(Color.red);
LowerBand0_H.SetDefaultColor(Color.green);
#UpperBand0_H.SetStyle(Curve.SHORT_DASH);
#LowerBand0_H.SetStyle(Curve.SHORT_DASH);
# Main bands (upperMult / lowerMult)
plot UpperBand_H = upperMult;
plot LowerBand_H = -lowerMult;
UpperBand_H.SetDefaultColor(Color.RED);
LowerBand_H.SetDefaultColor(Color.GREEN);
UpperBand_H.SetLineWeight(1);
LowerBand_H.SetLineWeight(1);
# Outer bands
plot OuterUpper_H = if showOuterBands then upperMult * outerUpperMult else Double.NaN;
plot OuterLower_H = if showOuterBands then -lowerMult * outerLowerMult else Double.NaN;
OuterUpper_H.SetDefaultColor(Color.MAGENTA);
OuterLower_H.SetDefaultColor(Color.CYAN);
#=== Fair Value Line Slope Coloring for Oscillator line ===
def fairSlopeRaw = fair - fair[1];
def fairSlopeAvg = ExpAverage(AbsValue(fairSlopeRaw), lineSlopeLen);
def fairSlopeNorm = if fairSlopeAvg != 0 then fairSlopeRaw / fairSlopeAvg else 0;
def fairSlopeSmooth = ExpAverage(fairSlopeNorm, lineSlopeLen);
def lineRatioRaw = 0.5 + fairSlopeSmooth / (2 * lineSlopeSensitivity);
def lineRatio = Min(1, Max(0, lineRatioRaw));
def lineR = bearR + (bullR - bearR) * lineRatio;
def lineG = bearG + (bullG - bearG) * lineRatio;
def lineB = bearB + (bullB - bearB) * lineRatio;
#=== Oscillator Plot ===
plot OscLine = osc;
OscLine.AssignValueColor(CreateColor(lineR, lineG, lineB));
OscLine.SetLineWeight(3);
ZeroLine.AssignValueColor(CreateColor(lineR, lineG, lineB));
#=== Reversal Signals ===
# Signals fire when osc crosses back inside the main bands
def rawBuy = osc[1] <= -lowerMult and osc > -lowerMult;
def rawSell = osc[1] >= upperMult and osc < upperMult;
def barsSinceSignal = CompoundValue(1,
if enableSignals and (rawBuy or rawSell) and (barsSinceSignal[1] >= cooldownBars)
then 0
else barsSinceSignal[1] + 1,
9999);
def barsOk = barsSinceSignal[1] >= cooldownBars;
def finalBuy = enableSignals and rawBuy and barsOk;
def finalSell = enableSignals and rawSell and barsOk;
#=== Signal Arrows ===
plot BuySignal = if finalBuy then osc - 0.15 else Double.NaN;
BuySignal.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
BuySignal.SetDefaultColor(Color.GREEN);
BuySignal.SetLineWeight(3);
plot SellSignal = if finalSell then osc + 0.15 else Double.NaN;
SellSignal.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
SellSignal.SetDefaultColor(Color.RED);
SellSignal.SetLineWeight(3);
#=== Fills between horizontal band levels ===
AddCloud(UpperBand_H, UpperBandI_H, CreateColor(129, 20, 135), CreateColor(129, 20, 135));
AddCloud(LowerBandI_H, LowerBand_H, CreateColor(70, 180, 155), CreateColor(70, 180, 155));
# Outer extension fills
AddCloud(OuterUpper_H, UpperBand_H, CreateColor(bearR, bearG, bearB), CreateColor(bearR, bearG, bearB));
AddCloud(LowerBand_H, OuterLower_H, CreateColor(bullR, bullG, bullB), CreateColor(bullR, bullG, bullB));
# Band0 fills (between band0 and main band)
AddCloud(UpperBand_H, UpperBand0_H, CreateColor(150, 40, 155), CreateColor(150, 40, 155));
AddCloud(LowerBand0_H, LowerBand_H, CreateColor(90, 200, 175), CreateColor(90, 200, 175));
Last edited: