Moving Average - fade when crossed [cajole]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// A moving average that fades away (wanes) when crossed, then grows again (waxes) afterwards.
// © cajole

// v34 - published

//@version=5
indicator('Moving Average - fade when crossed [cajole]', shorttitle= "Fade MA [cj]", overlay=true)

// INPUTS
src     = input(close, "Source", inline='MA') 
maType  = input.string("EMA", "", options=["SMA", "EMA", "SMMA (RMA)", "WMA", "VWMA"], inline='MA')
waneRate = input.float(50, 'Fade rate [alpha%/bar]', tooltip='How quickly should the line fade when crossed repeatedly?')
waxRate  = input.float(5 ,  'Wax rate [alpha%/bar]', tooltip='How quickly should the MA become visible again?')
ma_length = input.int(13, "Length", minval=1, inline='MA')
ma_color  = input(#fffd74, "", inline="MA")

waxwane(ma, prev_transp) => 
    crossed = (ma < high and ma > low)   // cross bar/wick
     or (ma[1] > high[1] and ma < low )  // gap up 
     or (ma[1] <  low[1] and ma > high)  // gap down
    new_transp = crossed ? math.min(100, nz(prev_transp) + waneRate)
                         : math.max(  0, nz(prev_transp) -  waxRate)

ma(source, length, type) =>
    type == "SMA" ? ta.sma(source, length) :
     type == "EMA" ? ta.ema(source, length) :
     type == "WMA" ? ta.wma(source, length) :
     type == "VWMA" ? ta.vwma(source, length) :
     na

ma0 = ma(src, ma_length, maType)
transp = 0.
transp := waxwane(ma0, transp[1])
plot(ma0, color = color.new(ma_color, transp), title="Fade-MA")

// Text label on the fast EMA (last completed bar). 
labelThreshold = input.int(90, minval=1, title="Add label if transp. <", inline= "label",  
      tooltip='For labels at right only.')
labelOffset = input.int(10, minval=1, title="with offset", inline= "label",   
      tooltip='For labels at right only.')
      
vline(BarIndex, Color, LineStyle, LineWidth) => 
    line.new(BarIndex, low, BarIndex, high, xloc.bar_index, extend.both, Color, LineStyle, LineWidth) 
sessionClosed = barstate.islast ? (timenow > time_close ? 1 : 0) : 1
lastcEMA =      sessionClosed ? ma0      : ma0[1]
this_bar_xloc = sessionClosed ? bar_index   : bar_index - 1
this_bar_yloc = lastcEMA > high      ? yloc.abovebar : yloc.belowbar
emaLabStr0 = str.tostring(math.round_to_mintick(lastcEMA)) + ' (' + str.tostring(ma_length) + ') '
emaLabStr1  = lastcEMA > high      ? emaLabStr0 + "\n↓" :  "↑\n" + emaLabStr0
var emaLabel = label.new(bar_index, na, na, xloc.bar_index, yloc.abovebar, 
     color(na), label.style_none, ma_color, size.normal, text.align_center)
var fEMAline = line.new(na, na, na, na)
line.delete(fEMAline), label.delete(emaLabel)
if transp[0] < labelThreshold
    label.set_yloc(emaLabel, this_bar_yloc), label.set_x(   emaLabel, this_bar_xloc)
    emaLabel := label.new(bar_index + labelOffset,
             lastcEMA,style=label.style_none, textcolor=color.new(ma_color, 20), 
             textalign=text.align_right, text=str.tostring(emaLabStr0), xloc=xloc.bar_index)
    fEMAline := line.new(this_bar_xloc, lastcEMA, this_bar_xloc + labelOffset, lastcEMA,
         color=ma_color, style=line.style_dotted, extend=extend.right, width=1)
