Just found this thread and I'm so sorry if this has been answered already, but have you looked into John Carter's 1- x bars? It creates dots for volume spikes. This code is not from John Carter, but rather by someone on site who re-created his indicator. I'm reading through all of the posts and so far I'm amazed! I was looking for a simple MACD crossover scan and somehow landed on this thread. I've installed the indicator and it's pretty damn awesome! Here is the code. I apologize for not quoting the source, I don't remember who created it.
#Visual DMI Bar Paint and Volume Dot
#Last Updated on Wednesday, November 27 2019 at 04:18:47 PM
#
#CREDITS
# John Carter's 10x bars,
@sierioiza,
@billgt,
@tomsk
#
#CHANGELOG
# EXAMPLE 2019.11.25 1.0
@billgt - Example
#DESCRIPTION
# We can see the DMI / ADX calculation used painted on the price
# bars for the current time frame. The first part of this code was
# written by
@sierioiza and just copied here to add the volume dot.
# I copied some code for generating dots for some other Study from a post by
@tomsk and the modified to get the volume dots.
# A blue dot is plotted on bars that have a volume greater than input volumeGreaterPercent of the moving average for the timeframe of
# input volumeLength.
#INSTRUCTIONS
# Recommended to add it and use the defaults
# If you want to see volume dots on the yellow (neutral) bars too then change the plotVolumeDotOnNeutral to yes.
input length = 14;
input averageType = AverageType.WILDERS;
input volumeLength = 20;
input volumeFactor = 1;
input plotVolumeDotOnNeutral = no;
input volumeGreaterPercent = 50;
def hiDiff = high - high[1];
def loDiff = low[1] - low;
def plusDM = if hiDiff > loDiff and hiDiff > 0 then hiDiff else 0;
def minusDM = if loDiff > hiDiff and loDiff > 0 then loDiff else 0;
def ATR = MovingAverage(averageType, TrueRange(high, close, low), length);
def "DI+" = 100 * MovingAverage(averageType, plusDM, length) / ATR;
def "DI-" = 100 * MovingAverage(averageType, minusDM, length) / ATR;
def DX = if ("DI+" + "DI-" > 0) then 100 * AbsValue("DI+" - "DI-") / ("DI+" + "DI-") else 0;
def ADX = MovingAverage(averageType, DX, length);
declare upper;
declare once_per_bar;
def priceColor = if "DI+" > "DI-" and ADX > 20 then 0
else if "DI+" < "DI-" and ADX > 20 then 1
else 2;
AssignPriceColor(if pricecolor == 0 then Color.GREEN
else if priceColor == 1 then Color.RED
else Color.YELLOW);
#Get moving average of volume
def volAvg = MovingAverage(length = volumeLength,data = volume);
#Calculate middle of bar
def volDotLocation = volumeFactor * MidBodyVal();
#calculate 50% increase in average volume
def vol50IncLevel = volAvg * (1 + (volumeGreaterPercent / 100));
#if current volume is greater than the configured length MA of the volume and the price color is not yellow (neutral) or configured to plot on yellow bars (neutral) then plot volume dot
plot volDot = if volume >= vol50IncLevel and (priceColor != 2 or plotVolumeDotOnNeutral) then volDotLocation else Double.NaN;
volDot.SetStyle(Curve.POINTS);
volDot.SetDefaultColor(Color.CYAN);
volDot.SetLineWeight(2);
#AssignPriceColor(Color.BLUE);