Uptrick Liquid Reversal Bands for ThinkorSwim

chewie76

Well-known member
VIP
VIP Enthusiast
Uptrick Liquid Reversal Bands for ThinkorSwim was converted from this original source.
https://www.tradingview.com/script/NkOJyPWb-Uptrick-Liquid-Reversal-Bands/

1783866438008.png


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:
1785277700587.png


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:
Chewie in the tradingview the candle colors are the opposite color how can I change them.
If you want to change the colors to the opposite, then rename the below in the code line 26 and 27. Change the bull to bear and bear to bull.

#=== Fixed palette ===
def bullR = 92; def bullG = 240; def bullB = 215;
def bearR = 179; def bearG = 42; def bearB = 195;
 

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
1230 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top