Carrey's Velocity and Acceleration
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © CarreyTrades

// This is initially based on the MA Speed indicator from TradeStation (https://www.tradingview.com/v/4j9HWCVA/)
// and expanded upon greatly. This implements 3 different variable MAs and calculates and plots
// both speed and acceleration of each. Also, a single line composite option is
// included for both speed and acceleration that changes color based on directional
// confluence of each MA's speed/acceleration. Additionally, optional labels are
// included to show where the 3 MAs are clustered, and a volatile move is expected, 
// and where they are more distributed, expecting a temporary reversal.

//@version=5
indicator("Carrey's Velocity and Acceleration", overlay=false)

enableMA = input.bool(true, title="════ Enable Moving Average Rate of Change ════", group="MA")

q1 = input.bool(false, title="Enable 9/36/64 MA", inline="d", group="MA")
q2 = input.bool(false, title="Enable 9/24/49 MA", inline="d", group="MA")
q3 = input.bool(false, title="Enable 9/36/49 MA", inline="d", group="MA")

// accept user inputs for the types of moving average
enableMA1 = enableMA ? input.bool(true, title="Enable MA Velocity 1", inline="ma1", group="MA") : na
malength1 = q1 or q2 or q3 ? 9 : input.int(25, minval=1, title='MA Length 1', group="MA")
masrc1 = input(close, title='MA1 Source', group="MA")
matype1 = input.string("Hull", title='MA1 AvgType', options=["simple", "exponential", "Hull", "weighted", "volume weighted"], group="MA")


enableMA2 = enableMA ? input.bool(true, title="Enable MA Velocity 2", inline="ma2", group="MA") : na
malength2 = q1 or q3 ? 36 : q2 ? 24 :input.int(36, minval=1, title='MA Length 2', group="MA")
masrc2 = input(close, title='MA2 Source', group="MA")
matype2 = input.string("Hull", title='MA2 AvgType', options=["simple", "exponential", "Hull", "weighted", "volume weighted"], group="MA")

enableMA3 = enableMA ? input.bool(true, title="Enable MA Velocity 3", inline="ma3", group="MA") : na
malength3 = q1 ? 64 : q2 or q3 ? 49 : input.int(49, minval=1, title='MA Length 3', group="MA")
masrc3 = input(close, title='MA3 Source', group="MA")
matype3 = input.string("Hull", title='MA3 AvgType', options=["simple", "exponential", "Hull", "weighted", "volume weighted"], group="MA")

scale = input.float(2, title="Scale MA Plots", minval=0.1, maxval=25, step=0.1, group="MA")
dc = input.float(1, title="Acceleration Extreme", minval=1, maxval=100, group="MA")
dm = input.float(2, title="Acceleration Scale", minval=1, maxval=100, group="MA")

enablecomp = input.bool(false, title="Composite MA Speed?", inline="c", group="MA")
enabledp   = input.bool(false, title="Composite MA Acceleration?", inline="c2", group="MA")
numa       = input.string("Average", title="Velocity Composite Style", options=["Average", "Cumulative"], inline="c", group="MA")
numb       = input.string("Average", title="Accel Composite Style", options=["Average", "Cumulative"], inline="c2", group="MA")


enabled1 = enableMA ? input.bool(false, title="Enable MA Acceleration 1", inline="ma1", group="MA") : na
enabled2 = enableMA ? input.bool(false, title="Enable MA Acceleration 2", inline="ma2", group="MA") : na
enabled3 = enableMA ? input.bool(false, title="Enable MA Acceleration 3", inline="ma3", group="MA") : na

enablecd = input.bool(false, title="Enable Velocity Cluster/Distribution Signals", inline="cd", group="MA")
clust    = input.float(10,  title="Cluster Percent Sensitivity", minval=1, maxval=1000, step=1, inline="cd", group="MA")   
dist     = input.float(150, title="Distribution Percent Sensitivity", minval=1, maxval=1000, step=1, inline="cd", group="MA")
cdl      = input.int(3, title="Cluster/Distribution Lookback", tooltip="How many bars back before getting another Cluster/Distribution signal. This helps to avoid overlapping or constantly repeating signals", inline="cd1", group="MA")
ex       = input.float(30, title="Extrema Levels", inline="cd2", group="MA")

// calculate moving averages
simplema1 = ta.sma(masrc1, malength1)
exponentialma1 = ta.ema(masrc1, malength1)
hullma1 = ta.wma(2 * ta.wma(masrc1, malength1 / 2) - ta.wma(masrc1, malength1), math.round(math.sqrt(malength1)))
weightedma1 = ta.wma(masrc1, malength1)
volweightedma1 = ta.vwma(masrc1, malength1)

simplema2 = ta.sma(masrc2, malength2)
exponentialma2 = ta.ema(masrc2, malength2)
hullma2 = ta.wma(2 * ta.wma(masrc2, malength2 / 2) - ta.wma(masrc2, malength2), math.round(math.sqrt(malength2)))
weightedma2 = ta.wma(masrc2, malength2)
volweightedma2 = ta.vwma(masrc2, malength2)

simplema3 = ta.sma(masrc3, malength3)
exponentialma3 = ta.ema(masrc3, malength3)
hullma3 = ta.wma(2 * ta.wma(masrc3, malength3 / 2) - ta.wma(masrc3, malength3), math.round(math.sqrt(malength3)))
weightedma3 = ta.wma(masrc3, malength3)
volweightedma3 = ta.vwma(masrc3, malength3)

// assign value based on user input
avgval1 = matype1 == "simple" ? simplema1 : matype1 == "exponential" ? exponentialma1 : matype1 == "Hull" ? hullma1 : matype1 == "weighted" ? weightedma1 : matype1 == "volume weighted" ? volweightedma1 : na
avgval2 = matype2 == "simple" ? simplema2 : matype2 == "exponential" ? exponentialma2 : matype2 == "Hull" ? hullma2 : matype2 == "weighted" ? weightedma2 : matype2 == "volume weighted" ? volweightedma2 : na
avgval3 = matype3 == "simple" ? simplema3 : matype3 == "exponential" ? exponentialma3 : matype3 == "Hull" ? hullma3 : matype3 == "weighted" ? weightedma3 : matype3 == "volume weighted" ? volweightedma3 : na

// Calculate MA speed
MA_speed1 = (avgval1 / avgval1[1] - 1)
MA_speed2 = (avgval2 / avgval2[1] - 1)
MA_speed3 = (avgval3 / avgval3[1] - 1)

// Second Derivative

d1 = (MA_speed1 / MA_speed1[1] - 1)
d2 = (MA_speed2 / MA_speed2[1] - 1)
d3 = (MA_speed3 / MA_speed3[1] - 1)

// set color

Pcolor1 = MA_speed1 > 0 ? color.orange : MA_speed1 < 0 ? color.yellow : na
Pcolor2 = MA_speed2 > 0 ? color.fuchsia : MA_speed2 < 0 ? color.aqua : na
Pcolor3 = MA_speed3 > 0 ? color.white : MA_speed3 < 0 ? color.gray : na

Pcolor4 = d1 > 0 ? color.blue : d1 < 0 ? color.purple : na
Pcolor5 = d2 > 0 ? color.green : d2 < 0 ? color.red : na
Pcolor6 = d3 > 0 ? color.olive : d3 < 0 ? color.teal : na


// Derivative Conditions

dd1 = d1 > 0 ? 1 : d1 < 0 ? -1 : na
dl1 = d1 > 0 ? color.green : d1 < 0 ? color.red : na
dd2 = d2 > 0 ? 1 : d2 < 0 ? -1 : na
dd3 = d3 > 0 ? 1 : d3 < 0 ? -1 : na

dp1 = d1 > dc*2.5 ? dc*2.5 : d1 < (-1)*dc*2.5 ? (-1)*dc*2.5 : d1
dp2 = d2 > dc*2.5 ? dc*2.5 : d2 < (-1)*dc*2.5 ? (-1)*dc*2.5 : d2
dp3 = d3 > dc*2.5 ? dc*2.5 : d3 < (-1)*dc*2.5 ? (-1)*dc*2.5 : d3


// Locate crossover

d1c = dd1[1] > dd1 ? -1 : dd1[1] < dd1 ? 1 : 0
d2c = dd2[1] > dd2 ? -1 : dd2[1] < dd2 ? 1 : 0
d3c = dd3[1] > dd3 ? -1 : dd3[1] < dd3 ? 1 : 0

//plotshape(enableMA? d1c : na, title='MA Confluence 1', location=location.top, style=shape.square, size=size.tiny, color=dl1)
//plotshape(enableMA? d2c : na, title='MA Confluence 2', location=location.bottom, style=shape.square, size=size.tiny, color=color.new(color.green, 20))

// Establish conditions
bull = MA_speed1 > MA_speed1[1] and MA_speed2 > MA_speed2[1] and MA_speed3 > MA_speed3[1] ? true : false
bear = MA_speed1 < MA_speed1[1] and MA_speed2 < MA_speed2[1] and MA_speed3 < MA_speed3[1] ? true : false

bull2 = dp1 > dp1[1] and dp2 > dp2[1] and dp3 > dp3[1] ? true : false
bear2 = dp1 < dp1[1] and dp2 < dp2[1] and dp3 < dp1[1] ? true : false


//plotshape(enableMA? bear : na, title='MA Confluence 1', location=location.top, style=shape.square, size=size.tiny, color=color.new(color.red, 20))
//plotshape(enableMA? bull : na, title='MA Confluence 2', location=location.bottom, style=shape.square, size=size.tiny, color=color.new(color.green, 20))

num1 = numa == "Average" ? 3 : 1
macomp = (MA_speed1 + MA_speed2 + MA_speed3) / num1
compcolor = bull ? color.green : bear ? color.red : color.gray

num2 = numb == "Average" ? 3 : 1
dcomp = (dp1 + dp2 + dp3) / num2
dcolor = bull2 ? color.lime : bear2 ? color.fuchsia : color.white

// Velocity Clusters and Distribution

atob = math.abs(MA_speed1 - MA_speed2)
atoc = math.abs(MA_speed1 - MA_speed3)
btoc = math.abs(MA_speed2 - MA_speed3)

cd1 = math.abs(atob / MA_speed2) * 100
cd2 = math.abs(atoc / MA_speed3) * 100
cd3 = math.abs(btoc / MA_speed3) * 100

cluster = cd1 < clust and cd2 < clust and cd3 < clust ? true : false
distribution = cd1 > dist/(malength2/malength1) and cd2 > dist and cd3 > dist/(malength3/malength2) ? true : false

lbc = ta.barssince(cluster[1])
lbd = ta.barssince(distribution[1])

lookbackc = lbc > cdl ? true : false
lookbackd = lbd > cdl ? true : false

locdu = MA_speed1 > 0 and MA_speed2 > 0 and bull ? true : false
locdd = MA_speed1 < 0 and MA_speed2 < 0 and bear ? true : false

loccu = (MA_speed1 + MA_speed2 > 0) ? true : false
loccd = (MA_speed1 + MA_speed2 < 0) ? true : false

sbu = 50000*MA_speed3 > ex  ? true : false
sbe = 50000*MA_speed3 < -1 * ex ? true : false 

buc = MA_speed2[1] <= MA_speed3[1] and MA_speed2 >= MA_speed3 ? true : false 
bec = MA_speed2[1] >= MA_speed3[1] and MA_speed2 <= MA_speed3 ? true : false

plotshape(enableMA and enablecd and cluster and lookbackc and loccu and not(sbu)? 100 : na, title='MA Cluster Short', location=location.top, style=shape.labeldown, size=size.tiny, color=color.new(color.red, 20), text="Cluster", textcolor=color.white)
plotshape(enableMA and enablecd and cluster and lookbackc and loccd and not(sbe)? 100 : na, title='MA Cluster Long', location=location.bottom, style=shape.labelup, size=size.tiny, color=color.new(color.green, 20), text="Cluster", textcolor=color.white)

plotshape(enableMA and enablecd and distribution and lookbackd and locdd ? -100 : na, title='MA Distribution Long', location=location.bottom, style=shape.labelup, size=size.tiny, color=color.new(color.green, 20), text="Dist", textcolor=color.white)
plotshape(enableMA and enablecd and distribution and lookbackd and locdu ? -100 : na, title='MA Distribution Short', location=location.top, style=shape.labeldown, size=size.tiny, color=color.new(color.red, 20), text="Dist", textcolor=color.white)

plotshape(enableMA and enablecd and bec and sbu? 100 : na, title='MA Cross Short', location=location.top, style=shape.labeldown, size=size.tiny, color=color.new(color.red, 20), text="Cross", textcolor=color.white)
plotshape(enableMA and enablecd and buc and sbe? 100 : na, title='MA Cross Long', location=location.bottom, style=shape.labelup, size=size.tiny, color=color.new(color.green, 20), text="Cross", textcolor=color.white)



// Plot output

plot(enableMA1 and not(enablecomp) ? 50000*MA_speed1*scale : na, color=color.new(Pcolor1, 0), linewidth=1)
plot(enableMA2 and not(enablecomp) ? 50000*MA_speed2*scale : na, color=color.new(Pcolor2, 0), linewidth=1)
plot(enableMA3 and not(enablecomp) ? 50000*MA_speed3*scale : na, color=color.new(Pcolor3, 0), linewidth=1)

plot(enableMA and enablecomp ? 50000*macomp*scale : na, title="Composite MA", color=color.new(compcolor, 0))

plot(enabled1 and not(enabledp) ? dp1 * scale * dm * 10 : na, color=color.new(Pcolor4, 0), linewidth=1, style=plot.style_histogram)
plot(enabled2 and not(enabledp) ? dp2 * scale * dm * 10 : na, color=color.new(Pcolor5, 0), linewidth=1, style=plot.style_histogram)
plot(enabled3 and not(enabledp) ? dp3 * scale * dm * 10 : na, color=color.new(Pcolor6, 0), linewidth=1, style=plot.style_histogram)

plot(enableMA and enabledp ? dcomp*scale*dm*10 : na, title="Composite MA", color=color.new(dcolor, 0), style=plot.style_histogram)

hline(enableMA ? 0 : na, title="Zero Point", color=color.gray, linestyle=hline.style_dashed)
hline(enableMA ? ex * scale : na, title="Strong Bull", color=color.green, linestyle=hline.style_dashed)
hline(enableMA ? -ex * scale : na, title="Strong Bear", color=color.red, linestyle=hline.style_dashed)

// VFI

enableV = input.bool(false, title="════ Enable VFI ════", group="VFI")

length = input(130, title='VFI length')
coef = input(0.2)
vcoef = input(2.5, title='Max. vol. cutoff')
vscale = input.float(1, title="VFI Scale")
signalLength = input(5)
smoothVFI = input(false)

ma(x, y) =>
    sma_1 = ta.sma(x, y)
    smoothVFI ? sma_1 : x

typical = hlc3
inter = math.log(typical) - math.log(typical[1])
vinter = ta.stdev(inter, 30)
cutoff = coef * vinter * close
vave = ta.sma(volume, length)[1]
vmax = vave * vcoef
vc = volume < vmax ? volume : vmax  //min( volume, vmax )
mf = typical - typical[1]
iff_1 = mf < -cutoff ? -vc : 0
vcp = mf > cutoff ? vc : iff_1

vfi = ma(math.sum(vcp, length) / vave, 3) * vscale
vfima = ta.ema(vfi, signalLength)
d = vfi - vfima

showHisto = input(false)
plot(showHisto and enableV ? d : na, style=plot.style_histogram, color=color.new(#c6cff2, 50), linewidth=1)
plot(enableV ? vfima : na, title='EMA of vfi', color=color.new(#0040ff, 0))
plot(enableV ? vfi : na, title='vfi', color=color.new(#af7a4c, 0), linewidth=1)

