Volume Based Colored Candle For ThinkOrSwim

NormalTrader888

New member
VIP
Trying something new. Please test it out. Need help since it's my very first custom indicator.
V8uKsTk.png

Code:
# ═══════════════════════════════════════════════════════════════════
# Volume-Validated Trend Color (VVTC) — 5-Minute Edition
# ═══════════════════════════════════════════════════════════════════

declare upper;

# ═══════════════════════════════════════════════════════════════════
# INPUTS
# ═══════════════════════════════════════════════════════════════════

input trendMaLen    = 21;
input fastMaLen     = 8;
input volLookback   = 15;
input volMultiplier = 1.3;
input volStrongMult = 2.0;
input atrLen        = 10;
input momentumLen   = 5;
input showLabels    = yes;
input useVwap       = yes;
input strictMode    = yes;

# ═══════════════════════════════════════════════════════════════════
# MOVING AVERAGES
# ═══════════════════════════════════════════════════════════════════

def trendMA    = ExpAverage(close, trendMaLen);
def fastMA     = ExpAverage(close, fastMaLen);
def trendSlope = trendMA - trendMA[2];
def fastSlope  = fastMA  - fastMA[1];

# ═══════════════════════════════════════════════════════════════════
# VWAP — using built-in to avoid recursive def issues
# ═══════════════════════════════════════════════════════════════════

def isNewDay     = GetDay() != GetDay()[1];
def cumVolPrice  = if isNewDay then close * volume
                  else cumVolPrice[1] + close * volume;
def cumVol       = if isNewDay then volume
                  else cumVol[1] + volume;
def vwapLine     = if !useVwap then close
                  else if cumVol > 0 then cumVolPrice / cumVol
                  else close;
def aboveVwap = close > vwapLine;
def belowVwap = close < vwapLine;

# ═══════════════════════════════════════════════════════════════════
# VOLUME
# ═══════════════════════════════════════════════════════════════════

def avgVol      = Average(volume, volLookback);
def volRatio    = if avgVol != 0 then volume / avgVol else 1;
def isSigVol    = volRatio >= volMultiplier;
def isStrongVol = volRatio >= volStrongMult;
def isNormalVol = volRatio >= 1.0;

def recentSigVol    = isSigVol    or isSigVol[1]    or isSigVol[2];
def recentStrongVol = isStrongVol or isStrongVol[1] or isStrongVol[2];

# ═══════════════════════════════════════════════════════════════════
# MOMENTUM
# ═══════════════════════════════════════════════════════════════════

def atrVal      = ATR(atrLen);
def safeATR     = if atrVal > 0 then atrVal else 0.0001;
def momentum    = close - close[momentumLen];
def momStrength = AbsValue(momentum) / safeATR;
def strongMom   = momStrength > 1.2;
def weakMom     = momStrength < 0.4;
def bullMom     = momentum > 0;
def bearMom     = momentum < 0;

# ═══════════════════════════════════════════════════════════════════
# CANDLE BODY
# ═══════════════════════════════════════════════════════════════════

def bullCandle = close > open;
def bearCandle = close < open;
def candleRange  = high - low;
def bodySize     = AbsValue(close - open);
def bodyRatio    = if candleRange != 0 then bodySize / candleRange else 0;
def strongCandle = bodyRatio > 0.5;

# ═══════════════════════════════════════════════════════════════════
# TREND CONDITIONS
# Price must be on correct side of both MAs,
# MAs must be aligned, slopes must agree,
# and VWAP must confirm (if enabled)
# ═══════════════════════════════════════════════════════════════════

def priceAboveBoth  = close > trendMA and close > fastMA;
def priceBelowBoth  = close < trendMA and close < fastMA;
def masAlignedBull  = fastMA > trendMA;
def masAlignedBear  = fastMA < trendMA;
def slopesBull      = trendSlope > 0 and fastSlope > 0;
def slopesBear      = trendSlope < 0 and fastSlope < 0;

def vwapBull = if useVwap then aboveVwap else 1;
def vwapBear = if useVwap then belowVwap else 1;

def rawBull = priceAboveBoth and masAlignedBull and slopesBull and vwapBull;
def rawBear = priceBelowBoth and masAlignedBear and slopesBear and vwapBear;

# ═══════════════════════════════════════════════════════════════════
# VOLUME VALIDATED TREND
# ═══════════════════════════════════════════════════════════════════

def volConfirmedBull = rawBull and recentSigVol and !weakMom and bullMom;
def volConfirmedBear = rawBear and recentSigVol and !weakMom and bearMom;

# ═══════════════════════════════════════════════════════════════════
# TREND STATE — persistent, sticky
# ═══════════════════════════════════════════════════════════════════

def trendState =
    if volConfirmedBull then  1
    else if volConfirmedBear then -1
    else trendState[1];

def inBull    = trendState ==  1;
def inBear    = trendState == -1;
def inNeutral = trendState ==  0;

def newBullTrend = inBull and trendState[1] != 1;
def newBearTrend = inBear and trendState[1] != -1;

# ═══════════════════════════════════════════════════════════════════
# STRICT MODE — candle direction must agree with trend
# ═══════════════════════════════════════════════════════════════════

def candleAgrees  = (inBull and bullCandle) or (inBear and bearCandle);
def candleOpposes = (inBull and bearCandle) or (inBear and bullCandle);

def showFull = if strictMode then candleAgrees  else 1;
def showDim  = if strictMode then candleOpposes else 0;

# ═══════════════════════════════════════════════════════════════════
# CANDLE COLOR
# ═══════════════════════════════════════════════════════════════════

AssignPriceColor(
    if inBull and showFull and recentStrongVol and strongMom
        then CreateColor(0,   255, 255)   # Cyan        - max bull
    else if inBull and showFull and recentStrongVol
        then CreateColor(0,   230, 130)   # Light green - strong vol
    else if inBull and showFull and recentSigVol
        then CreateColor(0,   190, 90)    # Green       - sig vol
    else if inBull and showFull
        then CreateColor(0,   140, 55)    # Dark green  - low vol
    else if inBull and showDim
        then CreateColor(40,  80,  60)    # Muted       - pullback in uptrend

    else if inBear and showFull and recentStrongVol and strongMom
        then CreateColor(255, 0,   255)   # Magenta     - max bear
    else if inBear and showFull and recentStrongVol
        then CreateColor(230, 0,   80)    # Bright red  - strong vol
    else if inBear and showFull and recentSigVol
        then CreateColor(190, 0,   55)    # Red         - sig vol
    else if inBear and showFull
        then CreateColor(140, 0,   35)    # Dark red    - low vol
    else if inBear and showDim
        then CreateColor(80,  40,  50)    # Muted       - bounce in downtrend

    else CreateColor(100, 100, 100)       # Gray        - no trend
);

# ═══════════════════════════════════════════════════════════════════
# MA + VWAP PLOTS
# ═══════════════════════════════════════════════════════════════════

plot TrendMAPlot = trendMA;
TrendMAPlot.SetLineWeight(2);
TrendMAPlot.AssignValueColor(
    if inBull then CreateColor(0,   200, 100)
    else if inBear then CreateColor(200, 0,   60)
    else Color.GRAY
);

plot FastMAPlot = fastMA;
FastMAPlot.SetLineWeight(1);
FastMAPlot.SetStyle(Curve.SHORT_DASH);
FastMAPlot.AssignValueColor(
    if inBull then CreateColor(0,   255, 150)
    else if inBear then CreateColor(255, 80,  80)
    else Color.DARK_GRAY
);

plot VwapPlot = if useVwap then vwapLine else Double.NaN;
VwapPlot.SetDefaultColor(CreateColor(255, 200, 0));
VwapPlot.SetLineWeight(2);

# ═══════════════════════════════════════════════════════════════════
# EMA CLOUD
# ═══════════════════════════════════════════════════════════════════

AddCloud(
    if inBull then fastMA  else Double.NaN,
    if inBull then trendMA else Double.NaN,
    CreateColor(0, 50, 25), CreateColor(0, 50, 25)
);
AddCloud(
    if inBear then fastMA  else Double.NaN,
    if inBear then trendMA else Double.NaN,
    CreateColor(50, 0, 15), CreateColor(50, 0, 15)
);

# ═══════════════════════════════════════════════════════════════════
# TREND CHANGE ARROWS
# ═══════════════════════════════════════════════════════════════════

plot BullArrow = if newBullTrend then low  else Double.NaN;
BullArrow.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
BullArrow.SetDefaultColor(CreateColor(0, 255, 255));
BullArrow.SetLineWeight(4);

plot BearArrow = if newBearTrend then high else Double.NaN;
BearArrow.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
BearArrow.SetDefaultColor(CreateColor(255, 0, 255));
BearArrow.SetLineWeight(4);

# ═══════════════════════════════════════════════════════════════════
# LABELS
# ═══════════════════════════════════════════════════════════════════

AddLabel(showLabels,
    "Trend: " + (if inBull then "BULL" else if inBear then "BEAR" else "NEUTRAL"),
    if inBull then CreateColor(0, 230, 100)
    else if inBear then CreateColor(230, 0, 60)
    else Color.GRAY
);

AddLabel(showLabels,
    "Vol: " + Round(volRatio, 1) + "x " +
    (if isStrongVol then "STRONG" else if isSigVol then "SIG" else "WEAK"),
    if isStrongVol then CreateColor(0,   255, 255)
    else if isSigVol    then CreateColor(0,   200, 100)
    else                     Color.GRAY
);

AddLabel(showLabels and useVwap,
    "VWAP: " + (if aboveVwap then "ABOVE" else "BELOW"),
    if aboveVwap then CreateColor(0, 200, 100)
    else              CreateColor(200, 0, 60)
);

AddLabel(showLabels,
    "Mom: " + Round(momStrength, 2) +
    (if strongMom then " STRONG" else if weakMom then " WEAK" else " MOD"),
    if strongMom then CreateColor(0,   230, 120)
    else if weakMom  then Color.GRAY
    else                  Color.WHITE
);
 
Last edited by a moderator:

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