Just a rewrite of a transcribed script from TV that in my opinion correctly attributes volume confirmation to the price chart- emphasizing whether the action is backed by the volume and participation.
Code:
########################################################
# Volume Confirmed Trend Dashboard
# Based on TASC 2024.08:
# Trend Thrust Indicator + Volume Price Confirmation
#
# Rewritten for ThinkorSwim as a lower confirmation panel
# Role:
# - Confirms whether trend has volume participation
# - Does NOT act as a standalone buy/sell system
# REWRITE AS A VALIDATOR NOT INDICATOR
# ANTWERKS
########################################################
declare lower;
#========================
# INPUTS
#========================
input adxThreshold = 20.0;
input adxStrongThreshold = 30.0;
input adxLength = 14;
input adxSmoothingLength = 14;
input ttiFastLength = 13;
input ttiSlowLength = 26;
input ttiSignalLength = 9;
input vpciFastLength = 5;
input vpciSlowLength = 25;
input vpciScale = 10.0;
input showLabels = yes;
input showClouds = yes;
input showVerticalEvents = yes;
input showHistogram = yes;
input showLines = yes;
#========================
# HELPERS
#========================
script SafeVWMA {
input src = close;
input len = 14;
input vol = volume;
def numerator = Average(src * vol, len);
def denominator = Average(vol, len);
plot result =
if denominator != 0 then numerator / denominator
else Average(src, len);
}
script TTI_Calc {
input price = close;
input fast = 13;
input slow = 26;
def fastMA = SafeVWMA(price, fast);
def slowMA = SafeVWMA(price, slow);
def ratio =
if slowMA != 0 then fastMA / slowMA
else 1;
def vMult = Power(ratio, 2);
def VEFA = fastMA * vMult;
def VESA =
if vMult != 0 then slowMA / vMult
else slowMA;
plot out = VEFA - VESA;
}
script VPCI_Calc {
input longLen = 25;
input shortLen = 5;
def longVWMA = SafeVWMA(close, longLen);
def longSMA = Average(close, longLen);
def shortVWMA = SafeVWMA(close, shortLen);
def shortSMA = Average(close, shortLen);
def shortVolAvg = Average(volume, shortLen);
def longVolAvg = Average(volume, longLen);
def VPC = longVWMA - longSMA;
def VPR =
if shortSMA != 0 then shortVWMA / shortSMA
else 1;
def VM =
if longVolAvg != 0 then shortVolAvg / longVolAvg
else 1;
plot out = VPC * VPR * VM;
}
#========================
# CORE CALCULATIONS
#========================
def diPlus = DMI(length = adxLength)."DI+";
def diMinus = DMI(length = adxLength)."DI-";
def dx =
if diPlus + diMinus > 0 then
100 * AbsValue(diPlus - diMinus) / (diPlus + diMinus)
else 0;
def adx = WildersAverage(dx, adxSmoothingLength);
def tti = TTI_Calc(close, ttiFastLength, ttiSlowLength);
def ttiSignal = Average(tti, ttiSignalLength);
def ttiHist = tti - ttiSignal;
def vpci = VPCI_Calc(vpciSlowLength, vpciFastLength);
def vpciPlotValue = vpci * vpciScale;
#========================
# STATES
#========================
def trendBuilding =
adx >= 15 and adx < adxThreshold;
def trendUsable =
adx >= adxThreshold and adx < adxStrongThreshold;
def trendStrong =
adx >= adxStrongThreshold;
def trendWeak =
adx < 15;
def adxRising =
adx > adx[1];
def adxFalling =
adx < adx[1];
def ttiBull =
tti > ttiSignal;
def ttiBear =
tti < ttiSignal;
def ttiImproving =
ttiHist > ttiHist[1];
def ttiFading =
ttiHist < ttiHist[1];
def vpciBull =
vpci > 0;
def vpciBear =
vpci < 0;
def vpciImproving =
vpci > vpci[1];
def vpciFading =
vpci < vpci[1];
def bullVolumeConfirm =
adx >= adxThreshold and
ttiBull and
vpciBull;
def bearVolumeConfirm =
adx >= adxThreshold and
ttiBear and
vpciBear;
def bullEarlyConfirm =
adx >= 15 and
adx < adxThreshold and
adxRising and
ttiBull and
vpciBull;
def bearEarlyConfirm =
adx >= 15 and
adx < adxThreshold and
adxRising and
ttiBear and
vpciBear;
def bullDivergence =
ttiBull and
!vpciBull;
def bearDivergence =
ttiBear and
!vpciBear;
def bullWarning =
ttiBull and
vpciBull and
(ttiFading or vpciFading or adxFalling);
def bearWarning =
ttiBear and
vpciBear and
(ttiImproving or vpciImproving or adxFalling);
def neutral =
!bullVolumeConfirm and
!bearVolumeConfirm and
!bullEarlyConfirm and
!bearEarlyConfirm;
#========================
# CONFIRMATION STATE MACHINE
#========================
def startBullConfirm =
bullVolumeConfirm and !bullVolumeConfirm[1];
def startBearConfirm =
bearVolumeConfirm and !bearVolumeConfirm[1];
def bullFail =
vpciBear or ttiBear;
def bearFail =
vpciBull or ttiBull;
def inBullConfirm =
CompoundValue(
1,
if startBullConfirm then 1
else if bullFail then 0
else inBullConfirm[1],
0
);
def inBearConfirm =
CompoundValue(
1,
if startBearConfirm then 1
else if bearFail then 0
else inBearConfirm[1],
0
);
def bullConfirmEvent =
startBullConfirm;
def bearConfirmEvent =
startBearConfirm;
def bullFailEvent =
inBullConfirm[1] and bullFail;
def bearFailEvent =
inBearConfirm[1] and bearFail;
#========================
# PLOTS
#========================
plot ZeroLine = 0;
ZeroLine.SetDefaultColor(Color.LIGHT_GRAY);
ZeroLine.SetStyle(Curve.SHORT_DASH);
plot ADXLine = if showLines then adx else Double.NaN;
ADXLine.SetDefaultColor(Color.MAGENTA);
ADXLine.SetLineWeight(2);
plot ADXThresholdLine = if showLines then adxThreshold else Double.NaN;
ADXThresholdLine.SetDefaultColor(Color.PLUM);
ADXThresholdLine.SetStyle(Curve.SHORT_DASH);
plot TTIHistPlot = if showHistogram then ttiHist else Double.NaN;
TTIHistPlot.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
TTIHistPlot.SetLineWeight(3);
TTIHistPlot.AssignValueColor(
if ttiBull and ttiImproving then Color.GREEN
else if ttiBull and ttiFading then Color.YELLOW
else if ttiBear and ttiFading then Color.RED
else if ttiBear and ttiImproving then Color.MAGENTA
else Color.GRAY
);
plot TTIPlot = if showLines then tti else Double.NaN;
TTIPlot.SetDefaultColor(Color.ORANGE);
TTIPlot.SetLineWeight(2);
plot TTISignalPlot = if showLines then ttiSignal else Double.NaN;
TTISignalPlot.SetDefaultColor(Color.VIOLET);
TTISignalPlot.SetLineWeight(1);
plot VPCIPlot = if showLines then vpciPlotValue else Double.NaN;
VPCIPlot.SetPaintingStrategy(PaintingStrategy.LINE);
VPCIPlot.SetLineWeight(2);
VPCIPlot.AssignValueColor(
if vpciBull and vpciImproving then Color.GREEN
else if vpciBull and vpciFading then Color.YELLOW
else if vpciBear and vpciFading then Color.RED
else if vpciBear and vpciImproving then Color.MAGENTA
else Color.GRAY
);
# Optional clouds
AddCloud(
if showClouds then TTIPlot else Double.NaN,
if showClouds then TTISignalPlot else Double.NaN,
Color.DARK_GREEN,
Color.DARK_RED
);
AddCloud(
if showClouds then VPCIPlot else Double.NaN,
if showClouds then ZeroLine else Double.NaN,
Color.GREEN,
Color.RED
);
#========================
# VERTICAL EVENT LINES
#========================
AddVerticalLine(
showVerticalEvents and bullConfirmEvent,
"VOL CONFIRM",
Color.GREEN
);
AddVerticalLine(
showVerticalEvents and bearConfirmEvent,
"BEAR VOL CONFIRM",
Color.RED
);
AddVerticalLine(
showVerticalEvents and bullFailEvent,
"VOL FAIL",
Color.ORANGE
);
AddVerticalLine(
showVerticalEvents and bearFailEvent,
"BEAR FAIL",
Color.ORANGE
);
#========================
# LABELS
#========================
AddLabel(
showLabels,
"ADX: " + Round(adx, 1) + " - " +
if trendStrong then "STRONG"
else if trendUsable then "USABLE"
else if trendBuilding then "BUILDING"
else "WEAK",
if trendStrong then Color.GREEN
else if trendUsable then Color.CYAN
else if trendBuilding then Color.YELLOW
else Color.GRAY
);
AddLabel(
showLabels,
"TTI: " +
if ttiBull and ttiImproving then "BULL THRUST"
else if ttiBull and ttiFading then "BULL FADING"
else if ttiBear and ttiFading then "BEAR THRUST"
else if ttiBear and ttiImproving then "BEAR FADING"
else "NEUTRAL",
if ttiBull and ttiImproving then Color.GREEN
else if ttiBull and ttiFading then Color.YELLOW
else if ttiBear and ttiFading then Color.RED
else if ttiBear and ttiImproving then Color.MAGENTA
else Color.GRAY
);
AddLabel(
showLabels,
"VPCI: " +
if vpciBull and vpciImproving then "BULL CONFIRM"
else if vpciBull and vpciFading then "BULL FADING"
else if vpciBear and vpciFading then "BEAR CONFIRM"
else if vpciBear and vpciImproving then "BEAR FADING"
else "NEUTRAL",
if vpciBull and vpciImproving then Color.GREEN
else if vpciBull and vpciFading then Color.YELLOW
else if vpciBear and vpciFading then Color.RED
else if vpciBear and vpciImproving then Color.MAGENTA
else Color.GRAY
);
AddLabel(
showLabels,
"VOL TREND: " +
if bullVolumeConfirm then "BULL CONFIRMED"
else if bearVolumeConfirm then "BEAR CONFIRMED"
else if bullEarlyConfirm then "EARLY BULL CONFIRM"
else if bearEarlyConfirm then "EARLY BEAR CONFIRM"
else if bullDivergence then "BULL PRICE / NO VOLUME"
else if bearDivergence then "BEAR PRICE / NO VOLUME"
else "NEUTRAL / WAIT",
if bullVolumeConfirm then Color.GREEN
else if bearVolumeConfirm then Color.RED
else if bullEarlyConfirm then Color.CYAN
else if bearEarlyConfirm then Color.PINK
else if bullDivergence or bearDivergence then Color.ORANGE
else Color.GRAY
);
AddLabel(
showLabels,
"ACTION: " +
if bullVolumeConfirm and !bullWarning then "CONFIRM LONG SETUPS"
else if bullVolumeConfirm and bullWarning then "LONG CONFIRMED / FADING"
else if bullEarlyConfirm then "EARLY LONG WATCH"
else if bullDivergence then "WAIT - PRICE AHEAD OF VOLUME"
else if bearVolumeConfirm and !bearWarning then "CONFIRM SHORT SETUPS"
else if bearVolumeConfirm and bearWarning then "SHORT CONFIRMED / FADING"
else if bearEarlyConfirm then "EARLY SHORT WATCH"
else if bearDivergence then "WAIT - BEAR MOVE UNCONFIRMED"
else "NO VOLUME EDGE",
if bullVolumeConfirm and !bullWarning then Color.GREEN
else if bullVolumeConfirm and bullWarning then Color.YELLOW
else if bullEarlyConfirm then Color.CYAN
else if bullDivergence then Color.ORANGE
else if bearVolumeConfirm and !bearWarning then Color.RED
else if bearVolumeConfirm and bearWarning then Color.MAGENTA
else if bearEarlyConfirm then Color.PINK
else if bearDivergence then Color.ORANGE
else Color.GRAY
);