MACD Divergence Fast by RSU
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © rsu9111
//@version=5
indicator("MACD Divergence Fast by RSU",max_bars_back=1000)
fastlinelen=input.int(12,title="Fast line Length")
slowlinelen=input.int(26,title="Slow line Length")
smoothlinelen=input.int(9,title="Smooth line Length")

usdBB=input.bool(false,"Enhanced Mode:Bollinger bands instead of dea lines")

//MACD
diff=ta.ema(close,fastlinelen)-ta.ema(close,slowlinelen)
dea=ta.ema(diff,smoothlinelen)
macd=(diff-dea)
//plot macd Histogram
col_grow_above = #26A69A
col_grow_below = #FFCDD2
col_fall_above = #B2DFDB
col_fall_below = #EF5350
plot(usdBB?na:macd, title="Histogram", style=plot.style_columns, color=(macd>=0 ? (macd[1] < macd ? col_grow_above : col_fall_above) : (macd[1] < macd  ? col_grow_below : col_fall_below) ))


//Bollinger bands instead of dea lines
stdev = ta.stdev(diff,9)
upper = dea + stdev
lower = dea - stdev

ul=plot(usdBB?upper:na,color=color.new(color.gray,70))
ll=plot(usdBB?lower:na,color=color.new(color.gray,70))
fill(ul,ll,color=color.new(color.gray,90))
dl=plot(diff,color=usdBB?diff>upper?color.new(#008000,0):diff<lower?color.new(#FF0000,0):color.blue:color.orange,title="MACD Diff Line",linewidth=2)
fill(dl,ul,color=diff>upper?color.new(#008000,50):na)
fill(dl,ll,color=diff<lower?color.new(#FF0000,50):na)
plot(dea,color=color.purple)
plot(0,color=color.new(color.gray,70),linewidth=2)



//Divergance function
findMACDTopBl(len)=>
    src=diff
    top= ta.pivothigh(src,len, len)
    topc = 0
    topc := top ? len : nz(topc[1]) + 1
    newtop=ta.pivothigh(src,len,0)
    topBL_z=newtop[1] and not newtop and high[1]>high[topc] and src[1]<src[topc] and diff[topc]>dea[topc] and src[topc]>0
    topBL_h=newtop[1] and not newtop and high[1]<high[topc] and src[1]>src[topc] and diff[topc]>dea[topc] and src[topc]>0
    BLTopc=0
    if topBL_z or topBL_h
        BLTopc:=topc
    BLTopc
findMACDBotBl(len)=>
    src=diff
    bot= ta.pivotlow(src,len, len)
    botc = 0
    botc := bot ? len : nz(botc[1]) + 1
    newbot=ta.pivotlow(src,len,0)
    BotBL_z=newbot[1] and not newbot and low[1]<low[botc] and src[1]>src[botc] and diff[botc]<dea[botc] and src[botc]<0 
    BotBL_h=newbot[1] and not newbot and low[1]>low[botc] and src[1]<src[botc] and diff[botc]<dea[botc] and src[botc]<0 
    BLBotc=0
    if BotBL_z or BotBL_h
        BLBotc:=botc
    BLBotc

//Different Len from short to long
//5,20,40,60
mt5result=findMACDTopBl(5)
mt10result=findMACDTopBl(10)
mt20result=findMACDTopBl(20)
mt40result=findMACDTopBl(40)
mt60result=findMACDTopBl(60)
mb5result=findMACDBotBl(5)
mb10result=findMACDBotBl(10)
mb20result=findMACDBotBl(20)
mb40result=findMACDBotBl(40)
mb60result=findMACDBotBl(60)

string notfinished=""
if timenow<time_close
    notfinished:="\nK not end"
    
var toplines = array.new_line()
var toplabels = array.new_label()
var botlines = array.new_line()
var botlabels = array.new_label()


//keep array length within 5
pushArray(array1,obj)=>
    if array.size(array1)>4
        array.shift(array1)
    array.push(array1,obj)


//label and line
if mt5result
    pushArray(toplabels,label.new(x=bar_index,y=diff[1]*1.1,text="m"+notfinished,textcolor=#ffffff,color=color.new(color.red,40),size=size.tiny,style=label.style_label_down))
    pushArray(toplines,line.new(x1=bar_index[1],y1=diff[1]*1.1,x2=bar_index[mt5result],y2=diff[mt5result]*1.1,color=color.red,width=1))
    
if mt10result
    pushArray(toplabels,label.new(x=bar_index,y=diff[1]*1.1,text="m"+notfinished,textcolor=#ffffff,color=color.new(color.red,40),size=size.tiny,style=label.style_label_down))
    pushArray(toplines,line.new(x1=bar_index[1],y1=diff[1]*1.1,x2=bar_index[mt10result],y2=diff[mt10result]*1.1,color=color.red,width=1))
if mt20result
    pushArray(toplabels,label.new(x=bar_index,y=diff[1]*1.1,text="m"+notfinished,textcolor=#ffffff,color=color.new(color.red,40),size=size.tiny,style=label.style_label_down))
    pushArray(toplines,line.new(x1=bar_index[1],y1=diff[1]*1.1,x2=bar_index[mt20result],y2=diff[mt20result]*1.1,color=color.red,width=1))
if mt40result
    pushArray(toplabels,label.new(x=bar_index,y=diff[1]*1.1,text="m"+notfinished,textcolor=#ffffff,color=color.new(color.red,40),size=size.tiny,style=label.style_label_down))
    pushArray(toplines,line.new(x1=bar_index[1],y1=diff[1]*1.1,x2=bar_index[mt40result],y2=diff[mt40result]*1.1,color=color.red,width=1))
if mt60result
    pushArray(toplabels,label.new(x=bar_index,y=diff[1]*1.1,text="m"+notfinished,textcolor=#ffffff,color=color.new(color.red,40),size=size.tiny,style=label.style_label_down))
    pushArray(toplines,line.new(x1=bar_index[1],y1=diff[1]*1.1,x2=bar_index[mt60result],y2=diff[mt60result]*1.1,color=color.red,width=1))

//recolor previous error divergence lines
if array.size(toplines)>=1
    for i=0 to array.size(toplines)-1
        templine=array.get(toplines,i)
        x1=line.get_x1(templine)
        if bar_index-x1-1<4 and diff>diff[bar_index-x1]
            line.set_color(templine,color.new(color.gray,80))
//delete previous error divergance labels
if array.size(toplabels)>=1
    for i=0 to array.size(toplabels)-1
        templabel=array.get(toplabels,i)
        x1=label.get_x(templabel)
        if bar_index-x1-1<4 and diff>diff[bar_index-x1]
            label.delete(templabel)

if mb5result
    pushArray(botlines,line.new(x1=bar_index[1],y1=diff[1]*1.1,x2=bar_index[mb5result],y2=diff[mb5result]*1.1,color=color.green,width=1))
    pushArray(botlabels,label.new(x=bar_index,y=diff[1]*1.1,text="m"+notfinished,textcolor=#ffffff,color=color.new(color.green,40),size=size.tiny,style=label.style_label_up))
if mb10result
    pushArray(botlines,line.new(x1=bar_index[1],y1=diff[1]*1.1,x2=bar_index[mb10result],y2=diff[mb10result]*1.1,color=color.green,width=1))
    pushArray(botlabels,label.new(x=bar_index,y=diff[1]*1.1,text="m"+notfinished,textcolor=#ffffff,color=color.new(color.green,40),size=size.tiny,style=label.style_label_up))
if mb20result
    pushArray(botlines,line.new(x1=bar_index[1],y1=diff[1]*1.1,x2=bar_index[mb20result],y2=diff[mb20result]*1.1,color=color.green,width=1))
    pushArray(botlabels,label.new(x=bar_index,y=diff[1]*1.1,text="m"+notfinished,textcolor=#ffffff,color=color.new(color.green,40),size=size.tiny,style=label.style_label_up))
if mb40result
    pushArray(botlines,line.new(x1=bar_index[1],y1=diff[1]*1.1,x2=bar_index[mb40result],y2=diff[mb40result]*1.1,color=color.green,width=1))
    pushArray(botlabels,label.new(x=bar_index,y=diff[1]*1.1,text="m"+notfinished,textcolor=#ffffff,color=color.new(color.green,40),size=size.tiny,style=label.style_label_up))
if mb60result
    pushArray(botlines,line.new(x1=bar_index[1],y1=diff[1]*1.1,x2=bar_index[mb60result],y2=diff[mb60result]*1.1,color=color.green,width=1))
    pushArray(botlabels,label.new(x=bar_index,y=diff[1]*1.1,text="m"+notfinished,textcolor=#ffffff,color=color.new(color.green,40),size=size.tiny,style=label.style_label_up))

if array.size(botlines)>=1
    for i=0 to array.size(botlines)-1
        templine=array.get(botlines,i)
        x1=line.get_x1(templine)
        if bar_index-x1-1<4 and diff<diff[bar_index-x1]
            line.set_color(templine,color.new(color.gray,80)) 
            //line.delete(templine)
//delete previous error divergance labels
if array.size(botlabels)>=1
    for i=0 to array.size(botlabels)-1
        templabel=array.get(botlabels,i)
        x1=label.get_x(templabel)
        if bar_index-x1-1<4 and diff<diff[bar_index-x1]
            label.delete(templabel)
