Standardized MACD Heikin-Ashi Transformed
// This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/
// © QuantiLuxe

//@version=5
indicator("Standardized MACD Heikin-Ashi Transformed", "[Ʌ] - 𝗦𝘁. 𝗠𝗔𝗖𝗗 𝗛-𝗔", false)

type bar
    float o = na
    float h = na
    float l = na
    float c = na

method src(bar b, simple string src) =>
    float x = switch src
        'open'  =>          b.o
        'high'  =>          b.h
        'low'   =>          b.l
        'close' =>          b.c
        'oc2'   => math.avg(b.o, b.c          )
        'hl2'   => math.avg(b.h, b.l          )
        'hlc3'  => math.avg(b.h, b.l, b.c     )
        'ohlc4' => math.avg(b.o, b.h, b.l, b.c)
        'hlcc4' => math.avg(b.h, b.l, b.c, b.c)

    x

method ha(bar b, simple bool p = true) =>
    var bar x = bar.new(       )
    x.c      := b  .src('ohlc4')
    x        := bar.new(
         na(x.o[1]) ? 
             b.src('oc2') : nz(x.src('oc2')[1]),
         math.max(b.h, math.max(x.o, x.c))     ,
         math.min(b.l, math.min(x.o, x.c))     ,
         x.c                                   )

    p ? x : b

f_macd(src, fast, slow) =>

    (ta.ema(src, fast) - ta.ema(src, slow)) / (ta.ema(high - low, slow)) * 100


var string gm = "MACD Settings", var string gu = "UI Options"
src  = input.source(close   , "Source"             ,                                                                                         group = gm)
fast = input.int   (12      , "Fast Length"        ,                                                                                         group = gm)
slow = input.int   (26      , "Slow Length"        ,                                                                                         group = gm)
sigb = input.bool  (true    , "Signal"             ,                                                                           inline = '1', group = gm)
sigs = input.string('close' , "Source"             , ['open',  'high',  'low',  'close',  'hl2',  'hlc3',  'ohlc4',  'hlcc4'], inline = '1', group = gm)
sigl = input.int   (9       , "Length"             ,                                                                           inline = '1', group = gm)
mode = input.string('Hybrid', "Display Mode"       , ['Hybrid',                       'MACD',                    'Histogram'],               group = gu)
revs = input.bool  (true    , ""                   ,                                                                           inline = '0', group = gu)
revt = input.int   (100     , "Reversion Threshold", [100,                                                               150], inline = '0', group = gu)
colb = input.string('None'  , "Bar Coloring"       , ['None', 'MidLine', 'Candles', 'Sig Cross', 'Extremities', 'Reversions'],               group = gu)
hol  = input.bool  (true    , "Hollow Candles"     ,                                                                                         group = gu)


float macd = f_macd (src , fast, slow  )
bar   hm   = bar.new(  
              macd[1]                  ,
              math.max(macd, macd[1])  ,
              math.min(macd, macd[1])  ,
              macd                     ).ha()
              
float sig  = ta .ema(hm.src(sigs), sigl)
float hist = macd - sig


var color colup  = #00bcd4
var color coldn  = #fc1f1f
var color colsig = chart.fg_color

color     h_col  = hist > 0 ?
     (hist > hist[1] ? #8ac3f5a1 : #74a5cfa1) :
     (hist > hist[1] ? #ffa7b6a1 : #d88b98a1)

color haColor = switch
    hm.c > hm.o => colup
    hm.c < hm.o => coldn

hline(0, "Mid Line", chart.fg_color, hline.style_solid)

min = hline(mode != 'Histogram' ? -200 : -100, display = display.none)
ll  = hline(mode != 'Histogram' ? -150 : -75 , display = display.none)
hl  = hline(mode != 'Histogram' ? -100 : -50 , display = display.none)
max = hline(mode != 'Histogram' ? 200  : 100 , display = display.none)
hh  = hline(mode != 'Histogram' ? 150  : 75  , display = display.none)
lh  = hline(mode != 'Histogram' ? 100  : 50  , display = display.none)

fill(lh, hh , #fc1f1f1c)
fill(hh, max, #fc1f1f38)
fill(ll, hl , #00bbd41a)
fill(ll, min, #00bbd436)

plot(mode != 'Histogram' and sigb ? sig  : na, "𝗦𝗶𝗴𝗻𝗮𝗹", colsig                       )
plot(mode != 'MACD'               ? hist : na, "𝗛"    , h_col , 1, plot.style_columns)

plotcandle(mode != 'Histogram' ? hm.o : na,
           mode != 'Histogram' ? hm.h : na,
           mode != 'Histogram' ? hm.l : na,
           mode != 'Histogram' ? hm.c : na,
           "𝗠𝗔𝗖𝗗", hol ? hm.c > hm.o ? na : haColor : haColor, haColor, bordercolor = haColor)

plotshape(mode != 'Histogram' ? revs ? hm.h >  revt and hm.c < hm.o and not (hm.c[1] < hm.o[1]) ? hm.h + 40 : na : na : na, "OB", shape.triangledown, location.absolute, coldn, size = size.tiny)
plotshape(mode != 'Histogram' ? revs ? hm.l < -revt and hm.c > hm.o and not (hm.c[1] > hm.o[1]) ? hm.l - 40 : na : na : na, "OS", shape.triangleup  , location.absolute, colup, size = size.tiny)

color col = switch colb
    'None'        => na
    'MidLine'     => macd > 0    ? colup : coldn
    'Candles'     => hm.c > hm.o ? colup : coldn
    'Sig Cross'   => sig  > hm.c ? coldn : colup
    'Extremities' => macd > revt ? coldn : macd < -revt ? colup : #b3b3b3c2
    'Reversions'  => macd > revt and macd < macd[1] and not (macd[1] < macd[2]) ? coldn : macd < -revt and macd > macd[1] and not (macd[1] > macd[2]) ? colup : #b3b3b3c2

barcolor(col)

//Source Construction For Indicator\Strategy Exports
plot(hm.o           , "open" , editable = false, display = display.none)
plot(hm.h           , "high" , editable = false, display = display.none)
plot(hm.l           , "low"  , editable = false, display = display.none)
plot(hm.c           , "close", editable = false, display = display.none)
plot(hm.src('hl2'  ), "hl2"  , editable = false, display = display.none)
plot(hm.src('hlc3' ), "hlc3" , editable = false, display = display.none)
plot(hm.src('ohlc4'), "ohlc4", editable = false, display = display.none)
plot(hm.src('hlcc4'), "hlcc4", editable = false, display = display.none)