MAD Volatility Trail [BackQuant] for ThinkOrSwim

chewie76

Well-known member
VIP
VIP Enthusiast
MAD Volatility Trail [BackQuant]

Overview

MAD Volatility Trail is a robust trend-following overlay built from a rolling median and Median Absolute Deviation rather than a conventional moving average and standard deviation.

The indicator estimates a central price using the rolling median, measures how widely recent prices are distributed around that median using MAD, converts that dispersion into adaptive upper and lower bands, and then transforms those bands into one-sided trailing boundaries.

Original concept: https://www.tradingview.com/script/H9JdI5rn-MAD-Volatility-Trail-BackQuant/

Trading Note: I've noticed that when price gets to the line, there is a big move in either direction. That is a good time to place a straddle option strategy.

Here is an hourly chart of /NQ
1788017348330.png


Code:
# MAD_Volatility_Trail
# Original concept: https://www.tradingview.com/script/H9JdI5rn-MAD-Volatility-Trail-BackQuant/
# Converted by Chewie 8/29/2026

declare upper;

# ──────────────────────────────────────────────
# INPUTS
# ──────────────────────────────────────────────

input src             = close;
input madLen          = 45;
input madScale        = 1.4655;
input factor          = 1.15;

input useAtrFloor     = no;
input atrLen          = 14;
input atrFloorMult    = 0.2;

input useSlopeConfirm = no;
input slopeLen        = 2;
input triggerClose    = yes;
input breakTrailOnFlip = yes;

input showTrail       = yes;
input showMedian      = no;
input showBands       = no;
input showFill        = yes;
input showGlow        = yes;
input showSig         = yes;
input paintBar        = yes;

DefineGlobalColor("Bull",      Color.GREEN);
DefineGlobalColor("Bear",      Color.RED);
DefineGlobalColor("Median",    Color.WHITE);
DefineGlobalColor("GradL1",    CreateColor(0,   200, 0));
DefineGlobalColor("GradL2",    CreateColor(0,   170, 0));
DefineGlobalColor("GradL3",    CreateColor(0,   130, 0));
DefineGlobalColor("GradL4",    CreateColor(0,    90, 0));
DefineGlobalColor("GradL5",    CreateColor(0,    55, 0));
DefineGlobalColor("GradS1",    CreateColor(200,   0, 0));
DefineGlobalColor("GradS2",    CreateColor(170,   0, 0));
DefineGlobalColor("GradS3",    CreateColor(130,   0, 0));
DefineGlobalColor("GradS4",    CreateColor(90,    0, 0));
DefineGlobalColor("GradS5",    CreateColor(55,    0, 0));
DefineGlobalColor("GlowBull",  CreateColor(0,   255, 0));
DefineGlobalColor("GlowBear",  CreateColor(255,   0, 0));
DefineGlobalColor("BloomBull", CreateColor(0,   200, 0));
DefineGlobalColor("BloomBear", CreateColor(200,   0, 0));

# ──────────────────────────────────────────────
# MAD CALCULATION
# ──────────────────────────────────────────────

def medianValue      = Median(src, madLen);
def absDev           = AbsValue(src - medianValue);
def rawMad           = Median(absDev, madLen);
def robustDeviation  = rawMad * madScale;
def madWidth         = robustDeviation * factor;
def atrVal           = WildersAverage(TrueRange(high, close, low), atrLen);
def atrFloorAmt      = atrVal * atrFloorMult;
def bandWidth        = if useAtrFloor then Max(madWidth, atrFloorAmt) else madWidth;
def rawUpper         = medianValue + bandWidth;
def rawLower         = medianValue - bandWidth;

# ──────────────────────────────────────────────
# TRIGGER
# ──────────────────────────────────────────────

def trigger = if triggerClose then close else src;

# ──────────────────────────────────────────────
# TRAILING BANDS
# ──────────────────────────────────────────────

def trailLower = CompoundValue(1,
    if !IsNaN(trailLower[1]) and trigger[1] > trailLower[1]
    then Max(rawLower, trailLower[1])
    else rawLower,
    rawLower);

def trailUpper = CompoundValue(1,
    if !IsNaN(trailUpper[1]) and trigger[1] < trailUpper[1]
    then Min(rawUpper, trailUpper[1])
    else rawUpper,
    rawUpper);

# ──────────────────────────────────────────────
# SLOPE CONFIRMATION
# ──────────────────────────────────────────────

def bullSlopePass = if !useSlopeConfirm then 1 else if medianValue > medianValue[slopeLen] then 1 else 0;
def bearSlopePass = if !useSlopeConfirm then 1 else if medianValue < medianValue[slopeLen] then 1 else 0;

# ──────────────────────────────────────────────
# TREND STATE
# ──────────────────────────────────────────────

def trend = CompoundValue(1,
    if trend[1] == 0 and !IsNaN(medianValue) then
        if trigger >= medianValue then 1 else -1
    else if trigger > trailUpper and trend[1] != 1 and bullSlopePass then 1
    else if trigger < trailLower and trend[1] != -1 and bearSlopePass then -1
    else trend[1],
    0);

def bullFlip  = trend == 1  and trend[1] == -1;
def bearFlip  = trend == -1 and trend[1] == 1;
def trendFlip = bullFlip or bearFlip;

def trendTrail = if trend == 1 then trailLower
                 else if trend == -1 then trailUpper
                 else Double.NaN;

def plottedTrail = if breakTrailOnFlip and trendFlip then Double.NaN else trendTrail;

# ──────────────────────────────────────────────
# VISUAL STRENGTH
# ──────────────────────────────────────────────

def trailDistance    = if !IsNaN(trendTrail) then AbsValue(close - trendTrail) else 0.0;
def distanceStrength = if bandWidth > 0 then Min(trailDistance / bandWidth, 2.0) / 2.0 else 0.0;
def medianSlope      = AbsValue(medianValue - medianValue[slopeLen]);
def slopeStrength    = if bandWidth > 0 then Min(medianSlope / bandWidth, 1.0) else 0.0;
def trendStrength    = Min(distanceStrength * 0.70 + slopeStrength * 0.30, 1.0);

def barsSinceFlip = if trendFlip then 0
                    else if IsNaN(barsSinceFlip[1]) then 100000
                    else barsSinceFlip[1] + 1;

def bloomStrength = if barsSinceFlip == 0 then 1.0
                    else if barsSinceFlip == 1 then 0.55
                    else if barsSinceFlip == 2 then 0.25
                    else 0.0;

# ──────────────────────────────────────────────
# GRADIENT REFERENCE VALUES
# ──────────────────────────────────────────────

def fillReady = if showTrail and showFill and !IsNaN(plottedTrail) then 1 else 0;
def isBull    = trend == 1;

def grad1 = trendTrail + (close - trendTrail) * 0.15;
def grad2 = trendTrail + (close - trendTrail) * 0.35;
def grad3 = trendTrail + (close - trendTrail) * 0.60;
def grad4 = trendTrail + (close - trendTrail) * 0.82;

# ──────────────────────────────────────────────
# GLOW / BLOOM VALUES
# ──────────────────────────────────────────────

def atr14      = WildersAverage(TrueRange(high, close, low), 14);
def glowAmt    = atr14 * (0.045 + trendStrength * 0.025);
def outerGlow  = glowAmt * 2.3;
def glowReady  = if showTrail and showGlow and !IsNaN(plottedTrail) then 1 else 0;
def bloomWidth = atr14 * (0.12 + bloomStrength * 0.08);
def bloomReady = if showTrail and showGlow and bloomStrength > 0 and !IsNaN(trendTrail) then 1 else 0;

# ──────────────────────────────────────────────
# TRAIL PLOT
# ──────────────────────────────────────────────

plot TrailLine = if showTrail then plottedTrail else Double.NaN;
TrailLine.SetLineWeight(3);
TrailLine.AssignValueColor(if trend == 1 then GlobalColor("Bull") else GlobalColor("Bear"));
TrailLine.SetStyle(Curve.FIRM);

# ──────────────────────────────────────────────
# MEDIAN & RAW BANDS
# ──────────────────────────────────────────────

plot MedianLine = if showMedian then medianValue else Double.NaN;
MedianLine.SetDefaultColor(GlobalColor("Median"));
MedianLine.SetLineWeight(1);

plot UpperBand = if showBands then rawUpper else Double.NaN;
UpperBand.SetDefaultColor(Color.GRAY);
UpperBand.SetLineWeight(1);

plot LowerBand = if showBands then rawLower else Double.NaN;
LowerBand.SetDefaultColor(Color.GRAY);
LowerBand.SetLineWeight(1);

# ──────────────────────────────────────────────
# BULL GRADIENT PLOTS & CLOUDS
# ──────────────────────────────────────────────

plot BullTrail = if fillReady and isBull then trendTrail else Double.NaN;
BullTrail.Hide();
plot BullGrad1 = if fillReady and isBull then grad1 else Double.NaN;
BullGrad1.Hide();
plot BullGrad2 = if fillReady and isBull then grad2 else Double.NaN;
BullGrad2.Hide();
plot BullGrad3 = if fillReady and isBull then grad3 else Double.NaN;
BullGrad3.Hide();
plot BullGrad4 = if fillReady and isBull then grad4 else Double.NaN;
BullGrad4.Hide();
plot BullPrice = if fillReady and isBull then close else Double.NaN;
BullPrice.Hide();

AddCloud(BullGrad1, BullTrail, GlobalColor("GradL1"), GlobalColor("GradL2"));
AddCloud(BullGrad2, BullGrad1, GlobalColor("GradL2"), GlobalColor("GradL3"));
AddCloud(BullGrad3, BullGrad2, GlobalColor("GradL3"), GlobalColor("GradL4"));
AddCloud(BullGrad4, BullGrad3, GlobalColor("GradL4"), GlobalColor("GradL5"));
AddCloud(BullPrice, BullGrad4, GlobalColor("GradL5"), GlobalColor("GradL5"));

# ──────────────────────────────────────────────
# BEAR GRADIENT PLOTS & CLOUDS
# ──────────────────────────────────────────────

plot BearTrail = if fillReady and !isBull then trendTrail else Double.NaN;
BearTrail.Hide();
plot BearGrad1 = if fillReady and !isBull then grad1 else Double.NaN;
BearGrad1.Hide();
plot BearGrad2 = if fillReady and !isBull then grad2 else Double.NaN;
BearGrad2.Hide();
plot BearGrad3 = if fillReady and !isBull then grad3 else Double.NaN;
BearGrad3.Hide();
plot BearGrad4 = if fillReady and !isBull then grad4 else Double.NaN;
BearGrad4.Hide();
plot BearPrice = if fillReady and !isBull then close else Double.NaN;
BearPrice.Hide();

AddCloud(BearTrail, BearGrad1, GlobalColor("GradS1"), GlobalColor("GradS2"));
AddCloud(BearGrad1, BearGrad2, GlobalColor("GradS2"), GlobalColor("GradS3"));
AddCloud(BearGrad2, BearGrad3, GlobalColor("GradS3"), GlobalColor("GradS4"));
AddCloud(BearGrad3, BearGrad4, GlobalColor("GradS4"), GlobalColor("GradS5"));
AddCloud(BearGrad4, BearPrice, GlobalColor("GradS5"), GlobalColor("GradS5"));

# ──────────────────────────────────────────────
# BULL GLOW PLOTS & CLOUDS
# ──────────────────────────────────────────────

plot BullGlowOL = if glowReady and isBull then trendTrail - outerGlow else Double.NaN;
BullGlowOL.Hide();
plot BullGlowOU = if glowReady and isBull then trendTrail + outerGlow else Double.NaN;
BullGlowOU.Hide();
plot BullGlowL  = if glowReady and isBull then trendTrail - glowAmt else Double.NaN;
BullGlowL.Hide();
plot BullGlowU  = if glowReady and isBull then trendTrail + glowAmt else Double.NaN;
BullGlowU.Hide();

AddCloud(BullGlowOU, BullGlowOL, GlobalColor("GlowBull"), GlobalColor("GlowBull"));
AddCloud(BullGlowU,  BullGlowL,  GlobalColor("GlowBull"), GlobalColor("GlowBull"));

# ──────────────────────────────────────────────
# BEAR GLOW PLOTS & CLOUDS
# ──────────────────────────────────────────────

plot BearGlowOL = if glowReady and !isBull then trendTrail - outerGlow else Double.NaN;
BearGlowOL.Hide();
plot BearGlowOU = if glowReady and !isBull then trendTrail + outerGlow else Double.NaN;
BearGlowOU.Hide();
plot BearGlowL  = if glowReady and !isBull then trendTrail - glowAmt else Double.NaN;
BearGlowL.Hide();
plot BearGlowU  = if glowReady and !isBull then trendTrail + glowAmt else Double.NaN;
BearGlowU.Hide();

AddCloud(BearGlowOU, BearGlowOL, GlobalColor("GlowBear"), GlobalColor("GlowBear"));
AddCloud(BearGlowU,  BearGlowL,  GlobalColor("GlowBear"), GlobalColor("GlowBear"));

# ──────────────────────────────────────────────
# BLOOM PLOTS & CLOUDS
# ──────────────────────────────────────────────

plot BullBloomL = if bloomReady and isBull  then trendTrail - bloomWidth else Double.NaN;
BullBloomL.Hide();
plot BullBloomH = if bloomReady and isBull  then trendTrail + bloomWidth else Double.NaN;
BullBloomH.Hide();
plot BearBloomL = if bloomReady and !isBull then trendTrail - bloomWidth else Double.NaN;
BearBloomL.Hide();
plot BearBloomH = if bloomReady and !isBull then trendTrail + bloomWidth else Double.NaN;
BearBloomH.Hide();

AddCloud(BullBloomH, BullBloomL, GlobalColor("BloomBull"), GlobalColor("BloomBull"));
AddCloud(BearBloomH, BearBloomL, GlobalColor("BloomBear"), GlobalColor("BloomBear"));

# ──────────────────────────────────────────────
# CANDLE COLORING
# ──────────────────────────────────────────────

AssignPriceColor(
    if !paintBar then Color.CURRENT
    else if trend == 1 then GlobalColor("Bull")
    else GlobalColor("Bear")
);

# ──────────────────────────────────────────────
# SIGNALS
# ──────────────────────────────────────────────

plot BullSignal = if showSig and bullFlip then trendTrail else Double.NaN;
BullSignal.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
BullSignal.SetDefaultColor(GlobalColor("Bull"));
BullSignal.SetLineWeight(3);

plot BearSignal = if showSig and bearFlip then trendTrail else Double.NaN;
BearSignal.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
BearSignal.SetDefaultColor(GlobalColor("Bear"));
BearSignal.SetLineWeight(3);
 

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
2252 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