Papercuts Dynamic EMA - Relative Parameter Function
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © joelly3d

//@version=4
study("Papercuts Dynamic EMA - Relative Parameter Function", overlay=true)
//The goal of this is to link two parameters of different known low and high values so one affects the other.
//In this case, I want to link Relative Volume to the length of an MA, so it responds faster in times of high volume.
//As an animator I am used to linking values in this way with Maya using a set driven key, took some work to figure it out in pine.

rvolMin = input(0.75, title="RVOL Minimum", tooltip="This value sets the Relative Volume minimum cutoff amount for trading since low volume leads to manipulation and trends become useless.")
rvolMax = input(1.5, title="RVOL Maximum", tooltip="This value sets a limit of Relative Volume maximum cutoff for the fast limit of ema lengths to be hit.  This will help protect profit in rapid moves.")
rvolLen = input(50, title="RVOL: Relative Volume Length")

lengthMult = input(5, title="MA: Length High Volume Speed Multiplier", tooltip="How fast do you want the fast MA?!")
stdEMA = input(50, title="MA: Standard Target Length")

colorBull = input(defval=#2196F3, type=input.color, title="Bullish Color", inline="clr1") //Light Blue
colorBear = input(defval= #C1B82F, type=input.color, title="Bearish Color", inline="clr1") //yellow

//get relative volume
averageVolume = hma(volume, rvolLen)
relativeVolume = hma(volume / averageVolume, rvolLen)

//Relative values...
//aka linear interpolation
//aka rescale values
f_relativeVal(_source, in_bot, in_top, out_bot, out_top) =>
    // float _source: input signal
    // float in_bot   : minimum range of input signal.
    // float in_top   : maximum range of input signal.
    // float out_bot   : minimum range of output signal.
    // float out_top   : maximum range of output signal.
    clampSrc = _source > in_top ? in_top : _source < in_bot ? in_bot : _source //claps source to create a controlled range
    //relInput = (clampSrc - in_bot) / (in_top - in_bot) * 100
    inDiffIncrement = (in_top - in_bot) 
    outDiffIncrement = (out_top - out_bot) 
    out_bot + (clampSrc - in_bot) * outDiffIncrement / inDiffIncrement // rescale input range to output range


//Dynamic Ema function that allows for variable as length
Ema_f(src,p) =>
    ema = 0.0
    sf = 2/(p+1)
    ema := nz(ema[1] + sf*(src - ema[1]),src)


theEMASlow = Ema_f(close, stdEMA)
slowplot = plot(theEMASlow, style=plot.style_circles, color=theEMASlow > theEMASlow[1] ? color.new(colorBull,60) : color.new(colorBear,60), linewidth=1)

theEMAFast = Ema_f(close, stdEMA / lengthMult)
fastplot = plot(theEMAFast, style=plot.style_circles, color=theEMAFast > theEMAFast[1] ? color.new(colorBull,60) : color.new(colorBear,60), linewidth=1)

theEMADynamic = Ema_f(close, f_relativeVal(relativeVolume, rvolMin, rvolMax, stdEMA, stdEMA / lengthMult))
theColor= theEMADynamic > theEMADynamic[1] ? colorBull : colorBear
fill(slowplot, fastplot, color.new(theColor, 90))
plot(theEMADynamic, style=plot.style_line, color=theColor, linewidth=3)

//info_panel = label.new(x=timenow, y=close, text="ema: "+tostring(theEMADynamic)+"\n rvol: "+tostring(relativeVolume), xloc=xloc.bar_time, yloc=yloc.price,
//     color=color.white, style=label.style_label_left, textcolor=color.black, size=size.normal)
//label.delete(info_panel[1])

barcolor(theColor)