Dynamic Highest Lowest Moving Average
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © EsIstTurnt

//@version=5
indicator("Dynamic Highest Lowest Moving Average",shorttitle='DHLMA',overlay=true)


import TradingView/ta/4 as m

/////////////Beginning, Get Inputs
string high_oscillator         = input.string("Decline", "HH's Length Curve Shape (< > <> ><)", options = ["Incline", "Decline", "Peak", "Trough"])
string low_oscillator          = input.string("Decline", "LL's Length Curve Shape (< > <> ><)", options = ["Incline", "Decline", "Peak", "Trough"])
string curve                   = input.string("LRC", "Output Average Type ", options = ["EMA","WMA","LRC","DEMA","TEMA","TRIMA","FRAMA","NONE"])
var float mult                 = input.float (0.236,'Length Multiplier')
var bool avg_include_price     = input.bool(false,'Include Price in the Averaging of the Highest/Lowest ')
var int  included_price_offset = input.int(0,'Offset of the Price to Include in Averaging')
var int smoothlen              = input.int(12,'Smooth Length')
var int ratiolen               = input.int(12,'RSI of Ratio Length')
var int min                    = input.int(16 ,'Minimum length              ',maxval = 16,minval = 4)
var int maxHigh                = input.int(128,'Maximum HH length              ',maxval = 1024,minval = 32)
var int maxLow                 = input.int(128,'Maximum LL length              ',maxval = 1024,minval = 32)
var int coefHigh               = input.int(40)
var int coefLow                = input.int(40)
var int hlen                   = maxHigh
var int llen                   = maxLow

//Logic Selection,         (<)                               (>)                           (<>)                          (><) 
x1  =high_oscillator == "Incline"? 1  :high_oscillator == "Decline"?20:high_oscillator == "Peak"?1 :high_oscillator == "Trough"?10:na
x2  =high_oscillator == "Incline"? 2  :high_oscillator == "Decline"?19:high_oscillator == "Peak"?2 :high_oscillator == "Trough"?9 :na
x3  =high_oscillator == "Incline"? 3  :high_oscillator == "Decline"?18:high_oscillator == "Peak"?3 :high_oscillator == "Trough"?8 :na
x4  =high_oscillator == "Incline"? 4  :high_oscillator == "Decline"?17:high_oscillator == "Peak"?4 :high_oscillator == "Trough"?7 :na
x5  =high_oscillator == "Incline"? 5  :high_oscillator == "Decline"?16:high_oscillator == "Peak"?5 :high_oscillator == "Trough"?6 :na
x6  =high_oscillator == "Incline"? 6  :high_oscillator == "Decline"?15:high_oscillator == "Peak"?6 :high_oscillator == "Trough"?5 :na
x7  =high_oscillator == "Incline"? 7  :high_oscillator == "Decline"?14:high_oscillator == "Peak"?7 :high_oscillator == "Trough"?4 :na
x8  =high_oscillator == "Incline"? 8  :high_oscillator == "Decline"?13:high_oscillator == "Peak"?8 :high_oscillator == "Trough"?3 :na
x9  =high_oscillator == "Incline"? 9  :high_oscillator == "Decline"?12:high_oscillator == "Peak"?9 :high_oscillator == "Trough"?2 :na
x10 =high_oscillator == "Incline"? 10 :high_oscillator == "Decline"?11:high_oscillator == "Peak"?10:high_oscillator == "Trough"?1 :na
x11 =high_oscillator == "Incline"? 11 :high_oscillator == "Decline"?10:high_oscillator == "Peak"?10:high_oscillator == "Trough"?1 :na
x12 =high_oscillator == "Incline"? 12 :high_oscillator == "Decline"? 9:high_oscillator == "Peak"?9 :high_oscillator == "Trough"?2 :na
x13 =high_oscillator == "Incline"? 13 :high_oscillator == "Decline"? 8:high_oscillator == "Peak"?8 :high_oscillator == "Trough"?3 :na
x14 =high_oscillator == "Incline"? 14 :high_oscillator == "Decline"? 7:high_oscillator == "Peak"?7 :high_oscillator == "Trough"?4 :na
x15 =high_oscillator == "Incline"? 15 :high_oscillator == "Decline"? 6:high_oscillator == "Peak"?6 :high_oscillator == "Trough"?5 :na
x16 =high_oscillator == "Incline"? 16 :high_oscillator == "Decline"? 5:high_oscillator == "Peak"?5 :high_oscillator == "Trough"?6 :na
x17 =high_oscillator == "Incline"? 17 :high_oscillator == "Decline"? 4:high_oscillator == "Peak"?4 :high_oscillator == "Trough"?7 :na
x18 =high_oscillator == "Incline"? 18 :high_oscillator == "Decline"? 3:high_oscillator == "Peak"?3 :high_oscillator == "Trough"?8 :na
x19 =high_oscillator == "Incline"? 19 :high_oscillator == "Decline"? 2:high_oscillator == "Peak"?2 :high_oscillator == "Trough"?9 :na
x20 =high_oscillator == "Incline"? 20 :high_oscillator == "Decline"? 1:high_oscillator == "Peak"?1 :high_oscillator == "Trough"?10:na

y1  =low_oscillator  == "Incline"? 1  :low_oscillator  == "Decline"?20:low_oscillator  == "Peak"?1 :low_oscillator  == "Trough"?10:na
y2  =low_oscillator  == "Incline"? 2  :low_oscillator  == "Decline"?19:low_oscillator  == "Peak"?2 :low_oscillator  == "Trough"?9 :na
y3  =low_oscillator  == "Incline"? 3  :low_oscillator  == "Decline"?18:low_oscillator  == "Peak"?3 :low_oscillator  == "Trough"?8 :na
y4  =low_oscillator  == "Incline"? 4  :low_oscillator  == "Decline"?17:low_oscillator  == "Peak"?4 :low_oscillator  == "Trough"?7 :na
y5  =low_oscillator  == "Incline"? 5  :low_oscillator  == "Decline"?16:low_oscillator  == "Peak"?5 :low_oscillator  == "Trough"?6 :na
y6  =low_oscillator  == "Incline"? 6  :low_oscillator  == "Decline"?15:low_oscillator  == "Peak"?6 :low_oscillator  == "Trough"?5 :na
y7  =low_oscillator  == "Incline"? 7  :low_oscillator  == "Decline"?14:low_oscillator  == "Peak"?7 :low_oscillator  == "Trough"?4 :na
y8  =low_oscillator  == "Incline"? 8  :low_oscillator  == "Decline"?13:low_oscillator  == "Peak"?8 :low_oscillator  == "Trough"?3 :na
y9  =low_oscillator  == "Incline"? 9  :low_oscillator  == "Decline"?12:low_oscillator  == "Peak"?9 :low_oscillator  == "Trough"?2 :na
y10 =low_oscillator  == "Incline"? 10 :low_oscillator  == "Decline"?11:low_oscillator  == "Peak"?10:low_oscillator  == "Trough"?1 :na
y11 =low_oscillator  == "Incline"? 11 :low_oscillator  == "Decline"?10:low_oscillator  == "Peak"?10:low_oscillator  == "Trough"?1 :na
y12 =low_oscillator  == "Incline"? 12 :low_oscillator  == "Decline"? 9:low_oscillator  == "Peak"?9 :low_oscillator  == "Trough"?2 :na
y13 =low_oscillator  == "Incline"? 13 :low_oscillator  == "Decline"? 8:low_oscillator  == "Peak"?8 :low_oscillator  == "Trough"?3 :na
y14 =low_oscillator  == "Incline"? 14 :low_oscillator  == "Decline"? 7:low_oscillator  == "Peak"?7 :low_oscillator  == "Trough"?4 :na
y15 =low_oscillator  == "Incline"? 15 :low_oscillator  == "Decline"? 6:low_oscillator  == "Peak"?6 :low_oscillator  == "Trough"?5 :na
y16 =low_oscillator  == "Incline"? 16 :low_oscillator  == "Decline"? 5:low_oscillator  == "Peak"?5 :low_oscillator  == "Trough"?6 :na
y17 =low_oscillator  == "Incline"? 17 :low_oscillator  == "Decline"? 4:low_oscillator  == "Peak"?4 :low_oscillator  == "Trough"?7 :na
y18 =low_oscillator  == "Incline"? 18 :low_oscillator  == "Decline"? 3:low_oscillator  == "Peak"?3 :low_oscillator  == "Trough"?8 :na
y19 =low_oscillator  == "Incline"? 19 :low_oscillator  == "Decline"? 2:low_oscillator  == "Peak"?2 :low_oscillator  == "Trough"?9 :na
y20 =low_oscillator  == "Incline"? 20 :low_oscillator  == "Decline"? 1:low_oscillator  == "Peak"?1 :low_oscillator  == "Trough"?10:na
//Get Distance from current price to highest high and lowest low, using the maximum length input 
difh=ta.highest(high,maxHigh) - close
difl=close - ta.lowest(low,maxLow)
//Then get the RSI value of the the ratio for each
ratio1=ta.rsi(difh/difl,ratiolen)
ratio2=ta.rsi(difl/difh,ratiolen)

//Get the difference of the max high/low lengths and the minimum length, divide by the coefficient to get how far apart each step will be
rangeh=(maxHigh-min) / coefHigh
rangel=(maxLow-min)  / coefLow 
// Set the length variables according to the value of the ratios. From the Maximum subtract the c
hlen:=math.round(math.max(ratio2<=30?min
  :ratio2<=32?maxHigh-((x1 /mult)*rangeh)
  :ratio2<=34?maxHigh-((x2 /mult)*rangeh)
  :ratio2<=36?maxHigh-((x3 /mult)*rangeh)
  :ratio2<=38?maxHigh-((x4 /mult)*rangeh)
  :ratio2<=40?maxHigh-((x5 /mult)*rangeh)
  :ratio2<=42?maxHigh-((x6 /mult)*rangeh)
  :ratio2<=44?maxHigh-((x7 /mult)*rangeh)
  :ratio2<=46?maxHigh-((x8 /mult)*rangeh)
  :ratio2<=48?maxHigh-((x9 /mult)*rangeh)
  :ratio2<=50?maxHigh-((x10/mult)*rangeh)
  :ratio2<=52?maxHigh-((x11/mult)*rangeh)
  :ratio2<=54?maxHigh-((x12/mult)*rangeh)
  :ratio2<=56?maxHigh-((x13/mult)*rangeh)
  :ratio2<=58?maxHigh-((x14/mult)*rangeh)
  :ratio2<=60?maxHigh-((x15/mult)*rangeh)
  :ratio2<=62?maxHigh-((x16/mult)*rangeh)
  :ratio2<=64?maxHigh-((x17/mult)*rangeh)
  :ratio2<=66?maxHigh-((x18/mult)*rangeh)
  :ratio2<=68?maxHigh-((x19/mult)*rangeh)
  :ratio2<=70?maxHigh-((x20/mult)*rangeh)
  :maxHigh,min))
llen:=math.round(math.max(ratio1<=30?min
  :ratio1<=32?maxLow-((y1 /mult)*rangel)
  :ratio1<=34?maxLow-((y2 /mult)*rangel)
  :ratio1<=36?maxLow-((y3 /mult)*rangel)
  :ratio1<=38?maxLow-((y4 /mult)*rangel)
  :ratio1<=40?maxLow-((y5 /mult)*rangel)
  :ratio1<=42?maxLow-((y6 /mult)*rangel)
  :ratio1<=44?maxLow-((y7 /mult)*rangel)
  :ratio1<=46?maxLow-((y8 /mult)*rangel)
  :ratio1<=48?maxLow-((y9 /mult)*rangel)
  :ratio1<=50?maxLow-((y10/mult)*rangel)
  :ratio1<=52?maxLow-((y11/mult)*rangel)
  :ratio1<=54?maxLow-((y12/mult)*rangel)
  :ratio1<=56?maxLow-((y13/mult)*rangel)
  :ratio1<=58?maxLow-((y14/mult)*rangel)
  :ratio1<=60?maxLow-((y15/mult)*rangel)
  :ratio1<=62?maxLow-((y16/mult)*rangel)
  :ratio1<=64?maxLow-((y17/mult)*rangel)
  :ratio1<=66?maxLow-((y18/mult)*rangel)
  :ratio1<=68?maxLow-((y19/mult)*rangel)
  :ratio1<=70?maxLow-((y20/mult)*rangel)
  :maxLow,min))

//Now, Average the highest high and lowest low using their respective dynamic lengths from above. Then get a SWMA of the LRC of the value. (basically a base level of smoothing) 
hl=avg_include_price?ta.swma(ta.linreg(math.avg(ta.highest(high,hlen),ta.lowest(low,llen),hl2[included_price_offset]),math.round(math.avg(hlen,llen)),0)):ta.swma(ta.linreg(math.avg(ta.highest(high,hlen),ta.lowest(low,llen)),math.round(math.avg(hlen,llen)),0))

////Final Filter using moving averages that allow the use of dynamic lengths
float avg = switch curve
	'LRC'   => ta.ema(ta.linreg  (hl,math.round(math.avg(hlen,llen)),0),smoothlen)
    "EMA"   => ta.ema(m.ema2     (hl,math.round(math.avg(hlen,llen))),smoothlen)
    'WMA'   => ta.ema(ta.wma     (hl,math.round(math.avg(hlen,llen))),smoothlen)
    'DEMA'  => ta.ema(m.dema2    (hl,math.round(math.avg(hlen,llen))),smoothlen)
    'TEMA'  => ta.ema(m.tema2    (hl,math.round(math.avg(hlen,llen))),smoothlen)
    'TRIMA' => ta.ema(m.trima2   (hl,math.round(math.avg(hlen,llen))),smoothlen)
    'FRAMA' => ta.ema(m.frama    (hl,math.round(math.avg(hlen,llen))),smoothlen)
    'NONE'  => ta.ema(hl,smoothlen)
   	// Default used when the three first cases do not match.
	=> ta.ema(ta.linreg(hl,math.round(math.avg(hlen,llen)),0),smoothlen)
//Plot it!
plot(avg)
//plot(hl)

