Momentum and Acceleration
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
//Credit: This script utilizes the "Color Gradient Framework" tutorial by LucF (PineCoders) to create gradient visuals, which are also customizable for the user.
//@version=5

//INPUT
indicator(title='Momentum and Acceleration', 
     shorttitle='Momentum & Acceleration', 
     overlay=false, timeframe="", timeframe_gaps=true)

source = input.source(close, 'Source', inline='Source')
len = input.int(10, minval=1, title='Length', inline='Source')
choice = input.string(title='Modifier', defval='Source Only', options=['Source * Volume', 'Volume Only', 'Source Only'], inline='0')
scaleosc = input.bool(true, 'Divide calculation by length? (Only affects scaling, 1st deriv is equivalent to built-in momentum indicator when unchecked, unchecked may help seeing acceleration easier)', inline='10')

//CALCS
dp = choice == 'Source * Volume' ? source * volume - source[len] * volume[len] : choice == 'Volume Only' ? volume - volume[len] : choice == 'Source Only' ? source - source[len] : na
dt = scaleosc == true ? len : 1
mom = dp / dt
dmom = mom - mom[len]
acc = dmom / dt

//PLOT INPUTS
show_1d = input.bool(true, 'Show?', inline='1', group='1st Derivative - Momentum')
grow1 = input.color(color.green, 'Grow', group='1st Derivative - Momentum', inline='2')
fall1 = input.color(color.red, 'Fall', group='1st Derivative - Momentum', inline='2')
bullfill = input.color(color.lime, 'Bull Fill', group='1st Derivative - Momentum', inline='2')
bearfill = input.color(color.fuchsia, 'Bear Fill', group='1st Derivative - Momentum', inline='2')
show_2d = input.bool(true, 'Show?', inline='3', group='2nd Derivative - Acceleration')
grow2 = input.color(color.blue, 'Grow', group='2nd Derivative - Acceleration', inline='4')
fall2 = input.color(color.orange, 'Fall', group='2nd Derivative - Acceleration', inline='4')
bullfill2 = input.color(color.aqua, 'Bull Fill', group='2nd Derivative - Acceleration', inline='4')
bearfill2 = input.color(color.yellow, 'Bear Fill', group='2nd Derivative - Acceleration', inline='4')

//GRADIENT
gradmult = input.float(1, title='Gradient \'Intensity\' (Higher = more intense)', step=0.01, group='Plot Color and Label Settings', inline='6')
gradconst = input.int(1, title='Gradient Constant (Higher = less intense)', minval=-100, maxval=100, group='Plot Color and Label Settings', inline='7')
gradlimit = input.int(99, title='Transparency Limit', minval=0, maxval=100, group='Plot Color and Label Settings', inline='8')
colorgrad = input.bool(defval=true, title='Fill Gradient?', group='Plot Color and Label Settings', inline='8')

// —————————————————————————————————————————
// ————— Advance/Decline Gradient (Credit: LucF from PineCoders)
// ————————————————————————————————————————— 
// ————— Function returning one of the bull/bear colors in a transparency proportional to the current qty of advances/declines 
//       relative to the historical max qty of adv/dec for this `_source`.

f_c_gradientAdvDec(_source, _center, _c_bear, _c_bull) =>
    // float _source: input signal.
    // float _center: centerline used to determine if signal is bull/bear.
    // color _c_bear: most bearish color.
    // color _c_bull: most bullish color.
    // Dependency: `f_colorNew()`
    var float _maxAdvDec = 0.
    var float _qtyAdvDec = 0.
    bool _xUp = ta.crossover(_source, _center)
    bool _xDn = ta.crossunder(_source, _center)
    float _chg = ta.change(_source)
    bool _up = _chg > 0
    bool _dn = _chg < 0
    bool _srcBull = _source > _center
    bool _srcBear = _source < _center
    _qtyAdvDec := _srcBull ? _xUp ? 1 : _up ? _qtyAdvDec + 1 : _dn ? math.max(1, _qtyAdvDec - 1) : _qtyAdvDec : _srcBear ? _xDn ? 1 : _dn ? _qtyAdvDec + 1 : _up ? math.max(1, _qtyAdvDec - 1) : _qtyAdvDec : _qtyAdvDec
    // Keep track of max qty of advances/declines.
    _maxAdvDec := math.max(_maxAdvDec, _qtyAdvDec)
    // Calculate transparency from the current qty of advances/declines relative to the historical max qty of adv/dec for this `_source`.
    float _transp = 100 - _qtyAdvDec * 100 / _maxAdvDec * gradmult + gradconst
    _transp2 = _transp > gradlimit ? gradlimit : _transp
    var color _return = na
    _return := _srcBull ? color.new(_c_bull, _transp2) : _srcBear ? color.new(_c_bear, _transp2) : _return
    _return

//PLOTS
p0 = hline(0, title='Zero', color=color.gray, linestyle=hline.style_dashed)
p1 = plot(show_1d ? mom : na, title='1st Deriv', linewidth=2, color=mom > mom[1] ? grow1 : fall1, style=plot.style_line)
p2 = plot(show_2d ? acc : na, title='2nd Deriv', linewidth=2, color=acc > acc[1] ? grow2 : fall2, style=plot.style_line)
color c_1 = f_c_gradientAdvDec(mom, 0, bearfill, bullfill)
color c_2 = f_c_gradientAdvDec(acc, 0, bearfill2, bullfill2)
fill(p1, plot(0), colorgrad == true ? c_1 : color.new(color.white, 100), title='Momentum Fill')
fill(plot(0), p2, colorgrad == true ? c_2 : color.new(color.white, 100), title='Acceleration Fill')