Distance From Moving Average
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Botnet101

//@version=5
indicator("Distance From Moving Average", overlay=false, precision=2)

// Inputs
//{
src              = input.source(defval=close       , title="Source")
length           = input.int   (defval=20          , title="Length")
calculation_type = input.string(defval="Percentage", title="Calculation Type", options=["Spread", "Percentage"])
ma_type          = input.string(defval="EMA"       , title="MA Type"         , options=["EMA", "SMA", "WMA", "VWMA", "HMA"])

show_LL          = input.bool  (defval=true        , title="Lowest Low"                       , group='Highest High/Lowest Low', inline="High/Low")
show_HH          = input.bool  (defval=true        , title="Highest High"                     , group='Highest High/Lowest Low', inline="High/Low")

show_past_low    = input.bool  (defval=true        , title='Lows'                             , group='Historic Highs/Lows'    , inline="High/Low")
show_past_high   = input.bool  (defval=true        , title='Highs'                            , group='Historic Highs/Lows'    , inline="High/Low")
_lookback        = input.int   (defval=50          , title='Lookback Length', step=1, minval=0, group='Historic Highs/Lows'                       )
label_text_colour = input.color(defval=color.white , title="Text Colour"                      , group='Historic Highs/Lows'                       )

show_labels     = input.bool  (defval=true         , title='show Labels'                                                                 , group='Current values Label Settings')
label_size      = input.string(defval='Normal'     , title='Label Size'    , options=["Auto", "Tiny", "Small", "Normal", "Large", "Huge"], group='Current values Label Settings')
label_position  = input.int   (defval=5            , title='Label Position', step=5                                                      , group='Current values Label Settings')
//}


// Functions
//{
GetMA = switch ma_type
    "EMA"  => ta.ema (src, length)
    "SMA"  => ta.sma (src, length)
    "WMA"  => ta.wma (src, length)
    "VWMA" => ta.vwma(src, length)
    "HMA"  => ta.hma (src, length)

GetSeries = switch calculation_type
    "Spread"     => close - GetMA
    "Percentage" => 100 * (close - GetMA) / GetMA


GetLowestLow () =>
    if (show_LL)
        var float lowest_low = 0.0
        if (GetSeries < lowest_low)
            lowest_low := GetSeries
            
        lowest_low

GetHighestHigh () =>
    if (show_HH)
        var float highest_high = 0.0
        if (GetSeries > highest_high)
            highest_high := GetSeries
            
        highest_high    
    

// Calculate and Show historic Highs and Lows
PlotHistoricHighLows (_series) =>
    _pl       = ta.pivotlow (_series, _lookback, _lookback)
    _ph       = ta.pivothigh(_series, _lookback, _lookback)
    
    _low  = math.round (_pl, 2)
    _high = math.round (_ph, 2)
    
    if not na(_low) and show_past_low
        label.new(x=bar_index[_lookback], y=_low , text=str.tostring(_low , format.percent), style=label.style_label_up  , color=color.new(color.black, 100), textcolor=label_text_colour)
        
    if not na(_high) and show_past_high
        label.new(x=bar_index[_lookback], y=_high, text=str.tostring(_high, format.percent), style=label.style_label_down, color=color.new(color.black, 100), textcolor=label_text_colour)
        
  
  
GetLabelSize = switch label_size
    "Auto"   => size.auto
    "Tiny"   => size.tiny
    "Small"  => size.small
    "Normal" => size.normal
    "Large"  => size.large
    "Huge"   => size.huge
    
SetLabel(show_label, textValue, percentage, col) =>
    if not na(percentage) and barstate.islast and show_label
        dt   = time - time[1]
        newX = time + label_position * dt

        string percentageString = str.tostring(percentage, format.percent)
        string textLabel = textValue != '' ? textValue + ' (' + percentageString + ')' : percentageString

        label = label.new(x=newX, y=percentage, xloc=xloc.bar_time, style=label.style_label_left)

        label.set_color    (id=label, color=color.new(col, 0))
        label.set_text     (id=label, text=textLabel)
        label.set_textcolor(id=label, textcolor=color.white)
        label.set_textalign(id=label, textalign=text.align_right)
        label.set_size     (id=label, size=GetLabelSize)
        label.set_style    (id=label, style=label.style_label_left)

        label.delete(label[1])
//}



lowest_low   = GetLowestLow  ()
highest_high = GetHighestHigh()


PlotHistoricHighLows (GetSeries)

// Plots
//{
plot(GetSeries   , title="Distance"    , color=color.aqua, style=plot.style_columns)

plot(lowest_low  , title="Highest High", color=color.red , style=plot.style_line   )
plot(highest_high, title="Lowest Low"  , color=color.red , style=plot.style_line   )
//}

if (show_labels)
    SetLabel(true, 'LL'  , math.round(lowest_low  , 2), color.red)
    SetLabel(true, 'HH'  , math.round(highest_high, 2), color.red)
    SetLabel(true, 'Dist', math.round(GetSeries   , 2), color.blue)